Line 21... |
Line 21... |
/* We treat all letters the same in encode/decode routines so
|
/* We treat all letters the same in encode/decode routines so
|
we need to assign some characteristics to them like signess etc.*/
|
we need to assign some characteristics to them like signess etc.*/
|
#include <string.h>
|
#include <string.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
# include "config.h"
|
# include "config.h"
|
#endif
|
#endif
|
#include "opcode/or32.h"
|
#include "opcode/or32.h"
|
Line 329... |
Line 331... |
#undef EFN
|
#undef EFN
|
#undef EF
|
#undef EF
|
|
|
/* **INDENT-ON** */
|
/* **INDENT-ON** */
|
|
|
CONST unsigned int num_opcodes = ((sizeof(or32_opcodes)) / (sizeof(struct or32_opcode))) - 1;
|
/* Define dummy, if debug is not defined. */
|
|
#if !defined HAS_DEBUG
|
|
void debug(int level, const char *format, ...)
|
|
{
|
|
/* Just to get rid of warnings. */
|
|
format = level = 0;
|
|
}
|
|
#endif
|
|
|
|
CONST int num_opcodes = ((sizeof(or32_opcodes)) / (sizeof(struct or32_opcode))) - 1;
|
|
|
/* Calculates instruction length in bytes. Always 4 for OR32. */
|
/* Calculates instruction length in bytes. Always 4 for OR32. */
|
int
|
int
|
insn_len(int insn_index)
|
insn_len(int insn_index)
|
{
|
{
|
Line 382... |
Line 393... |
/* MM: Returns index of given instruction name. */
|
/* MM: Returns index of given instruction name. */
|
int
|
int
|
insn_index (char *insn)
|
insn_index (char *insn)
|
{
|
{
|
int i, found = -1;
|
int i, found = -1;
|
for (i = 0; (unsigned int)i < num_opcodes; i++)
|
for (i = 0; i < num_opcodes; i++)
|
if (!strcmp (or32_opcodes[i].name, insn))
|
if (!strcmp (or32_opcodes[i].name, insn))
|
{
|
{
|
found = i;
|
found = i;
|
break;
|
break;
|
}
|
}
|
return found;
|
return found;
|
}
|
}
|
|
|
CONST char *insn_name(int index)
|
CONST char *insn_name(int index)
|
{
|
{
|
if (index >= 0 && (unsigned int)index < num_opcodes)
|
if (index >= 0 && index < num_opcodes)
|
return or32_opcodes[index].name;
|
return or32_opcodes[index].name;
|
else
|
else
|
return "???";
|
return "???";
|
}
|
}
|
|
|
Line 538... |
Line 549... |
int j;
|
int j;
|
unsigned long *c;
|
unsigned long *c;
|
curpass++;
|
curpass++;
|
for (j = 0; j < num_opcodes; j++)
|
for (j = 0; j < num_opcodes; j++)
|
if (ti[j].in_pass == pass
|
if (ti[j].in_pass == pass
|
&& ((ti[j].insn >> best_first) & cur_mask) == i
|
&& ((ti[j].insn >> best_first) & cur_mask) == (unsigned long) i
|
&& ((ti[j].insn_mask >> best_first) & cur_mask) == cur_mask)
|
&& ((ti[j].insn_mask >> best_first) & cur_mask) == cur_mask)
|
ti[j].in_pass = curpass;
|
ti[j].in_pass = curpass;
|
|
|
debug(9, "%08X %08X %i\n", mask, cur_mask, best_first);
|
debug(9, "%08X %08X %i\n", mask, cur_mask, best_first);
|
c = cover_insn (cur, curpass, mask & (~(cur_mask << best_first)));
|
c = cover_insn (cur, curpass, mask & (~(cur_mask << best_first)));
|
Line 687... |
Line 698... |
/* Constructs new automata based on or32_opcodes array. */
|
/* Constructs new automata based on or32_opcodes array. */
|
|
|
void
|
void
|
build_automata()
|
build_automata()
|
{
|
{
|
int i, j;
|
int i;
|
unsigned long *end;
|
unsigned long *end;
|
struct insn_op_struct *cur;
|
struct insn_op_struct *cur;
|
|
|
automata = (unsigned long *) malloc (MAX_AUTOMATA_SIZE * sizeof (unsigned long));
|
automata = (unsigned long *) malloc (MAX_AUTOMATA_SIZE * sizeof (unsigned long));
|
ti = (struct temp_insn_struct *) malloc (sizeof (struct temp_insn_struct) * num_opcodes);
|
ti = (struct temp_insn_struct *) malloc (sizeof (struct temp_insn_struct) * num_opcodes);
|
Line 774... |
Line 785... |
return i;
|
return i;
|
else
|
else
|
return -1;
|
return -1;
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|
|
static char disassembled_str[50];
|
|
char *disassembled = &disassembled_str[0];
|
|
|
|
/* Automagically does zero- or sign- extension and also finds correct
|
|
sign bit position if sign extension is correct extension. Which extension
|
|
is proper is figured out from letter description. */
|
|
|
|
unsigned long
|
|
extend_imm(unsigned long imm, char l)
|
|
{
|
|
unsigned long mask;
|
|
int letter_bits;
|
|
|
|
/* First truncate all bits above valid range for this letter
|
|
in case it is zero extend. */
|
|
letter_bits = letter_range(l);
|
|
mask = (1 << letter_bits) - 1;
|
|
imm &= mask;
|
|
|
|
/* Do sign extend if this is the right one. */
|
|
if (letter_signed(l) && (imm >> (letter_bits - 1)))
|
|
imm |= (~mask);
|
|
|
|
return imm;
|
|
}
|
|
|
|
static unsigned long
|
|
or32_extract(param_ch, enc_initial, insn)
|
|
char param_ch;
|
|
char *enc_initial;
|
|
unsigned long insn;
|
|
{
|
|
char *enc;
|
|
unsigned long ret = 0;
|
|
int opc_pos = 0;
|
|
int param_pos = 0;
|
|
|
|
for (enc = enc_initial; *enc != '\0'; enc++)
|
|
if (*enc == param_ch)
|
|
{
|
|
if (enc - 2 >= enc_initial && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
|
|
continue;
|
|
else
|
|
param_pos++;
|
|
}
|
|
|
|
#if DEBUG
|
|
printf("or32_extract: %x ", param_pos);
|
|
#endif
|
|
opc_pos = 32;
|
|
for (enc = enc_initial; *enc != '\0'; )
|
|
if ((*enc == '0') && (*(enc+1) == 'x'))
|
|
{
|
|
opc_pos -= 4;
|
|
if ((param_ch == '0') || (param_ch == '1'))
|
|
{
|
|
unsigned long tmp = strtol(enc, NULL, 16);
|
|
#if DEBUG
|
|
printf(" enc=%s, tmp=%x ", enc, tmp);
|
|
#endif
|
|
if (param_ch == '0')
|
|
tmp = 15 - tmp;
|
|
ret |= tmp << opc_pos;
|
|
}
|
|
enc += 3;
|
|
}
|
|
else if ((*enc == '0') || (*enc == '1'))
|
|
{
|
|
opc_pos--;
|
|
if (param_ch == *enc)
|
|
ret |= 1 << opc_pos;
|
|
enc++;
|
|
}
|
|
else if (*enc == param_ch)
|
|
{
|
|
opc_pos--;
|
|
param_pos--;
|
|
#if DEBUG
|
|
printf("\n ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
|
|
#endif
|
|
if (islower(param_ch))
|
|
ret -= ((insn >> opc_pos) & 0x1) << param_pos;
|
|
else
|
|
ret += ((insn >> opc_pos) & 0x1) << param_pos;
|
|
enc++;
|
|
}
|
|
else if (isalpha(*enc))
|
|
{
|
|
opc_pos--;
|
|
enc++;
|
|
}
|
|
else if (*enc == '-')
|
|
{
|
|
opc_pos--;
|
|
enc++;
|
|
}
|
|
else
|
|
enc++;
|
|
|
|
#if DEBUG
|
|
printf ("ret=%x\n", ret);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
/* Print register. Used only by print_insn. */
|
|
|
|
static void
|
|
or32_print_register (param_ch, encoding, insn)
|
|
char param_ch;
|
|
char *encoding;
|
|
unsigned long insn;
|
|
{
|
|
int regnum = or32_extract(param_ch, encoding, insn);
|
|
|
|
sprintf (disassembled, "%sr%d", disassembled, regnum);
|
|
}
|
|
|
|
/* Print immediate. Used only by print_insn. */
|
|
|
|
static void
|
|
or32_print_immediate (param_ch, encoding, insn)
|
|
char param_ch;
|
|
char *encoding;
|
|
unsigned long insn;
|
|
{
|
|
int imm = or32_extract (param_ch, encoding, insn);
|
|
|
|
imm = extend_imm(imm, param_ch);
|
|
|
|
if (letter_signed(param_ch))
|
|
{
|
|
if (imm < 0)
|
|
sprintf (disassembled, "%s%d", disassembled, imm);
|
|
else
|
|
sprintf (disassembled, "%s0x%x", disassembled, imm);
|
|
}
|
|
else
|
|
sprintf (disassembled, "%s%#x", disassembled, imm);
|
|
}
|
|
|
|
/* Disassemble one instruction from insn to disassemble.
|
|
Return the size of the instruction. */
|
|
|
|
int
|
|
disassemble_insn (insn)
|
|
unsigned long insn;
|
|
{
|
|
int index;
|
|
index = insn_decode (insn);
|
|
|
|
if (index >= 0)
|
|
{
|
|
struct or32_opcode const *opcode = &or32_opcodes[index];
|
|
char *s;
|
|
|
|
sprintf(disassembled, "%s ", opcode->name);
|
|
for (s = opcode->args; *s != '\0'; ++s)
|
|
{
|
|
switch (*s)
|
|
{
|
|
case '\0':
|
|
return 4;
|
|
|
|
case 'r':
|
|
or32_print_register(*++s, opcode->encoding, insn);
|
|
break;
|
|
|
|
default:
|
|
if (strchr (opcode->encoding, *s))
|
|
or32_print_immediate (*s, opcode->encoding, insn);
|
|
else
|
|
sprintf(disassembled, "%s%c", disassembled, *s);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* This used to be %8x for binutils. */
|
|
sprintf(disassembled, "%s.word 0x%08x", disassembled, insn);
|
|
}
|
|
return insn_len (insn);
|
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|