23cf992f4a
Insn attributes hand patched until cgen can generate the correct values.
253 lines
9.8 KiB
Plaintext
253 lines
9.8 KiB
Plaintext
/* -- dis.c */
|
|
|
|
#undef CGEN_PRINT_INSN
|
|
#define CGEN_PRINT_INSN my_print_insn
|
|
|
|
static int
|
|
my_print_insn (pc, info, buf, buflen)
|
|
bfd_vma pc;
|
|
disassemble_info *info;
|
|
char *buf;
|
|
int buflen;
|
|
{
|
|
/* 32 bit insn? */
|
|
if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
|
|
return print_insn (pc, info, buf, buflen);
|
|
|
|
/* Print the first insn. */
|
|
if ((pc & 3) == 0)
|
|
{
|
|
if (print_insn (pc, info, buf, 16) == 0)
|
|
(*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
|
|
buf += 2;
|
|
}
|
|
|
|
if (buf[0] & 0x80)
|
|
{
|
|
/* Parallel. */
|
|
(*info->fprintf_func) (info->stream, " || ");
|
|
buf[0] &= 0x7f;
|
|
}
|
|
else
|
|
(*info->fprintf_func) (info->stream, " -> ");
|
|
|
|
/* The "& 3" is to ensure the branch address is computed correctly
|
|
[if it is a branch]. */
|
|
if (print_insn (pc & ~ (bfd_vma) 3, info, buf, 16) == 0)
|
|
(*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
|
|
|
|
return (pc & 3) ? 2 : 4;
|
|
}
|
|
|
|
/* -- */
|
|
|
|
/* Main entry point for operand extraction.
|
|
|
|
This function is basically just a big switch statement. Earlier versions
|
|
used tables to look up the function to use, but
|
|
- if the table contains both assembler and disassembler functions then
|
|
the disassembler contains much of the assembler and vice-versa,
|
|
- there's a lot of inlining possibilities as things grow,
|
|
- using a switch statement avoids the function call overhead.
|
|
|
|
This function could be moved into `print_insn_normal', but keeping it
|
|
separate makes clear the interface between `print_insn_normal' and each of
|
|
the handlers.
|
|
*/
|
|
|
|
CGEN_INLINE int
|
|
m32r_cgen_extract_operand (opindex, buf_ctrl, insn_value, fields)
|
|
int opindex;
|
|
void *buf_ctrl;
|
|
cgen_insn_t insn_value;
|
|
CGEN_FIELDS *fields;
|
|
{
|
|
int length;
|
|
|
|
switch (opindex)
|
|
{
|
|
case M32R_OPERAND_SR :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2);
|
|
break;
|
|
case M32R_OPERAND_DR :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1);
|
|
break;
|
|
case M32R_OPERAND_SRC1 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1);
|
|
break;
|
|
case M32R_OPERAND_SRC2 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2);
|
|
break;
|
|
case M32R_OPERAND_SCR :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2);
|
|
break;
|
|
case M32R_OPERAND_DCR :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1);
|
|
break;
|
|
case M32R_OPERAND_SIMM8 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm8);
|
|
break;
|
|
case M32R_OPERAND_SIMM16 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm16);
|
|
break;
|
|
case M32R_OPERAND_UIMM4 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm4);
|
|
break;
|
|
case M32R_OPERAND_UIMM5 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm5);
|
|
break;
|
|
case M32R_OPERAND_UIMM16 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm16);
|
|
break;
|
|
case M32R_OPERAND_ACC_S :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 2, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_acc_s);
|
|
break;
|
|
case M32R_OPERAND_ACC :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 1, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_acc);
|
|
break;
|
|
case M32R_OPERAND_HI16 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_hi16);
|
|
break;
|
|
case M32R_OPERAND_SLO16 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm16);
|
|
break;
|
|
case M32R_OPERAND_ULO16 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm16);
|
|
break;
|
|
case M32R_OPERAND_UIMM24 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm24);
|
|
break;
|
|
case M32R_OPERAND_DISP8 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp8);
|
|
break;
|
|
case M32R_OPERAND_DISP16 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp16);
|
|
break;
|
|
case M32R_OPERAND_DISP24 :
|
|
length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp24);
|
|
break;
|
|
|
|
default :
|
|
fprintf (stderr, "Unrecognized field %d while decoding insn.\n",
|
|
opindex);
|
|
abort ();
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
/* Main entry point for printing operands.
|
|
|
|
This function is basically just a big switch statement. Earlier versions
|
|
used tables to look up the function to use, but
|
|
- if the table contains both assembler and disassembler functions then
|
|
the disassembler contains much of the assembler and vice-versa,
|
|
- there's a lot of inlining possibilities as things grow,
|
|
- using a switch statement avoids the function call overhead.
|
|
|
|
This function could be moved into `print_insn_normal', but keeping it
|
|
separate makes clear the interface between `print_insn_normal' and each of
|
|
the handlers.
|
|
*/
|
|
|
|
CGEN_INLINE void
|
|
m32r_cgen_print_operand (opindex, info, fields, attrs, pc, length)
|
|
int opindex;
|
|
disassemble_info *info;
|
|
CGEN_FIELDS *fields;
|
|
void const * attrs;
|
|
bfd_vma pc;
|
|
int length;
|
|
{
|
|
switch (opindex)
|
|
{
|
|
case M32R_OPERAND_SR :
|
|
print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
|
|
break;
|
|
case M32R_OPERAND_DR :
|
|
print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
|
|
break;
|
|
case M32R_OPERAND_SRC1 :
|
|
print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
|
|
break;
|
|
case M32R_OPERAND_SRC2 :
|
|
print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
|
|
break;
|
|
case M32R_OPERAND_SCR :
|
|
print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
|
|
break;
|
|
case M32R_OPERAND_DCR :
|
|
print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
|
|
break;
|
|
case M32R_OPERAND_SIMM8 :
|
|
print_normal (info, fields->f_simm8, 0, pc, length);
|
|
break;
|
|
case M32R_OPERAND_SIMM16 :
|
|
print_normal (info, fields->f_simm16, 0, pc, length);
|
|
break;
|
|
case M32R_OPERAND_UIMM4 :
|
|
print_normal (info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
|
|
break;
|
|
case M32R_OPERAND_UIMM5 :
|
|
print_normal (info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
|
|
break;
|
|
case M32R_OPERAND_UIMM16 :
|
|
print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
|
|
break;
|
|
case M32R_OPERAND_ACC_S :
|
|
print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_acc_s, 0|(1<<CGEN_OPERAND_UNSIGNED));
|
|
break;
|
|
case M32R_OPERAND_ACC :
|
|
print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED));
|
|
break;
|
|
case M32R_OPERAND_HI16 :
|
|
print_normal (info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
|
|
break;
|
|
case M32R_OPERAND_SLO16 :
|
|
print_normal (info, fields->f_simm16, 0, pc, length);
|
|
break;
|
|
case M32R_OPERAND_ULO16 :
|
|
print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
|
|
break;
|
|
case M32R_OPERAND_UIMM24 :
|
|
print_normal (info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
|
|
break;
|
|
case M32R_OPERAND_DISP8 :
|
|
print_normal (info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
|
|
break;
|
|
case M32R_OPERAND_DISP16 :
|
|
print_normal (info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
|
|
break;
|
|
case M32R_OPERAND_DISP24 :
|
|
print_normal (info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
|
|
break;
|
|
|
|
default :
|
|
fprintf (stderr, "Unrecognized field %d while printing insn.\n",
|
|
opindex);
|
|
abort ();
|
|
}
|
|
}
|
|
|
|
cgen_extract_fn *m32r_cgen_extract_handlers[] = {
|
|
0, /* default */
|
|
extract_insn_normal,
|
|
};
|
|
|
|
cgen_print_fn *m32r_cgen_print_handlers[] = {
|
|
0, /* default */
|
|
print_insn_normal,
|
|
};
|
|
|
|
|
|
void
|
|
m32r_cgen_init_dis (mach, endian)
|
|
int mach;
|
|
enum cgen_endian endian;
|
|
{
|
|
m32r_cgen_init_tables (mach);
|
|
cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian);
|
|
cgen_dis_init ();
|
|
}
|
|
|