Line 367... |
Line 367... |
|
|
printf("letter_signed(%c): Unknown letter.\n", l);
|
printf("letter_signed(%c): Unknown letter.\n", l);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
/* Simple cache for letter ranges */
|
|
static int range_cache[256] = {0};
|
|
|
/* Number of letters in the individual lettered operand. */
|
/* Number of letters in the individual lettered operand. */
|
int
|
int
|
letter_range(char l)
|
letter_range(char l)
|
{
|
{
|
CONST struct or32_opcode *pinsn;
|
CONST struct or32_opcode *pinsn;
|
char *enc;
|
char *enc;
|
int range = 0;
|
int range = 0;
|
|
|
|
/* Is value cached? */
|
|
if (range = range_cache[(unsigned char)l]) return range;
|
|
|
for(pinsn = or32_opcodes; strlen(pinsn->name); pinsn++)
|
for(pinsn = or32_opcodes; strlen(pinsn->name); pinsn++)
|
{
|
{
|
if (strchr(pinsn->encoding,l))
|
if (strchr(pinsn->encoding,l))
|
{
|
{
|
for (enc = pinsn->encoding; *enc != '\0'; enc++)
|
for (enc = pinsn->encoding; *enc != '\0'; enc++)
|
if ((*enc == '0') && (*(enc+1) == 'x'))
|
if ((*enc == '0') && (*(enc+1) == 'x'))
|
enc += 2;
|
enc += 2;
|
else if (*enc == l)
|
else if (*enc == l)
|
range++;
|
range++;
|
return range;
|
return range_cache[(unsigned char)l] = range;
|
}
|
}
|
}
|
}
|
|
|
printf("\nABORT: letter_range(%c): Never used letter.\n", l);
|
printf("\nABORT: letter_range(%c): Never used letter.\n", l);
|
exit(1);
|
exit(1);
|
}
|
}
|
|
|
/* MM: Returns index of given instruction name. */
|
/* MM: Returns index of given instruction name. */
|
Line 766... |
Line 773... |
unsigned long *a = automata;
|
unsigned long *a = automata;
|
int i;
|
int i;
|
while (!(*a & LEAF_FLAG))
|
while (!(*a & LEAF_FLAG))
|
{
|
{
|
unsigned int first = *a;
|
unsigned int first = *a;
|
debug(9, "%i ", a - automata);
|
//debug(9, "%i ", a - automata);
|
a++;
|
a++;
|
i = (insn >> first) & *a;
|
i = (insn >> first) & *a;
|
a++;
|
a++;
|
if (!*(a + i))
|
if (!*(a + i))
|
{ /* Invalid instruction found? */
|
{ /* Invalid instruction found? */
|
debug(9, "XXX\n", i);
|
//debug(9, "XXX\n", i);
|
return -1;
|
return -1;
|
}
|
}
|
a = automata + *(a + i);
|
a = automata + *(a + i);
|
}
|
}
|
i = *a & ~LEAF_FLAG;
|
i = *a & ~LEAF_FLAG;
|
debug(9, "%i\n", i);
|
//debug(9, "%i\n", i);
|
/* Final check - do we have direct match?
|
/* Final check - do we have direct match?
|
(based on or32_opcodes this should be the only possibility,
|
(based on or32_opcodes this should be the only possibility,
|
but in case of invalid/missing instruction we must perform a check) */
|
but in case of invalid/missing instruction we must perform a check) */
|
if ((ti[i].insn_mask & insn) == ti[i].insn)
|
if ((ti[i].insn_mask & insn) == ti[i].insn)
|
return i;
|
return i;
|
Line 795... |
Line 802... |
|
|
/* Automagically does zero- or sign- extension and also finds correct
|
/* Automagically does zero- or sign- extension and also finds correct
|
sign bit position if sign extension is correct extension. Which extension
|
sign bit position if sign extension is correct extension. Which extension
|
is proper is figured out from letter description. */
|
is proper is figured out from letter description. */
|
|
|
unsigned long
|
static unsigned long
|
extend_imm(unsigned long imm, char l)
|
extend_imm(unsigned long imm, char l)
|
{
|
{
|
unsigned long mask;
|
unsigned long mask;
|
int letter_bits;
|
int letter_bits;
|
|
|
Line 895... |
Line 902... |
return ret;
|
return ret;
|
}
|
}
|
|
|
/* Print register. Used only by print_insn. */
|
/* Print register. Used only by print_insn. */
|
|
|
static void
|
static char *
|
or32_print_register (param_ch, encoding, insn)
|
or32_print_register (dest, param_ch, encoding, insn)
|
|
char *dest;
|
char param_ch;
|
char param_ch;
|
char *encoding;
|
char *encoding;
|
unsigned long insn;
|
unsigned long insn;
|
{
|
{
|
int regnum = or32_extract(param_ch, encoding, insn);
|
int regnum = or32_extract(param_ch, encoding, insn);
|
|
|
sprintf (disassembled, "%sr%d", disassembled, regnum);
|
sprintf (dest, "r%d", regnum);
|
|
while (*dest) dest++;
|
|
return dest;
|
}
|
}
|
|
|
/* Print immediate. Used only by print_insn. */
|
/* Print immediate. Used only by print_insn. */
|
|
|
static void
|
static char *
|
or32_print_immediate (param_ch, encoding, insn)
|
or32_print_immediate (dest, param_ch, encoding, insn)
|
|
char *dest;
|
char param_ch;
|
char param_ch;
|
char *encoding;
|
char *encoding;
|
unsigned long insn;
|
unsigned long insn;
|
{
|
{
|
int imm = or32_extract (param_ch, encoding, insn);
|
int imm = or32_extract (param_ch, encoding, insn);
|
Line 921... |
Line 932... |
imm = extend_imm(imm, param_ch);
|
imm = extend_imm(imm, param_ch);
|
|
|
if (letter_signed(param_ch))
|
if (letter_signed(param_ch))
|
{
|
{
|
if (imm < 0)
|
if (imm < 0)
|
sprintf (disassembled, "%s%d", disassembled, imm);
|
sprintf (dest, "%d", imm);
|
else
|
else
|
sprintf (disassembled, "%s0x%x", disassembled, imm);
|
sprintf (dest, "0x%x", imm);
|
}
|
}
|
else
|
else
|
sprintf (disassembled, "%s%#x", disassembled, imm);
|
sprintf (dest, "%#x", imm);
|
|
while (*dest) dest++;
|
|
return dest;
|
}
|
}
|
|
|
/* Disassemble one instruction from insn to disassemble.
|
/* Disassemble one instruction from insn to disassemble.
|
Return the size of the instruction. */
|
Return the size of the instruction. */
|
|
|
int
|
int
|
disassemble_insn (insn)
|
disassemble_insn (insn)
|
unsigned long insn;
|
unsigned long insn;
|
{
|
{
|
int index;
|
int index;
|
index = insn_decode (insn);
|
return disassemble_index (insn, insn_decode (insn));
|
|
}
|
|
|
|
/* Disassemble one instruction from insn index.
|
|
Return the size of the instruction. */
|
|
|
|
int
|
|
disassemble_index (insn, index)
|
|
unsigned long insn;
|
|
int index;
|
|
{
|
|
char *dest = disassembled;
|
if (index >= 0)
|
if (index >= 0)
|
{
|
{
|
struct or32_opcode const *opcode = &or32_opcodes[index];
|
struct or32_opcode const *opcode = &or32_opcodes[index];
|
char *s;
|
char *s;
|
|
|
sprintf(disassembled, "%s ", opcode->name);
|
strcpy (dest, opcode->name);
|
|
while (*dest) dest++;
|
|
*dest++ = ' ';
|
|
*dest = 0;
|
|
|
for (s = opcode->args; *s != '\0'; ++s)
|
for (s = opcode->args; *s != '\0'; ++s)
|
{
|
{
|
switch (*s)
|
switch (*s)
|
{
|
{
|
case '\0':
|
case '\0':
|
return 4;
|
return insn_len (insn);
|
|
|
case 'r':
|
case 'r':
|
or32_print_register(*++s, opcode->encoding, insn);
|
dest = or32_print_register(dest, *++s, opcode->encoding, insn);
|
break;
|
break;
|
|
|
default:
|
default:
|
if (strchr (opcode->encoding, *s))
|
if (strchr (opcode->encoding, *s))
|
or32_print_immediate (*s, opcode->encoding, insn);
|
dest = or32_print_immediate (dest, *s, opcode->encoding, insn);
|
else
|
else {
|
sprintf(disassembled, "%s%c", disassembled, *s);
|
*dest++ = *s;
|
|
*dest = 0;
|
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* This used to be %8x for binutils. */
|
/* This used to be %8x for binutils. */
|
sprintf(disassembled, "%s.word 0x%08x", disassembled, insn);
|
sprintf(dest, ".word 0x%08x", insn);
|
|
while (*dest) dest++;
|
}
|
}
|
return insn_len (insn);
|
return insn_len (insn);
|
}
|
}
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|