* gdb.dwarf2/dw2-basic.exp: Run on Hurd also.
[deliverable/binutils-gdb.git] / opcodes / xtensa-dis.c
CommitLineData
e0001a05 1/* xtensa-dis.c. Disassembly functions for Xtensa.
43cd72b9 2 Copyright 2003, 2004 Free Software Foundation, Inc.
e0001a05
NC
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"
43cd72b9 28#include "libiberty.h"
e0001a05
NC
29#include "sysdep.h"
30#include "dis-asm.h"
31
32#include <setjmp.h>
33
43cd72b9
BW
34extern xtensa_isa xtensa_default_isa;
35
e0001a05
NC
36#ifndef MAX
37#define MAX(a,b) (a > b ? a : b)
38#endif
39
e0001a05
NC
40int show_raw_fields;
41
42static int fetch_data
43cd72b9 43 PARAMS ((struct disassemble_info *, bfd_vma));
e0001a05 44static void print_xtensa_operand
43cd72b9 45 PARAMS ((bfd_vma, struct disassemble_info *, xtensa_opcode, int, unsigned));
e0001a05 46
43cd72b9
BW
47struct dis_private
48{
e0001a05
NC
49 bfd_byte *byte_buf;
50 jmp_buf bailout;
51};
52
43cd72b9 53
e0001a05 54static int
118fecd3 55fetch_data (info, memaddr)
e0001a05
NC
56 struct disassemble_info *info;
57 bfd_vma memaddr;
e0001a05
NC
58{
59 int length, status = 0;
60 struct dis_private *priv = (struct dis_private *) info->private_data;
43cd72b9 61 int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
e0001a05
NC
62
63 /* Read the maximum instruction size, padding with zeros if we go past
64 the end of the text section. This code will automatically adjust
65 length when we hit the end of the buffer. */
66
67 memset (priv->byte_buf, 0, insn_size);
68 for (length = insn_size; length > 0; length--)
69 {
70 status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
71 info);
72 if (status == 0)
73 return length;
74 }
75 (*info->memory_error_func) (status, memaddr, info);
76 longjmp (priv->bailout, 1);
77 /*NOTREACHED*/
78}
79
80
81static void
43cd72b9 82print_xtensa_operand (memaddr, info, opc, opnd, operand_val)
e0001a05
NC
83 bfd_vma memaddr;
84 struct disassemble_info *info;
43cd72b9
BW
85 xtensa_opcode opc;
86 int opnd;
e0001a05 87 unsigned operand_val;
e0001a05 88{
43cd72b9 89 xtensa_isa isa = xtensa_default_isa;
e0001a05
NC
90 int signed_operand_val;
91
92 if (show_raw_fields)
93 {
94 if (operand_val < 0xa)
95 (*info->fprintf_func) (info->stream, "%u", operand_val);
96 else
97 (*info->fprintf_func) (info->stream, "0x%x", operand_val);
98 return;
99 }
100
43cd72b9 101 (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
e0001a05
NC
102 signed_operand_val = (int) operand_val;
103
43cd72b9 104 if (xtensa_operand_is_register (isa, opc, opnd) == 0)
e0001a05 105 {
43cd72b9
BW
106 if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
107 {
108 (void) xtensa_operand_undo_reloc (isa, opc, opnd,
109 &operand_val, memaddr);
110 info->target = operand_val;
111 (*info->print_address_func) (info->target, info);
112 }
e0001a05 113 else
43cd72b9
BW
114 {
115 if ((signed_operand_val > -256) && (signed_operand_val < 256))
116 (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
117 else
118 (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
119 }
e0001a05
NC
120 }
121 else
43cd72b9
BW
122 {
123 int i = 1;
124 xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
125 (*info->fprintf_func) (info->stream, "%s%u",
126 xtensa_regfile_shortname (isa, opnd_rf),
127 operand_val);
128 while (i < xtensa_operand_num_regs (isa, opc, opnd))
129 {
130 operand_val++;
131 (*info->fprintf_func) (info->stream, ":%s%u",
132 xtensa_regfile_shortname (isa, opnd_rf),
133 operand_val);
134 i++;
135 }
136 }
e0001a05
NC
137}
138
139
140/* Print the Xtensa instruction at address MEMADDR on info->stream.
141 Returns length of the instruction in bytes. */
142
143int
144print_insn_xtensa (memaddr, info)
145 bfd_vma memaddr;
146 struct disassemble_info *info;
147{
148 unsigned operand_val;
43cd72b9 149 int bytes_fetched, size, maxsize, i, n, noperands, nslots;
e0001a05
NC
150 xtensa_isa isa;
151 xtensa_opcode opc;
43cd72b9 152 xtensa_format fmt;
e0001a05
NC
153 struct dis_private priv;
154 static bfd_byte *byte_buf = NULL;
155 static xtensa_insnbuf insn_buffer = NULL;
43cd72b9
BW
156 static xtensa_insnbuf slot_buffer = NULL;
157 int first, first_slot, valid_insn;
e0001a05
NC
158
159 if (!xtensa_default_isa)
43cd72b9 160 xtensa_default_isa = xtensa_isa_init (0, 0);
e0001a05
NC
161
162 info->target = 0;
43cd72b9 163 maxsize = xtensa_isa_maxlength (xtensa_default_isa);
e0001a05
NC
164
165 /* Set bytes_per_line to control the amount of whitespace between the hex
166 values and the opcode. For Xtensa, we always print one "chunk" and we
167 vary bytes_per_chunk to determine how many bytes to print. (objdump
168 would apparently prefer that we set bytes_per_chunk to 1 and vary
169 bytes_per_line but that makes it hard to fit 64-bit instructions on
170 an 80-column screen.) The value of bytes_per_line here is not exactly
171 right, because objdump adds an extra space for each chunk so that the
172 amount of whitespace depends on the chunk size. Oh well, it's good
173 enough.... Note that we set the minimum size to 4 to accomodate
174 literal pools. */
175 info->bytes_per_line = MAX (maxsize, 4);
176
177 /* Allocate buffers the first time through. */
178 if (!insn_buffer)
43cd72b9
BW
179 {
180 insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
181 slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
182 byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
183 }
e0001a05
NC
184
185 priv.byte_buf = byte_buf;
186
187 info->private_data = (PTR) &priv;
188 if (setjmp (priv.bailout) != 0)
189 /* Error return. */
190 return -1;
191
192 /* Don't set "isa" before the setjmp to keep the compiler from griping. */
193 isa = xtensa_default_isa;
43cd72b9
BW
194 size = 0;
195 nslots = 0;
e0001a05
NC
196
197 /* Fetch the maximum size instruction. */
118fecd3 198 bytes_fetched = fetch_data (info, memaddr);
e0001a05
NC
199
200 /* Copy the bytes into the decode buffer. */
201 memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
202 sizeof (xtensa_insnbuf_word)));
43cd72b9
BW
203 xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf, bytes_fetched);
204
205 fmt = xtensa_format_decode (isa, insn_buffer);
206 if (fmt == XTENSA_UNDEFINED
207 || ((size = xtensa_format_length (isa, fmt)) > bytes_fetched))
208 valid_insn = 0;
209 else
210 {
211 /* Make sure all the opcodes are valid. */
212 valid_insn = 1;
213 nslots = xtensa_format_num_slots (isa, fmt);
214 for (n = 0; n < nslots; n++)
215 {
216 xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
217 if (xtensa_opcode_decode (isa, fmt, n, slot_buffer)
218 == XTENSA_UNDEFINED)
219 {
220 valid_insn = 0;
221 break;
222 }
223 }
224 }
e0001a05 225
43cd72b9 226 if (!valid_insn)
e0001a05
NC
227 {
228 (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
229 return 1;
230 }
231
43cd72b9
BW
232 if (nslots > 1)
233 (*info->fprintf_func) (info->stream, "{ ");
e0001a05 234
43cd72b9
BW
235 first_slot = 1;
236 for (n = 0; n < nslots; n++)
e0001a05 237 {
43cd72b9
BW
238 if (first_slot)
239 first_slot = 0;
240 else
241 (*info->fprintf_func) (info->stream, "; ");
242
243 xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
244 opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
245 (*info->fprintf_func) (info->stream, "%s",
246 xtensa_opcode_name (isa, opc));
e0001a05 247
43cd72b9
BW
248 /* Print the operands (if any). */
249 noperands = xtensa_opcode_num_operands (isa, opc);
250 first = 1;
e0001a05
NC
251 for (i = 0; i < noperands; i++)
252 {
43cd72b9
BW
253 if (xtensa_operand_is_visible (isa, opc, i) == 0)
254 continue;
e0001a05 255 if (first)
43cd72b9
BW
256 {
257 (*info->fprintf_func) (info->stream, "\t");
258 first = 0;
259 }
e0001a05
NC
260 else
261 (*info->fprintf_func) (info->stream, ", ");
43cd72b9
BW
262 (void) xtensa_operand_get_field (isa, opc, i, fmt, n,
263 slot_buffer, &operand_val);
264
265 print_xtensa_operand (memaddr, info, opc, i, operand_val);
266 }
e0001a05
NC
267 }
268
43cd72b9
BW
269 if (nslots > 1)
270 (*info->fprintf_func) (info->stream, " }");
271
e0001a05
NC
272 info->bytes_per_chunk = size;
273 info->display_endian = info->endian;
274
275 return size;
276}
277
This page took 0.104738 seconds and 4 git commands to generate.