00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <sys/types.h>
00029 #include <string.h>
00030 #include "xtensa-isa.h"
00031 #include "ansidecl.h"
00032 #include "libiberty.h"
00033 #include "sysdep.h"
00034 #include "dis-asm.h"
00035
00036 #include <setjmp.h>
00037
00038 extern xtensa_isa xtensa_default_isa;
00039
00040 #ifndef MAX
00041 #define MAX(a,b) (a > b ? a : b)
00042 #endif
00043
00044 int show_raw_fields;
00045
00046 struct dis_private
00047 {
00048 bfd_byte *byte_buf;
00049 jmp_buf bailout;
00050 };
00051
00052
00053 static int
00054 fetch_data (struct disassemble_info *info, bfd_vma memaddr)
00055 {
00056 int length, status = 0;
00057 struct dis_private *priv = (struct dis_private *) info->private_data;
00058 int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
00059
00060
00061
00062
00063
00064 memset (priv->byte_buf, 0, insn_size);
00065 for (length = insn_size; length > 0; length--)
00066 {
00067 status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
00068 info);
00069 if (status == 0)
00070 return length;
00071 }
00072 (*info->memory_error_func) (status, memaddr, info);
00073 longjmp (priv->bailout, 1);
00074
00075 }
00076
00077
00078 static void
00079 print_xtensa_operand (bfd_vma memaddr,
00080 struct disassemble_info *info,
00081 xtensa_opcode opc,
00082 int opnd,
00083 unsigned operand_val)
00084 {
00085 xtensa_isa isa = xtensa_default_isa;
00086 int signed_operand_val;
00087
00088 if (show_raw_fields)
00089 {
00090 if (operand_val < 0xa)
00091 (*info->fprintf_func) (info->stream, "%u", operand_val);
00092 else
00093 (*info->fprintf_func) (info->stream, "0x%x", operand_val);
00094 return;
00095 }
00096
00097 (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
00098 signed_operand_val = (int) operand_val;
00099
00100 if (xtensa_operand_is_register (isa, opc, opnd) == 0)
00101 {
00102 if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
00103 {
00104 (void) xtensa_operand_undo_reloc (isa, opc, opnd,
00105 &operand_val, memaddr);
00106 info->target = operand_val;
00107 (*info->print_address_func) (info->target, info);
00108 }
00109 else
00110 {
00111 if ((signed_operand_val > -256) && (signed_operand_val < 256))
00112 (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
00113 else
00114 (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
00115 }
00116 }
00117 else
00118 {
00119 int i = 1;
00120 xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
00121 (*info->fprintf_func) (info->stream, "%s%u",
00122 xtensa_regfile_shortname (isa, opnd_rf),
00123 operand_val);
00124 while (i < xtensa_operand_num_regs (isa, opc, opnd))
00125 {
00126 operand_val++;
00127 (*info->fprintf_func) (info->stream, ":%s%u",
00128 xtensa_regfile_shortname (isa, opnd_rf),
00129 operand_val);
00130 i++;
00131 }
00132 }
00133 }
00134
00135
00136
00137
00138
00139 int
00140 print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info)
00141 {
00142 unsigned operand_val;
00143 int bytes_fetched, size, maxsize, i, n, noperands, nslots;
00144 xtensa_isa isa;
00145 xtensa_opcode opc;
00146 xtensa_format fmt;
00147 struct dis_private priv;
00148 static bfd_byte *byte_buf = NULL;
00149 static xtensa_insnbuf insn_buffer = NULL;
00150 static xtensa_insnbuf slot_buffer = NULL;
00151 int first, first_slot, valid_insn;
00152
00153 if (!xtensa_default_isa)
00154 xtensa_default_isa = xtensa_isa_init (0, 0);
00155
00156 info->target = 0;
00157 maxsize = xtensa_isa_maxlength (xtensa_default_isa);
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 info->bytes_per_line = MAX (maxsize, 4);
00170
00171
00172 if (!insn_buffer)
00173 {
00174 insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
00175 slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
00176 byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
00177 }
00178
00179 priv.byte_buf = byte_buf;
00180
00181 info->private_data = (void *) &priv;
00182 if (setjmp (priv.bailout) != 0)
00183
00184 return -1;
00185
00186
00187 isa = xtensa_default_isa;
00188 size = 0;
00189 nslots = 0;
00190
00191
00192 bytes_fetched = fetch_data (info, memaddr);
00193
00194
00195 memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
00196 sizeof (xtensa_insnbuf_word)));
00197 xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf, bytes_fetched);
00198
00199 fmt = xtensa_format_decode (isa, insn_buffer);
00200 if (fmt == XTENSA_UNDEFINED
00201 || ((size = xtensa_format_length (isa, fmt)) > bytes_fetched))
00202 valid_insn = 0;
00203 else
00204 {
00205
00206 valid_insn = 1;
00207 nslots = xtensa_format_num_slots (isa, fmt);
00208 for (n = 0; n < nslots; n++)
00209 {
00210 xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
00211 if (xtensa_opcode_decode (isa, fmt, n, slot_buffer)
00212 == XTENSA_UNDEFINED)
00213 {
00214 valid_insn = 0;
00215 break;
00216 }
00217 }
00218 }
00219
00220 if (!valid_insn)
00221 {
00222 (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
00223 return 1;
00224 }
00225
00226 if (nslots > 1)
00227 (*info->fprintf_func) (info->stream, "{ ");
00228
00229 first_slot = 1;
00230 for (n = 0; n < nslots; n++)
00231 {
00232 if (first_slot)
00233 first_slot = 0;
00234 else
00235 (*info->fprintf_func) (info->stream, "; ");
00236
00237 xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
00238 opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
00239 (*info->fprintf_func) (info->stream, "%s",
00240 xtensa_opcode_name (isa, opc));
00241
00242
00243 noperands = xtensa_opcode_num_operands (isa, opc);
00244 first = 1;
00245 for (i = 0; i < noperands; i++)
00246 {
00247 if (xtensa_operand_is_visible (isa, opc, i) == 0)
00248 continue;
00249 if (first)
00250 {
00251 (*info->fprintf_func) (info->stream, "\t");
00252 first = 0;
00253 }
00254 else
00255 (*info->fprintf_func) (info->stream, ", ");
00256 (void) xtensa_operand_get_field (isa, opc, i, fmt, n,
00257 slot_buffer, &operand_val);
00258
00259 print_xtensa_operand (memaddr, info, opc, i, operand_val);
00260 }
00261 }
00262
00263 if (nslots > 1)
00264 (*info->fprintf_func) (info->stream, " }");
00265
00266 info->bytes_per_chunk = size;
00267 info->display_endian = info->endian;
00268
00269 return size;
00270 }
00271