#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include "xtensa-isa.h"
#include "ansidecl.h"
#include "sysdep.h"
#include "dis-asm.h"
#include <setjmp.h>
#ifndef MAX
#define MAX(a,b) (a > b ? a : b)
#endif
static char* state_names[256] =
{
"lbeg",
"lend",
"lcount",
"sar",
"br",
"reserved_5",
"reserved_6",
"reserved_7",
"av",
"avh",
"bv",
"sav",
"scompare1",
"reserved_13",
"reserved_14",
"reserved_15",
"acclo",
"acchi",
"reserved_18",
"reserved_19",
"reserved_20",
"reserved_21",
"reserved_22",
"reserved_23",
"reserved_24",
"reserved_25",
"reserved_26",
"reserved_27",
"reserved_28",
"reserved_29",
"reserved_30",
"reserved_31",
"mr0",
"mr1",
"mr2",
"mr3",
"reserved_36",
"reserved_37",
"reserved_38",
"reserved_39",
"reserved_40",
"reserved_41",
"reserved_42",
"reserved_43",
"reserved_44",
"reserved_45",
"reserved_46",
"reserved_47",
"reserved_48",
"reserved_49",
"reserved_50",
"reserved_51",
"reserved_52",
"reserved_53",
"reserved_54",
"reserved_55",
"reserved_56",
"reserved_57",
"reserved_58",
"reserved_59",
"reserved_60",
"reserved_61",
"reserved_62",
"reserved_63",
"reserved_64",
"reserved_65",
"reserved_66",
"reserved_67",
"reserved_68",
"reserved_69",
"reserved_70",
"reserved_71",
"wb",
"ws",
"reserved_74",
"reserved_75",
"reserved_76",
"reserved_77",
"reserved_78",
"reserved_79",
"reserved_80",
"reserved_81",
"reserved_82",
"ptevaddr",
"reserved_84",
"reserved_85",
"reserved_86",
"reserved_87",
"reserved_88",
"reserved_89",
"rasid",
"itlbcfg",
"dtlbcfg",
"reserved_93",
"reserved_94",
"reserved_95",
"ibreakenable",
"reserved_97",
"cacheattr",
"reserved_99",
"reserved_100",
"reserved_101",
"reserved_102",
"reserved_103",
"ddr",
"reserved_105",
"reserved_106",
"reserved_107",
"reserved_108",
"reserved_109",
"reserved_110",
"reserved_111",
"reserved_112",
"reserved_113",
"reserved_114",
"reserved_115",
"reserved_116",
"reserved_117",
"reserved_118",
"reserved_119",
"reserved_120",
"reserved_121",
"reserved_122",
"reserved_123",
"reserved_124",
"reserved_125",
"reserved_126",
"reserved_127",
"ibreaka0",
"ibreaka1",
"ibreaka2",
"ibreaka3",
"ibreaka4",
"ibreaka5",
"ibreaka6",
"ibreaka7",
"ibreaka8",
"ibreaka9",
"ibreaka10",
"ibreaka11",
"ibreaka12",
"ibreaka13",
"ibreaka14",
"ibreaka15",
"dbreaka0",
"dbreaka1",
"dbreaka2",
"dbreaka3",
"dbreaka4",
"dbreaka5",
"dbreaka6",
"dbreaka7",
"dbreaka8",
"dbreaka9",
"dbreaka10",
"dbreaka11",
"dbreaka12",
"dbreaka13",
"dbreaka14",
"dbreaka15",
"dbreakc0",
"dbreakc1",
"dbreakc2",
"dbreakc3",
"dbreakc4",
"dbreakc5",
"dbreakc6",
"dbreakc7",
"dbreakc8",
"dbreakc9",
"dbreakc10",
"dbreakc11",
"dbreakc12",
"dbreakc13",
"dbreakc14",
"dbreakc15",
"reserved_176",
"epc1",
"epc2",
"epc3",
"epc4",
"epc5",
"epc6",
"epc7",
"epc8",
"epc9",
"epc10",
"epc11",
"epc12",
"epc13",
"epc14",
"epc15",
"depc",
"reserved_193",
"eps2",
"eps3",
"eps4",
"eps5",
"eps6",
"eps7",
"eps8",
"eps9",
"eps10",
"eps11",
"eps12",
"eps13",
"eps14",
"eps15",
"reserved_208",
"excsave1",
"excsave2",
"excsave3",
"excsave4",
"excsave5",
"excsave6",
"excsave7",
"excsave8",
"excsave9",
"excsave10",
"excsave11",
"excsave12",
"excsave13",
"excsave14",
"excsave15",
"cpenable",
"reserved_225",
"interrupt",
"interrupt2",
"intenable",
"reserved_229",
"ps",
"reserved_231",
"exccause",
"debugcause",
"ccount",
"prid",
"icount",
"icountlvl",
"excvaddr",
"reserved_239",
"ccompare0",
"ccompare1",
"ccompare2",
"ccompare3",
"misc0",
"misc1",
"misc2",
"misc3",
"reserved_248",
"reserved_249",
"reserved_250",
"reserved_251",
"reserved_252",
"reserved_253",
"reserved_254",
"reserved_255",
};
int show_raw_fields;
static int fetch_data
PARAMS ((struct disassemble_info *info, bfd_vma memaddr));
static void print_xtensa_operand
PARAMS ((bfd_vma, struct disassemble_info *, xtensa_operand,
unsigned operand_val, int print_sr_name));
struct dis_private {
bfd_byte *byte_buf;
jmp_buf bailout;
};
static int
fetch_data (info, memaddr)
struct disassemble_info *info;
bfd_vma memaddr;
{
int length, status = 0;
struct dis_private *priv = (struct dis_private *) info->private_data;
int insn_size = xtensa_insn_maxlength (xtensa_default_isa);
memset (priv->byte_buf, 0, insn_size);
for (length = insn_size; length > 0; length--)
{
status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
info);
if (status == 0)
return length;
}
(*info->memory_error_func) (status, memaddr, info);
longjmp (priv->bailout, 1);
}
static void
print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name)
bfd_vma memaddr;
struct disassemble_info *info;
xtensa_operand opnd;
unsigned operand_val;
int print_sr_name;
{
char *kind = xtensa_operand_kind (opnd);
int signed_operand_val;
if (show_raw_fields)
{
if (operand_val < 0xa)
(*info->fprintf_func) (info->stream, "%u", operand_val);
else
(*info->fprintf_func) (info->stream, "0x%x", operand_val);
return;
}
operand_val = xtensa_operand_decode (opnd, operand_val);
signed_operand_val = (int) operand_val;
if (xtensa_operand_isPCRelative (opnd))
{
operand_val = xtensa_operand_undo_reloc (opnd, operand_val, memaddr);
info->target = operand_val;
(*info->print_address_func) (info->target, info);
}
else if (!strcmp (kind, "i"))
{
if (print_sr_name
&& signed_operand_val >= 0
&& signed_operand_val <= 255)
(*info->fprintf_func) (info->stream, "%s",
state_names[signed_operand_val]);
else if ((signed_operand_val > -256) && (signed_operand_val < 256))
(*info->fprintf_func) (info->stream, "%d", signed_operand_val);
else
(*info->fprintf_func) (info->stream, "0x%x",signed_operand_val);
}
else
(*info->fprintf_func) (info->stream, "%s%u", kind, operand_val);
}
int
print_insn_xtensa (memaddr, info)
bfd_vma memaddr;
struct disassemble_info *info;
{
unsigned operand_val;
int bytes_fetched, size, maxsize, i, noperands;
xtensa_isa isa;
xtensa_opcode opc;
char *op_name;
int print_sr_name;
struct dis_private priv;
static bfd_byte *byte_buf = NULL;
static xtensa_insnbuf insn_buffer = NULL;
if (!xtensa_default_isa)
(void) xtensa_isa_init ();
info->target = 0;
maxsize = xtensa_insn_maxlength (xtensa_default_isa);
info->bytes_per_line = MAX (maxsize, 4);
if (!insn_buffer)
insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
if (!byte_buf)
byte_buf = (bfd_byte *) malloc (MAX (maxsize, 4));
priv.byte_buf = byte_buf;
info->private_data = (PTR) &priv;
if (setjmp (priv.bailout) != 0)
return -1;
isa = xtensa_default_isa;
bytes_fetched = fetch_data (info, memaddr);
memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
sizeof (xtensa_insnbuf_word)));
xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf);
opc = xtensa_decode_insn (isa, insn_buffer);
if (opc == XTENSA_UNDEFINED
|| ((size = xtensa_insn_length (isa, opc)) > bytes_fetched))
{
(*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
return 1;
}
op_name = (char *) xtensa_opcode_name (isa, opc);
(*info->fprintf_func) (info->stream, "%s", op_name);
print_sr_name = (!strcasecmp (op_name, "wsr")
|| !strcasecmp (op_name, "xsr")
|| !strcasecmp (op_name, "rsr"));
noperands = xtensa_num_operands (isa, opc);
if (noperands > 0)
{
int first = 1;
(*info->fprintf_func) (info->stream, "\t");
for (i = 0; i < noperands; i++)
{
xtensa_operand opnd = xtensa_get_operand (isa, opc, i);
if (first)
first = 0;
else
(*info->fprintf_func) (info->stream, ", ");
operand_val = xtensa_operand_get_field (opnd, insn_buffer);
print_xtensa_operand (memaddr, info, opnd, operand_val,
print_sr_name);
}
}
info->bytes_per_chunk = size;
info->display_endian = info->endian;
return size;
}