home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume42
/
elfdis
/
part02
/
decode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-08
|
3KB
|
137 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <dis.h>
#include <formats.h>
#ifdef __STDC__
static void table_f2(unsigned long instr, unsigned long pc, char *buf);
#endif
/*
* Given 32 bit instruction to decode, and current program counter,
* put a string in "buf" that represents the decoded intstruction.
*
* Hopefully, this is enough separation from the executable image
* format for this to be re-usable if/when Sun switches to another
* format (ELF?).
* $Log: decode.c,v $
* Revision 1.1 1993/12/16 23:45:42 bediger
* Initial revision
*
*/
static char rcsident[] = "@(#) $Id$";
char *
decode_instr(instr, pc, buf, nosynthetic)
unsigned long instr, pc;
char *buf;
int nosynthetic;
{
struct format1 *instr1;
assert(NULL != buf);
buf[0] = '\0'; /* make buffer a zero-length string */
instr1 = (struct format1 *)&instr;
/*
* handle simpler instructions here inside a switch, call
* a function to do lookups for memory load/stores and
* the arithmetic instructions.
* This switch() is essentially table F-1 of
* "The SPARC Architecture Manual: Version 8".
*/
switch (instr1->op) {
case 0:
/* op == 0, UNIMP, Bicc, SETHI, NOP, FBfcc, CBccc: see Table F-2 */
table_f2(instr, pc, buf);
break;
case 1:
/* op == 1, CALL AND LINK */
sprintf(buf, "call 0x%08x", 4 * instr1->disp30 + (unsigned int)pc);
break;
case 2:
/* op == 2, Arithmetic, logical, shift, misc: see Table F-3 */
arithmetic(instr, buf, nosynthetic);
break;
case 3:
/* op == 3, Memory Instructions: see Table F-4 */
memory(instr, buf);
break;
default:
/* bogus */
sprintf(buf, "!bogus instruction: op = %d, bad value",
instr1->op);
}
return buf;
}
/*
* Table F-2 of Appendix F, SPARC Architecture Manual, v8
*/
static void
table_f2(instr, pc, buf)
unsigned long instr, pc;
char *buf;
{
struct format2 *instr2;
assert(NULL != buf);
assert(0 == ((struct format1 *)&instr)->op);
instr2 = (struct format2 *)&instr;
switch (instr2->op2) {
case 0:
strcpy(buf, "!UNIMP");
break;
case 1:
strcpy(buf, "!unimplemented, op2 = 1");
break;
case 2:
/* BRANCH On Integer Condition Codes */
sprintf(buf, "%s 0x%08x", bicc(instr2->rd),
(unsigned int)pc
+ (unsigned int)(4 * (unsigned int)(SIGN_EXT22(instr2->imm22))));
break;
case 3:
strcpy(buf, "!unimplemented, op2 = 3");
break;
case 4:
/* SETHI: nop is a special case of sethi */
if (instr2->rd == 0 && instr2->imm22 == 0)
sprintf(buf, "nop");
else
sprintf(buf, "sethi %%hi(0x%x) %s",
instr2->imm22 << 10, user_mode(instr2->rd));
break;
case 5:
strcpy(buf, "unimplemented, op2 = 5");
break;
case 6:
/* BRANCH On Floating-point Condition Codes */
sprintf(buf, "%s 0x%08x", fbfcc(instr2->rd),
(unsigned int)pc
+ (unsigned int)(4 * (unsigned int)SIGN_EXT22(instr2->imm22)));
break;
case 7:
/* BRANCH On Coprocessor Condition Codes */
sprintf(buf, "%s 0x%08x", cbcc(instr2->rd),
(unsigned int)pc
+ (unsigned int)(4 * (unsigned int)SIGN_EXT22(instr2->imm22)));
break;
default:
/* bogus instruction */
sprintf(buf, "!bogus instruction: op = %d, op2 = %d",
instr2->op, instr2->op2);
break;
}
}