Add Xtensa port
[deliverable/binutils-gdb.git] / opcodes / xtensa-dis.c
1 /* xtensa-dis.c. Disassembly functions for Xtensa.
2 Copyright 2003 Free Software Foundation, Inc.
3 Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com)
4
5 This file is part of GDB, GAS, and the GNU binutils.
6
7 GDB, GAS, and the GNU binutils are free software; you can redistribute
8 them and/or modify them under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either version 2,
10 or (at your option) any later version.
11
12 GDB, GAS, and the GNU binutils are distributed in the hope that they
13 will be useful, but WITHOUT ANY WARRANTY; without even the implied
14 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this file; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 USA. */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <string.h>
26 #include "xtensa-isa.h"
27 #include "ansidecl.h"
28 #include "sysdep.h"
29 #include "dis-asm.h"
30
31 #include <setjmp.h>
32
33 #ifndef MAX
34 #define MAX(a,b) (a > b ? a : b)
35 #endif
36
37 static char* state_names[256] =
38 {
39 "lbeg", /* 0 */
40 "lend", /* 1 */
41 "lcount", /* 2 */
42 "sar", /* 3 */
43 "br", /* 4 */
44
45 "reserved_5", /* 5 */
46 "reserved_6", /* 6 */
47 "reserved_7", /* 7 */
48
49 "av", /* 8 */
50 "avh", /* 9 */
51 "bv", /* 10 */
52 "sav", /* 11 */
53 "scompare1", /* 12 */
54
55 "reserved_13", /* 13 */
56 "reserved_14", /* 14 */
57 "reserved_15", /* 15 */
58
59 "acclo", /* 16 */
60 "acchi", /* 17 */
61
62 "reserved_18", /* 18 */
63 "reserved_19", /* 19 */
64 "reserved_20", /* 20 */
65 "reserved_21", /* 21 */
66 "reserved_22", /* 22 */
67 "reserved_23", /* 23 */
68 "reserved_24", /* 24 */
69 "reserved_25", /* 25 */
70 "reserved_26", /* 26 */
71 "reserved_27", /* 27 */
72 "reserved_28", /* 28 */
73 "reserved_29", /* 29 */
74 "reserved_30", /* 30 */
75 "reserved_31", /* 31 */
76
77 "mr0", /* 32 */
78 "mr1", /* 33 */
79 "mr2", /* 34 */
80 "mr3", /* 35 */
81
82 "reserved_36", /* 36 */
83 "reserved_37", /* 37 */
84 "reserved_38", /* 38 */
85 "reserved_39", /* 39 */
86 "reserved_40", /* 40 */
87 "reserved_41", /* 41 */
88 "reserved_42", /* 42 */
89 "reserved_43", /* 43 */
90 "reserved_44", /* 44 */
91 "reserved_45", /* 45 */
92 "reserved_46", /* 46 */
93 "reserved_47", /* 47 */
94 "reserved_48", /* 48 */
95 "reserved_49", /* 49 */
96 "reserved_50", /* 50 */
97 "reserved_51", /* 51 */
98 "reserved_52", /* 52 */
99 "reserved_53", /* 53 */
100 "reserved_54", /* 54 */
101 "reserved_55", /* 55 */
102 "reserved_56", /* 56 */
103 "reserved_57", /* 57 */
104 "reserved_58", /* 58 */
105 "reserved_59", /* 59 */
106 "reserved_60", /* 60 */
107 "reserved_61", /* 61 */
108 "reserved_62", /* 62 */
109 "reserved_63", /* 63 */
110
111 "reserved_64", /* 64 */
112 "reserved_65", /* 65 */
113 "reserved_66", /* 66 */
114 "reserved_67", /* 67 */
115 "reserved_68", /* 68 */
116 "reserved_69", /* 69 */
117 "reserved_70", /* 70 */
118 "reserved_71", /* 71 */
119
120 "wb", /* 72 */
121 "ws", /* 73 */
122
123 "reserved_74", /* 74 */
124 "reserved_75", /* 75 */
125 "reserved_76", /* 76 */
126 "reserved_77", /* 77 */
127 "reserved_78", /* 78 */
128 "reserved_79", /* 79 */
129 "reserved_80", /* 80 */
130 "reserved_81", /* 81 */
131 "reserved_82", /* 82 */
132
133 "ptevaddr", /* 83 */
134
135 "reserved_84", /* 84 */
136 "reserved_85", /* 85 */
137 "reserved_86", /* 86 */
138 "reserved_87", /* 87 */
139 "reserved_88", /* 88 */
140 "reserved_89", /* 89 */
141
142 "rasid", /* 90 */
143 "itlbcfg", /* 91 */
144 "dtlbcfg", /* 92 */
145
146 "reserved_93", /* 93 */
147 "reserved_94", /* 94 */
148 "reserved_95", /* 95 */
149
150 "ibreakenable", /* 96 */
151
152 "reserved_97", /* 97 */
153
154 "cacheattr", /* 98 */
155
156 "reserved_99", /* 99 */
157 "reserved_100", /* 100 */
158 "reserved_101", /* 101 */
159 "reserved_102", /* 102 */
160 "reserved_103", /* 103 */
161
162 "ddr", /* 104 */
163
164 "reserved_105", /* 105 */
165 "reserved_106", /* 106 */
166 "reserved_107", /* 107 */
167 "reserved_108", /* 108 */
168 "reserved_109", /* 109 */
169 "reserved_110", /* 110 */
170 "reserved_111", /* 111 */
171 "reserved_112", /* 112 */
172 "reserved_113", /* 113 */
173 "reserved_114", /* 114 */
174 "reserved_115", /* 115 */
175 "reserved_116", /* 116 */
176 "reserved_117", /* 117 */
177 "reserved_118", /* 118 */
178 "reserved_119", /* 119 */
179 "reserved_120", /* 120 */
180 "reserved_121", /* 121 */
181 "reserved_122", /* 122 */
182 "reserved_123", /* 123 */
183 "reserved_124", /* 124 */
184 "reserved_125", /* 125 */
185 "reserved_126", /* 126 */
186 "reserved_127", /* 127 */
187
188 "ibreaka0", /* 128 */
189 "ibreaka1", /* 129 */
190 "ibreaka2", /* 130 */
191 "ibreaka3", /* 131 */
192 "ibreaka4", /* 132 */
193 "ibreaka5", /* 133 */
194 "ibreaka6", /* 134 */
195 "ibreaka7", /* 135 */
196 "ibreaka8", /* 136 */
197 "ibreaka9", /* 137 */
198 "ibreaka10", /* 138 */
199 "ibreaka11", /* 139 */
200 "ibreaka12", /* 140 */
201 "ibreaka13", /* 141 */
202 "ibreaka14", /* 142 */
203 "ibreaka15", /* 143 */
204
205 "dbreaka0", /* 144 */
206 "dbreaka1", /* 145 */
207 "dbreaka2", /* 146 */
208 "dbreaka3", /* 147 */
209 "dbreaka4", /* 148 */
210 "dbreaka5", /* 149 */
211 "dbreaka6", /* 150 */
212 "dbreaka7", /* 151 */
213 "dbreaka8", /* 152 */
214 "dbreaka9", /* 153 */
215 "dbreaka10", /* 154 */
216 "dbreaka11", /* 155 */
217 "dbreaka12", /* 156 */
218 "dbreaka13", /* 157 */
219 "dbreaka14", /* 158 */
220 "dbreaka15", /* 159 */
221
222 "dbreakc0", /* 160 */
223 "dbreakc1", /* 161 */
224 "dbreakc2", /* 162 */
225 "dbreakc3", /* 163 */
226 "dbreakc4", /* 164 */
227 "dbreakc5", /* 165 */
228 "dbreakc6", /* 166 */
229 "dbreakc7", /* 167 */
230 "dbreakc8", /* 168 */
231 "dbreakc9", /* 169 */
232 "dbreakc10", /* 170 */
233 "dbreakc11", /* 171 */
234 "dbreakc12", /* 172 */
235 "dbreakc13", /* 173 */
236 "dbreakc14", /* 174 */
237 "dbreakc15", /* 175 */
238
239 "reserved_176", /* 176 */
240
241 "epc1", /* 177 */
242 "epc2", /* 178 */
243 "epc3", /* 179 */
244 "epc4", /* 180 */
245 "epc5", /* 181 */
246 "epc6", /* 182 */
247 "epc7", /* 183 */
248 "epc8", /* 184 */
249 "epc9", /* 185 */
250 "epc10", /* 186 */
251 "epc11", /* 187 */
252 "epc12", /* 188 */
253 "epc13", /* 189 */
254 "epc14", /* 190 */
255 "epc15", /* 191 */
256 "depc", /* 192 */
257
258 "reserved_193", /* 193 */
259
260 "eps2", /* 194 */
261 "eps3", /* 195 */
262 "eps4", /* 196 */
263 "eps5", /* 197 */
264 "eps6", /* 198 */
265 "eps7", /* 199 */
266 "eps8", /* 200 */
267 "eps9", /* 201 */
268 "eps10", /* 202 */
269 "eps11", /* 203 */
270 "eps12", /* 204 */
271 "eps13", /* 205 */
272 "eps14", /* 206 */
273 "eps15", /* 207 */
274
275 "reserved_208", /* 208 */
276
277 "excsave1", /* 209 */
278 "excsave2", /* 210 */
279 "excsave3", /* 211 */
280 "excsave4", /* 212 */
281 "excsave5", /* 213 */
282 "excsave6", /* 214 */
283 "excsave7", /* 215 */
284 "excsave8", /* 216 */
285 "excsave9", /* 217 */
286 "excsave10", /* 218 */
287 "excsave11", /* 219 */
288 "excsave12", /* 220 */
289 "excsave13", /* 221 */
290 "excsave14", /* 222 */
291 "excsave15", /* 223 */
292 "cpenable", /* 224 */
293
294 "reserved_225", /* 225 */
295
296 "interrupt", /* 226 */
297 "interrupt2", /* 227 */
298 "intenable", /* 228 */
299
300 "reserved_229", /* 229 */
301
302 "ps", /* 230 */
303
304 "reserved_231", /* 231 */
305
306 "exccause", /* 232 */
307 "debugcause", /* 233 */
308 "ccount", /* 234 */
309 "prid", /* 235 */
310 "icount", /* 236 */
311 "icountlvl", /* 237 */
312 "excvaddr", /* 238 */
313
314 "reserved_239", /* 239 */
315
316 "ccompare0", /* 240 */
317 "ccompare1", /* 241 */
318 "ccompare2", /* 242 */
319 "ccompare3", /* 243 */
320
321 "misc0", /* 244 */
322 "misc1", /* 245 */
323 "misc2", /* 246 */
324 "misc3", /* 247 */
325
326 "reserved_248", /* 248 */
327 "reserved_249", /* 249 */
328 "reserved_250", /* 250 */
329 "reserved_251", /* 251 */
330 "reserved_252", /* 252 */
331 "reserved_253", /* 253 */
332 "reserved_254", /* 254 */
333 "reserved_255", /* 255 */
334 };
335
336
337 int show_raw_fields;
338
339 static int fetch_data
340 PARAMS ((struct disassemble_info *info, bfd_vma memaddr, int numBytes));
341 static void print_xtensa_operand
342 PARAMS ((bfd_vma, struct disassemble_info *, xtensa_operand,
343 unsigned operand_val, int print_sr_name));
344
345 struct dis_private {
346 bfd_byte *byte_buf;
347 jmp_buf bailout;
348 };
349
350 static int
351 fetch_data (info, memaddr, numBytes)
352 struct disassemble_info *info;
353 bfd_vma memaddr;
354 int numBytes;
355 {
356 int length, status = 0;
357 struct dis_private *priv = (struct dis_private *) info->private_data;
358 int insn_size = (numBytes != 0 ? numBytes :
359 xtensa_insn_maxlength (xtensa_default_isa));
360
361 /* Read the maximum instruction size, padding with zeros if we go past
362 the end of the text section. This code will automatically adjust
363 length when we hit the end of the buffer. */
364
365 memset (priv->byte_buf, 0, insn_size);
366 for (length = insn_size; length > 0; length--)
367 {
368 status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
369 info);
370 if (status == 0)
371 return length;
372 }
373 (*info->memory_error_func) (status, memaddr, info);
374 longjmp (priv->bailout, 1);
375 /*NOTREACHED*/
376 }
377
378
379 static void
380 print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name)
381 bfd_vma memaddr;
382 struct disassemble_info *info;
383 xtensa_operand opnd;
384 unsigned operand_val;
385 int print_sr_name;
386 {
387 char *kind = xtensa_operand_kind (opnd);
388 int signed_operand_val;
389
390 if (show_raw_fields)
391 {
392 if (operand_val < 0xa)
393 (*info->fprintf_func) (info->stream, "%u", operand_val);
394 else
395 (*info->fprintf_func) (info->stream, "0x%x", operand_val);
396 return;
397 }
398
399 operand_val = xtensa_operand_decode (opnd, operand_val);
400 signed_operand_val = (int) operand_val;
401
402 if (xtensa_operand_isPCRelative (opnd))
403 {
404 operand_val = xtensa_operand_undo_reloc (opnd, operand_val, memaddr);
405 info->target = operand_val;
406 (*info->print_address_func) (info->target, info);
407 }
408 else if (!strcmp (kind, "i"))
409 {
410 if (print_sr_name
411 && signed_operand_val >= 0
412 && signed_operand_val <= 255)
413 (*info->fprintf_func) (info->stream, "%s",
414 state_names[signed_operand_val]);
415 else if ((signed_operand_val > -256) && (signed_operand_val < 256))
416 (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
417 else
418 (*info->fprintf_func) (info->stream, "0x%x",signed_operand_val);
419 }
420 else
421 (*info->fprintf_func) (info->stream, "%s%u", kind, operand_val);
422 }
423
424
425 /* Print the Xtensa instruction at address MEMADDR on info->stream.
426 Returns length of the instruction in bytes. */
427
428 int
429 print_insn_xtensa (memaddr, info)
430 bfd_vma memaddr;
431 struct disassemble_info *info;
432 {
433 unsigned operand_val;
434 int bytes_fetched, size, maxsize, i, noperands;
435 xtensa_isa isa;
436 xtensa_opcode opc;
437 char *op_name;
438 int print_sr_name;
439 struct dis_private priv;
440 static bfd_byte *byte_buf = NULL;
441 static xtensa_insnbuf insn_buffer = NULL;
442
443 if (!xtensa_default_isa)
444 (void) xtensa_isa_init ();
445
446 info->target = 0;
447 maxsize = xtensa_insn_maxlength (xtensa_default_isa);
448
449 /* Set bytes_per_line to control the amount of whitespace between the hex
450 values and the opcode. For Xtensa, we always print one "chunk" and we
451 vary bytes_per_chunk to determine how many bytes to print. (objdump
452 would apparently prefer that we set bytes_per_chunk to 1 and vary
453 bytes_per_line but that makes it hard to fit 64-bit instructions on
454 an 80-column screen.) The value of bytes_per_line here is not exactly
455 right, because objdump adds an extra space for each chunk so that the
456 amount of whitespace depends on the chunk size. Oh well, it's good
457 enough.... Note that we set the minimum size to 4 to accomodate
458 literal pools. */
459 info->bytes_per_line = MAX (maxsize, 4);
460
461 /* Allocate buffers the first time through. */
462 if (!insn_buffer)
463 insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
464 if (!byte_buf)
465 byte_buf = (bfd_byte *) malloc (MAX (maxsize, 4));
466
467 priv.byte_buf = byte_buf;
468
469 info->private_data = (PTR) &priv;
470 if (setjmp (priv.bailout) != 0)
471 /* Error return. */
472 return -1;
473
474 /* Don't set "isa" before the setjmp to keep the compiler from griping. */
475 isa = xtensa_default_isa;
476
477 /* Fetch the maximum size instruction. */
478 bytes_fetched = fetch_data (info, memaddr, 0);
479
480 /* Copy the bytes into the decode buffer. */
481 memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
482 sizeof (xtensa_insnbuf_word)));
483 xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf);
484
485 opc = xtensa_decode_insn (isa, insn_buffer);
486 if (opc == XTENSA_UNDEFINED
487 || ((size = xtensa_insn_length (isa, opc)) > bytes_fetched))
488 {
489 (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
490 return 1;
491 }
492
493 op_name = (char *) xtensa_opcode_name (isa, opc);
494 (*info->fprintf_func) (info->stream, "%s", op_name);
495
496 print_sr_name = (!strcasecmp (op_name, "wsr")
497 || !strcasecmp (op_name, "xsr")
498 || !strcasecmp (op_name, "rsr"));
499
500 /* Print the operands (if any). */
501 noperands = xtensa_num_operands (isa, opc);
502 if (noperands > 0)
503 {
504 int first = 1;
505
506 (*info->fprintf_func) (info->stream, "\t");
507 for (i = 0; i < noperands; i++)
508 {
509 xtensa_operand opnd = xtensa_get_operand (isa, opc, i);
510
511 if (first)
512 first = 0;
513 else
514 (*info->fprintf_func) (info->stream, ", ");
515 operand_val = xtensa_operand_get_field (opnd, insn_buffer);
516 print_xtensa_operand (memaddr, info, opnd, operand_val,
517 print_sr_name);
518 }
519 }
520
521 info->bytes_per_chunk = size;
522 info->display_endian = info->endian;
523
524 return size;
525 }
526
This page took 0.049182 seconds and 4 git commands to generate.