* gdb.dwarf2/dw2-basic.exp: Run on Hurd also.
[deliverable/binutils-gdb.git] / opcodes / xtensa-dis.c
... / ...
CommitLineData
1/* xtensa-dis.c. Disassembly functions for Xtensa.
2 Copyright 2003, 2004 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 "libiberty.h"
29#include "sysdep.h"
30#include "dis-asm.h"
31
32#include <setjmp.h>
33
34extern xtensa_isa xtensa_default_isa;
35
36#ifndef MAX
37#define MAX(a,b) (a > b ? a : b)
38#endif
39
40int show_raw_fields;
41
42static int fetch_data
43 PARAMS ((struct disassemble_info *, bfd_vma));
44static void print_xtensa_operand
45 PARAMS ((bfd_vma, struct disassemble_info *, xtensa_opcode, int, unsigned));
46
47struct dis_private
48{
49 bfd_byte *byte_buf;
50 jmp_buf bailout;
51};
52
53
54static int
55fetch_data (info, memaddr)
56 struct disassemble_info *info;
57 bfd_vma memaddr;
58{
59 int length, status = 0;
60 struct dis_private *priv = (struct dis_private *) info->private_data;
61 int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
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
82print_xtensa_operand (memaddr, info, opc, opnd, operand_val)
83 bfd_vma memaddr;
84 struct disassemble_info *info;
85 xtensa_opcode opc;
86 int opnd;
87 unsigned operand_val;
88{
89 xtensa_isa isa = xtensa_default_isa;
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
101 (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
102 signed_operand_val = (int) operand_val;
103
104 if (xtensa_operand_is_register (isa, opc, opnd) == 0)
105 {
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 }
113 else
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 }
120 }
121 else
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 }
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;
149 int bytes_fetched, size, maxsize, i, n, noperands, nslots;
150 xtensa_isa isa;
151 xtensa_opcode opc;
152 xtensa_format fmt;
153 struct dis_private priv;
154 static bfd_byte *byte_buf = NULL;
155 static xtensa_insnbuf insn_buffer = NULL;
156 static xtensa_insnbuf slot_buffer = NULL;
157 int first, first_slot, valid_insn;
158
159 if (!xtensa_default_isa)
160 xtensa_default_isa = xtensa_isa_init (0, 0);
161
162 info->target = 0;
163 maxsize = xtensa_isa_maxlength (xtensa_default_isa);
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)
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 }
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;
194 size = 0;
195 nslots = 0;
196
197 /* Fetch the maximum size instruction. */
198 bytes_fetched = fetch_data (info, memaddr);
199
200 /* Copy the bytes into the decode buffer. */
201 memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
202 sizeof (xtensa_insnbuf_word)));
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 }
225
226 if (!valid_insn)
227 {
228 (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
229 return 1;
230 }
231
232 if (nslots > 1)
233 (*info->fprintf_func) (info->stream, "{ ");
234
235 first_slot = 1;
236 for (n = 0; n < nslots; n++)
237 {
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));
247
248 /* Print the operands (if any). */
249 noperands = xtensa_opcode_num_operands (isa, opc);
250 first = 1;
251 for (i = 0; i < noperands; i++)
252 {
253 if (xtensa_operand_is_visible (isa, opc, i) == 0)
254 continue;
255 if (first)
256 {
257 (*info->fprintf_func) (info->stream, "\t");
258 first = 0;
259 }
260 else
261 (*info->fprintf_func) (info->stream, ", ");
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 }
267 }
268
269 if (nslots > 1)
270 (*info->fprintf_func) (info->stream, " }");
271
272 info->bytes_per_chunk = size;
273 info->display_endian = info->endian;
274
275 return size;
276}
277
This page took 0.023088 seconds and 4 git commands to generate.