diff options
Diffstat (limited to 'opcodes/xtensa-dis.c')
-rw-r--r-- | opcodes/xtensa-dis.c | 467 |
1 files changed, 110 insertions, 357 deletions
diff --git a/opcodes/xtensa-dis.c b/opcodes/xtensa-dis.c index 8c31085..d7554a7 100644 --- a/opcodes/xtensa-dis.c +++ b/opcodes/xtensa-dis.c @@ -1,5 +1,5 @@ /* xtensa-dis.c. Disassembly functions for Xtensa. - Copyright 2003 Free Software Foundation, Inc. + Copyright 2003, 2004 Free Software Foundation, Inc. Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com) This file is part of GDB, GAS, and the GNU binutils. @@ -25,328 +25,32 @@ #include <string.h> #include "xtensa-isa.h" #include "ansidecl.h" +#include "libiberty.h" #include "sysdep.h" #include "dis-asm.h" #include <setjmp.h> +extern xtensa_isa xtensa_default_isa; + #ifndef MAX #define MAX(a,b) (a > b ? a : b) #endif -static char* state_names[256] = -{ - "lbeg", /* 0 */ - "lend", /* 1 */ - "lcount", /* 2 */ - "sar", /* 3 */ - "br", /* 4 */ - - "reserved_5", /* 5 */ - "reserved_6", /* 6 */ - "reserved_7", /* 7 */ - - "av", /* 8 */ - "avh", /* 9 */ - "bv", /* 10 */ - "sav", /* 11 */ - "scompare1", /* 12 */ - - "reserved_13", /* 13 */ - "reserved_14", /* 14 */ - "reserved_15", /* 15 */ - - "acclo", /* 16 */ - "acchi", /* 17 */ - - "reserved_18", /* 18 */ - "reserved_19", /* 19 */ - "reserved_20", /* 20 */ - "reserved_21", /* 21 */ - "reserved_22", /* 22 */ - "reserved_23", /* 23 */ - "reserved_24", /* 24 */ - "reserved_25", /* 25 */ - "reserved_26", /* 26 */ - "reserved_27", /* 27 */ - "reserved_28", /* 28 */ - "reserved_29", /* 29 */ - "reserved_30", /* 30 */ - "reserved_31", /* 31 */ - - "mr0", /* 32 */ - "mr1", /* 33 */ - "mr2", /* 34 */ - "mr3", /* 35 */ - - "reserved_36", /* 36 */ - "reserved_37", /* 37 */ - "reserved_38", /* 38 */ - "reserved_39", /* 39 */ - "reserved_40", /* 40 */ - "reserved_41", /* 41 */ - "reserved_42", /* 42 */ - "reserved_43", /* 43 */ - "reserved_44", /* 44 */ - "reserved_45", /* 45 */ - "reserved_46", /* 46 */ - "reserved_47", /* 47 */ - "reserved_48", /* 48 */ - "reserved_49", /* 49 */ - "reserved_50", /* 50 */ - "reserved_51", /* 51 */ - "reserved_52", /* 52 */ - "reserved_53", /* 53 */ - "reserved_54", /* 54 */ - "reserved_55", /* 55 */ - "reserved_56", /* 56 */ - "reserved_57", /* 57 */ - "reserved_58", /* 58 */ - "reserved_59", /* 59 */ - "reserved_60", /* 60 */ - "reserved_61", /* 61 */ - "reserved_62", /* 62 */ - "reserved_63", /* 63 */ - - "reserved_64", /* 64 */ - "reserved_65", /* 65 */ - "reserved_66", /* 66 */ - "reserved_67", /* 67 */ - "reserved_68", /* 68 */ - "reserved_69", /* 69 */ - "reserved_70", /* 70 */ - "reserved_71", /* 71 */ - - "wb", /* 72 */ - "ws", /* 73 */ - - "reserved_74", /* 74 */ - "reserved_75", /* 75 */ - "reserved_76", /* 76 */ - "reserved_77", /* 77 */ - "reserved_78", /* 78 */ - "reserved_79", /* 79 */ - "reserved_80", /* 80 */ - "reserved_81", /* 81 */ - "reserved_82", /* 82 */ - - "ptevaddr", /* 83 */ - - "reserved_84", /* 84 */ - "reserved_85", /* 85 */ - "reserved_86", /* 86 */ - "reserved_87", /* 87 */ - "reserved_88", /* 88 */ - "reserved_89", /* 89 */ - - "rasid", /* 90 */ - "itlbcfg", /* 91 */ - "dtlbcfg", /* 92 */ - - "reserved_93", /* 93 */ - "reserved_94", /* 94 */ - "reserved_95", /* 95 */ - - "ibreakenable", /* 96 */ - - "reserved_97", /* 97 */ - - "cacheattr", /* 98 */ - - "reserved_99", /* 99 */ - "reserved_100", /* 100 */ - "reserved_101", /* 101 */ - "reserved_102", /* 102 */ - "reserved_103", /* 103 */ - - "ddr", /* 104 */ - - "reserved_105", /* 105 */ - "reserved_106", /* 106 */ - "reserved_107", /* 107 */ - "reserved_108", /* 108 */ - "reserved_109", /* 109 */ - "reserved_110", /* 110 */ - "reserved_111", /* 111 */ - "reserved_112", /* 112 */ - "reserved_113", /* 113 */ - "reserved_114", /* 114 */ - "reserved_115", /* 115 */ - "reserved_116", /* 116 */ - "reserved_117", /* 117 */ - "reserved_118", /* 118 */ - "reserved_119", /* 119 */ - "reserved_120", /* 120 */ - "reserved_121", /* 121 */ - "reserved_122", /* 122 */ - "reserved_123", /* 123 */ - "reserved_124", /* 124 */ - "reserved_125", /* 125 */ - "reserved_126", /* 126 */ - "reserved_127", /* 127 */ - - "ibreaka0", /* 128 */ - "ibreaka1", /* 129 */ - "ibreaka2", /* 130 */ - "ibreaka3", /* 131 */ - "ibreaka4", /* 132 */ - "ibreaka5", /* 133 */ - "ibreaka6", /* 134 */ - "ibreaka7", /* 135 */ - "ibreaka8", /* 136 */ - "ibreaka9", /* 137 */ - "ibreaka10", /* 138 */ - "ibreaka11", /* 139 */ - "ibreaka12", /* 140 */ - "ibreaka13", /* 141 */ - "ibreaka14", /* 142 */ - "ibreaka15", /* 143 */ - - "dbreaka0", /* 144 */ - "dbreaka1", /* 145 */ - "dbreaka2", /* 146 */ - "dbreaka3", /* 147 */ - "dbreaka4", /* 148 */ - "dbreaka5", /* 149 */ - "dbreaka6", /* 150 */ - "dbreaka7", /* 151 */ - "dbreaka8", /* 152 */ - "dbreaka9", /* 153 */ - "dbreaka10", /* 154 */ - "dbreaka11", /* 155 */ - "dbreaka12", /* 156 */ - "dbreaka13", /* 157 */ - "dbreaka14", /* 158 */ - "dbreaka15", /* 159 */ - - "dbreakc0", /* 160 */ - "dbreakc1", /* 161 */ - "dbreakc2", /* 162 */ - "dbreakc3", /* 163 */ - "dbreakc4", /* 164 */ - "dbreakc5", /* 165 */ - "dbreakc6", /* 166 */ - "dbreakc7", /* 167 */ - "dbreakc8", /* 168 */ - "dbreakc9", /* 169 */ - "dbreakc10", /* 170 */ - "dbreakc11", /* 171 */ - "dbreakc12", /* 172 */ - "dbreakc13", /* 173 */ - "dbreakc14", /* 174 */ - "dbreakc15", /* 175 */ - - "reserved_176", /* 176 */ - - "epc1", /* 177 */ - "epc2", /* 178 */ - "epc3", /* 179 */ - "epc4", /* 180 */ - "epc5", /* 181 */ - "epc6", /* 182 */ - "epc7", /* 183 */ - "epc8", /* 184 */ - "epc9", /* 185 */ - "epc10", /* 186 */ - "epc11", /* 187 */ - "epc12", /* 188 */ - "epc13", /* 189 */ - "epc14", /* 190 */ - "epc15", /* 191 */ - "depc", /* 192 */ - - "reserved_193", /* 193 */ - - "eps2", /* 194 */ - "eps3", /* 195 */ - "eps4", /* 196 */ - "eps5", /* 197 */ - "eps6", /* 198 */ - "eps7", /* 199 */ - "eps8", /* 200 */ - "eps9", /* 201 */ - "eps10", /* 202 */ - "eps11", /* 203 */ - "eps12", /* 204 */ - "eps13", /* 205 */ - "eps14", /* 206 */ - "eps15", /* 207 */ - - "reserved_208", /* 208 */ - - "excsave1", /* 209 */ - "excsave2", /* 210 */ - "excsave3", /* 211 */ - "excsave4", /* 212 */ - "excsave5", /* 213 */ - "excsave6", /* 214 */ - "excsave7", /* 215 */ - "excsave8", /* 216 */ - "excsave9", /* 217 */ - "excsave10", /* 218 */ - "excsave11", /* 219 */ - "excsave12", /* 220 */ - "excsave13", /* 221 */ - "excsave14", /* 222 */ - "excsave15", /* 223 */ - "cpenable", /* 224 */ - - "reserved_225", /* 225 */ - - "interrupt", /* 226 */ - "interrupt2", /* 227 */ - "intenable", /* 228 */ - - "reserved_229", /* 229 */ - - "ps", /* 230 */ - - "reserved_231", /* 231 */ - - "exccause", /* 232 */ - "debugcause", /* 233 */ - "ccount", /* 234 */ - "prid", /* 235 */ - "icount", /* 236 */ - "icountlvl", /* 237 */ - "excvaddr", /* 238 */ - - "reserved_239", /* 239 */ - - "ccompare0", /* 240 */ - "ccompare1", /* 241 */ - "ccompare2", /* 242 */ - "ccompare3", /* 243 */ - - "misc0", /* 244 */ - "misc1", /* 245 */ - "misc2", /* 246 */ - "misc3", /* 247 */ - - "reserved_248", /* 248 */ - "reserved_249", /* 249 */ - "reserved_250", /* 250 */ - "reserved_251", /* 251 */ - "reserved_252", /* 252 */ - "reserved_253", /* 253 */ - "reserved_254", /* 254 */ - "reserved_255", /* 255 */ -}; - - int show_raw_fields; static int fetch_data - PARAMS ((struct disassemble_info *info, bfd_vma memaddr)); + PARAMS ((struct disassemble_info *, bfd_vma)); static void print_xtensa_operand - PARAMS ((bfd_vma, struct disassemble_info *, xtensa_operand, - unsigned operand_val, int print_sr_name)); + PARAMS ((bfd_vma, struct disassemble_info *, xtensa_opcode, int, unsigned)); -struct dis_private { +struct dis_private +{ bfd_byte *byte_buf; jmp_buf bailout; }; + static int fetch_data (info, memaddr) struct disassemble_info *info; @@ -354,7 +58,7 @@ fetch_data (info, memaddr) { int length, status = 0; struct dis_private *priv = (struct dis_private *) info->private_data; - int insn_size = xtensa_insn_maxlength (xtensa_default_isa); + int insn_size = xtensa_isa_maxlength (xtensa_default_isa); /* Read the maximum instruction size, padding with zeros if we go past the end of the text section. This code will automatically adjust @@ -375,14 +79,14 @@ fetch_data (info, memaddr) static void -print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name) +print_xtensa_operand (memaddr, info, opc, opnd, operand_val) bfd_vma memaddr; struct disassemble_info *info; - xtensa_operand opnd; + xtensa_opcode opc; + int opnd; unsigned operand_val; - int print_sr_name; { - char *kind = xtensa_operand_kind (opnd); + xtensa_isa isa = xtensa_default_isa; int signed_operand_val; if (show_raw_fields) @@ -394,29 +98,42 @@ print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name) return; } - operand_val = xtensa_operand_decode (opnd, operand_val); + (void) xtensa_operand_decode (isa, opc, opnd, &operand_val); signed_operand_val = (int) operand_val; - if (xtensa_operand_isPCRelative (opnd)) + if (xtensa_operand_is_register (isa, opc, opnd) == 0) { - 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); + if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1) + { + (void) xtensa_operand_undo_reloc (isa, opc, opnd, + &operand_val, memaddr); + info->target = operand_val; + (*info->print_address_func) (info->target, info); + } else - (*info->fprintf_func) (info->stream, "0x%x",signed_operand_val); + { + 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 i = 1; + xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd); + (*info->fprintf_func) (info->stream, "%s%u", + xtensa_regfile_shortname (isa, opnd_rf), + operand_val); + while (i < xtensa_operand_num_regs (isa, opc, opnd)) + { + operand_val++; + (*info->fprintf_func) (info->stream, ":%s%u", + xtensa_regfile_shortname (isa, opnd_rf), + operand_val); + i++; + } + } } @@ -429,20 +146,21 @@ print_insn_xtensa (memaddr, info) struct disassemble_info *info; { unsigned operand_val; - int bytes_fetched, size, maxsize, i, noperands; + int bytes_fetched, size, maxsize, i, n, noperands, nslots; xtensa_isa isa; xtensa_opcode opc; - char *op_name; - int print_sr_name; + xtensa_format fmt; struct dis_private priv; static bfd_byte *byte_buf = NULL; static xtensa_insnbuf insn_buffer = NULL; + static xtensa_insnbuf slot_buffer = NULL; + int first, first_slot, valid_insn; if (!xtensa_default_isa) - (void) xtensa_isa_init (); + xtensa_default_isa = xtensa_isa_init (0, 0); info->target = 0; - maxsize = xtensa_insn_maxlength (xtensa_default_isa); + maxsize = xtensa_isa_maxlength (xtensa_default_isa); /* Set bytes_per_line to control the amount of whitespace between the hex values and the opcode. For Xtensa, we always print one "chunk" and we @@ -458,9 +176,11 @@ print_insn_xtensa (memaddr, info) /* Allocate buffers the first time through. */ if (!insn_buffer) - insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa); - if (!byte_buf) - byte_buf = (bfd_byte *) malloc (MAX (maxsize, 4)); + { + insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa); + slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa); + byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4)); + } priv.byte_buf = byte_buf; @@ -471,6 +191,8 @@ print_insn_xtensa (memaddr, info) /* Don't set "isa" before the setjmp to keep the compiler from griping. */ isa = xtensa_default_isa; + size = 0; + nslots = 0; /* Fetch the maximum size instruction. */ bytes_fetched = fetch_data (info, memaddr); @@ -478,44 +200,75 @@ print_insn_xtensa (memaddr, info) /* Copy the bytes into the decode buffer. */ memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) * sizeof (xtensa_insnbuf_word))); - xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf); + xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf, bytes_fetched); + + fmt = xtensa_format_decode (isa, insn_buffer); + if (fmt == XTENSA_UNDEFINED + || ((size = xtensa_format_length (isa, fmt)) > bytes_fetched)) + valid_insn = 0; + else + { + /* Make sure all the opcodes are valid. */ + valid_insn = 1; + nslots = xtensa_format_num_slots (isa, fmt); + for (n = 0; n < nslots; n++) + { + xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer); + if (xtensa_opcode_decode (isa, fmt, n, slot_buffer) + == XTENSA_UNDEFINED) + { + valid_insn = 0; + break; + } + } + } - opc = xtensa_decode_insn (isa, insn_buffer); - if (opc == XTENSA_UNDEFINED - || ((size = xtensa_insn_length (isa, opc)) > bytes_fetched)) + if (!valid_insn) { (*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")); + if (nslots > 1) + (*info->fprintf_func) (info->stream, "{ "); - /* Print the operands (if any). */ - noperands = xtensa_num_operands (isa, opc); - if (noperands > 0) + first_slot = 1; + for (n = 0; n < nslots; n++) { - int first = 1; + if (first_slot) + first_slot = 0; + else + (*info->fprintf_func) (info->stream, "; "); + + xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer); + opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer); + (*info->fprintf_func) (info->stream, "%s", + xtensa_opcode_name (isa, opc)); - (*info->fprintf_func) (info->stream, "\t"); + /* Print the operands (if any). */ + noperands = xtensa_opcode_num_operands (isa, opc); + first = 1; for (i = 0; i < noperands; i++) { - xtensa_operand opnd = xtensa_get_operand (isa, opc, i); - + if (xtensa_operand_is_visible (isa, opc, i) == 0) + continue; if (first) - first = 0; + { + (*info->fprintf_func) (info->stream, "\t"); + 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); - } + (void) xtensa_operand_get_field (isa, opc, i, fmt, n, + slot_buffer, &operand_val); + + print_xtensa_operand (memaddr, info, opc, i, operand_val); + } } + if (nslots > 1) + (*info->fprintf_func) (info->stream, " }"); + info->bytes_per_chunk = size; info->display_endian = info->endian; |