aboutsummaryrefslogtreecommitdiff
path: root/opcodes/xtensa-dis.c
diff options
context:
space:
mode:
Diffstat (limited to 'opcodes/xtensa-dis.c')
-rw-r--r--opcodes/xtensa-dis.c467
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;