gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / xtensa-dis.c
CommitLineData
e0001a05 1/* xtensa-dis.c. Disassembly functions for Xtensa.
b3adc24a 2 Copyright (C) 2003-2020 Free Software Foundation, Inc.
e0001a05
NC
3 Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com)
4
9b201bb5 5 This file is part of the GNU opcodes library.
e0001a05 6
9b201bb5
NC
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
e0001a05 11
9b201bb5
NC
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
e0001a05 16
9b201bb5
NC
17 You should have received a copy of the GNU General Public License
18 along with this file; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
e0001a05 21
df7b86aa 22#include "sysdep.h"
e0001a05
NC
23#include <stdlib.h>
24#include <stdio.h>
25#include <sys/types.h>
26#include <string.h>
27#include "xtensa-isa.h"
28#include "ansidecl.h"
43cd72b9 29#include "libiberty.h"
4b8e28c7
MF
30#include "bfd.h"
31#include "elf/xtensa.h"
88c1242d 32#include "disassemble.h"
e0001a05
NC
33
34#include <setjmp.h>
35
43cd72b9
BW
36extern xtensa_isa xtensa_default_isa;
37
e0001a05
NC
38#ifndef MAX
39#define MAX(a,b) (a > b ? a : b)
40#endif
41
e0001a05
NC
42int show_raw_fields;
43
43cd72b9
BW
44struct dis_private
45{
e0001a05 46 bfd_byte *byte_buf;
8df14d78 47 OPCODES_SIGJMP_BUF bailout;
4b8e28c7
MF
48 /* Persistent fields, valid for last_section only. */
49 asection *last_section;
50 property_table_entry *insn_table_entries;
51 int insn_table_entry_count;
52 /* Cached property table search position. */
53 bfd_vma insn_table_cur_addr;
54 int insn_table_cur_idx;
e0001a05
NC
55};
56
4b8e28c7
MF
57static void
58xtensa_coalesce_insn_tables (struct dis_private *priv)
59{
60 const int mask = ~(XTENSA_PROP_DATA | XTENSA_PROP_NO_TRANSFORM);
61 int count = priv->insn_table_entry_count;
62 int i, j;
63
64 /* Loop over all entries, combining adjacent ones that differ only in
65 the flag bits XTENSA_PROP_DATA and XTENSA_PROP_NO_TRANSFORM. */
66
67 for (i = j = 0; j < count; ++i)
68 {
69 property_table_entry *entry = priv->insn_table_entries + i;
70
71 *entry = priv->insn_table_entries[j];
72
73 for (++j; j < count; ++j)
74 {
75 property_table_entry *next = priv->insn_table_entries + j;
76 int fill = xtensa_compute_fill_extra_space (entry);
77 int size = entry->size + fill;
78
79 if (entry->address + size == next->address)
80 {
81 int entry_flags = entry->flags & mask;
82 int next_flags = next->flags & mask;
83
84 if (next_flags == entry_flags)
85 entry->size = next->address - entry->address + next->size;
86 else
87 break;
88 }
89 else
90 {
91 break;
92 }
93 }
94 }
95 priv->insn_table_entry_count = i;
96}
97
98static property_table_entry *
99xtensa_find_table_entry (bfd_vma memaddr, struct disassemble_info *info)
100{
101 struct dis_private *priv = (struct dis_private *) info->private_data;
102 int i;
103
104 if (priv->insn_table_entries == NULL
105 || priv->insn_table_entry_count < 0)
106 return NULL;
107
108 if (memaddr < priv->insn_table_cur_addr)
109 priv->insn_table_cur_idx = 0;
110
111 for (i = priv->insn_table_cur_idx; i < priv->insn_table_entry_count; ++i)
112 {
113 property_table_entry *block = priv->insn_table_entries + i;
114
115 if (block->size != 0)
116 {
117 if ((memaddr >= block->address
118 && memaddr < block->address + block->size)
119 || memaddr < block->address)
120 {
121 priv->insn_table_cur_addr = memaddr;
122 priv->insn_table_cur_idx = i;
123 return block;
124 }
125 }
126 }
127 return NULL;
128}
129
130/* Check whether an instruction crosses an instruction block boundary
131 (according to property tables).
132 If it does, return 0 (doesn't fit), else return 1. */
133
134static int
135xtensa_instruction_fits (bfd_vma memaddr, int size,
136 property_table_entry *insn_block)
137{
138 unsigned max_size;
139
140 /* If no property table info, assume it fits. */
141 if (insn_block == NULL || size <= 0)
142 return 1;
143
144 /* If too high, limit nextstop by the next insn address. */
145 if (insn_block->address > memaddr)
146 {
147 /* memaddr is not in an instruction block, but is followed by one. */
148 max_size = insn_block->address - memaddr;
149 }
150 else
151 {
152 /* memaddr is in an instruction block, go no further than the end. */
153 max_size = insn_block->address + insn_block->size - memaddr;
154 }
155
156 /* Crossing a boundary, doesn't "fit". */
157 if ((unsigned)size > max_size)
158 return 0;
159 return 1;
160}
43cd72b9 161
e0001a05 162static int
7fa3d080 163fetch_data (struct disassemble_info *info, bfd_vma memaddr)
e0001a05
NC
164{
165 int length, status = 0;
166 struct dis_private *priv = (struct dis_private *) info->private_data;
43cd72b9 167 int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
e0001a05 168
4b8e28c7
MF
169 insn_size = MAX (insn_size, 4);
170
e0001a05
NC
171 /* Read the maximum instruction size, padding with zeros if we go past
172 the end of the text section. This code will automatically adjust
173 length when we hit the end of the buffer. */
174
175 memset (priv->byte_buf, 0, insn_size);
176 for (length = insn_size; length > 0; length--)
177 {
178 status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
179 info);
180 if (status == 0)
181 return length;
182 }
183 (*info->memory_error_func) (status, memaddr, info);
8df14d78 184 OPCODES_SIGLONGJMP (priv->bailout, 1);
e0001a05
NC
185 /*NOTREACHED*/
186}
187
188
189static void
7fa3d080
BW
190print_xtensa_operand (bfd_vma memaddr,
191 struct disassemble_info *info,
192 xtensa_opcode opc,
193 int opnd,
194 unsigned operand_val)
e0001a05 195{
43cd72b9 196 xtensa_isa isa = xtensa_default_isa;
e0001a05 197 int signed_operand_val;
43e65147 198
e0001a05
NC
199 if (show_raw_fields)
200 {
201 if (operand_val < 0xa)
202 (*info->fprintf_func) (info->stream, "%u", operand_val);
203 else
204 (*info->fprintf_func) (info->stream, "0x%x", operand_val);
205 return;
206 }
207
43cd72b9 208 (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
e0001a05
NC
209 signed_operand_val = (int) operand_val;
210
43cd72b9 211 if (xtensa_operand_is_register (isa, opc, opnd) == 0)
e0001a05 212 {
43cd72b9
BW
213 if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
214 {
215 (void) xtensa_operand_undo_reloc (isa, opc, opnd,
216 &operand_val, memaddr);
217 info->target = operand_val;
218 (*info->print_address_func) (info->target, info);
219 }
e0001a05 220 else
43cd72b9
BW
221 {
222 if ((signed_operand_val > -256) && (signed_operand_val < 256))
223 (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
224 else
225 (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
226 }
e0001a05
NC
227 }
228 else
43cd72b9
BW
229 {
230 int i = 1;
231 xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
232 (*info->fprintf_func) (info->stream, "%s%u",
233 xtensa_regfile_shortname (isa, opnd_rf),
234 operand_val);
235 while (i < xtensa_operand_num_regs (isa, opc, opnd))
236 {
237 operand_val++;
238 (*info->fprintf_func) (info->stream, ":%s%u",
239 xtensa_regfile_shortname (isa, opnd_rf),
240 operand_val);
241 i++;
43e65147 242 }
43cd72b9 243 }
e0001a05
NC
244}
245
246
247/* Print the Xtensa instruction at address MEMADDR on info->stream.
248 Returns length of the instruction in bytes. */
249
250int
7fa3d080 251print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info)
e0001a05
NC
252{
253 unsigned operand_val;
43cd72b9 254 int bytes_fetched, size, maxsize, i, n, noperands, nslots;
e0001a05
NC
255 xtensa_isa isa;
256 xtensa_opcode opc;
43cd72b9 257 xtensa_format fmt;
4b8e28c7 258 static struct dis_private priv;
e0001a05
NC
259 static bfd_byte *byte_buf = NULL;
260 static xtensa_insnbuf insn_buffer = NULL;
43cd72b9 261 static xtensa_insnbuf slot_buffer = NULL;
ce72cd46 262 int first, first_slot, valid_insn;
4b8e28c7 263 property_table_entry *insn_block;
e0001a05
NC
264
265 if (!xtensa_default_isa)
43cd72b9 266 xtensa_default_isa = xtensa_isa_init (0, 0);
e0001a05
NC
267
268 info->target = 0;
43cd72b9 269 maxsize = xtensa_isa_maxlength (xtensa_default_isa);
e0001a05
NC
270
271 /* Set bytes_per_line to control the amount of whitespace between the hex
272 values and the opcode. For Xtensa, we always print one "chunk" and we
273 vary bytes_per_chunk to determine how many bytes to print. (objdump
274 would apparently prefer that we set bytes_per_chunk to 1 and vary
275 bytes_per_line but that makes it hard to fit 64-bit instructions on
276 an 80-column screen.) The value of bytes_per_line here is not exactly
277 right, because objdump adds an extra space for each chunk so that the
278 amount of whitespace depends on the chunk size. Oh well, it's good
279 enough.... Note that we set the minimum size to 4 to accomodate
280 literal pools. */
281 info->bytes_per_line = MAX (maxsize, 4);
282
283 /* Allocate buffers the first time through. */
284 if (!insn_buffer)
43cd72b9
BW
285 {
286 insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
287 slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
288 byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
289 }
e0001a05
NC
290
291 priv.byte_buf = byte_buf;
292
7fa3d080 293 info->private_data = (void *) &priv;
4b8e28c7
MF
294
295 /* Prepare instruction tables. */
296
297 if (info->section != NULL)
298 {
299 asection *section = info->section;
300
301 if (priv.last_section != section)
302 {
303 bfd *abfd = section->owner;
304
305 if (priv.last_section != NULL)
306 {
307 /* Reset insn_table_entries. */
308 priv.insn_table_entry_count = 0;
d96bf37b 309 free (priv.insn_table_entries);
4b8e28c7
MF
310 priv.insn_table_entries = NULL;
311 }
312 priv.last_section = section;
313
314 /* Read insn_table_entries. */
315 priv.insn_table_entry_count =
316 xtensa_read_table_entries (abfd, section,
317 &priv.insn_table_entries,
318 XTENSA_PROP_SEC_NAME, FALSE);
319 if (priv.insn_table_entry_count == 0)
320 {
d96bf37b 321 free (priv.insn_table_entries);
4b8e28c7
MF
322 priv.insn_table_entries = NULL;
323 /* Backwards compatibility support. */
324 priv.insn_table_entry_count =
325 xtensa_read_table_entries (abfd, section,
326 &priv.insn_table_entries,
327 XTENSA_INSN_SEC_NAME, FALSE);
328 }
329 priv.insn_table_cur_idx = 0;
330 xtensa_coalesce_insn_tables (&priv);
331 }
332 /* Else nothing to do, same section as last time. */
333 }
334
8df14d78 335 if (OPCODES_SIGSETJMP (priv.bailout) != 0)
e0001a05
NC
336 /* Error return. */
337 return -1;
338
e0001a05 339 /* Fetch the maximum size instruction. */
118fecd3 340 bytes_fetched = fetch_data (info, memaddr);
e0001a05 341
4b8e28c7 342 insn_block = xtensa_find_table_entry (memaddr, info);
43cd72b9 343
ce72cd46
AM
344 /* Don't set "isa" before the setjmp to keep the compiler from griping. */
345 isa = xtensa_default_isa;
346 size = 0;
347 nslots = 0;
348 valid_insn = 0;
349 fmt = 0;
4b8e28c7 350 if (!insn_block || (insn_block->flags & XTENSA_PROP_INSN))
43cd72b9 351 {
4b8e28c7
MF
352 /* Copy the bytes into the decode buffer. */
353 memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
354 sizeof (xtensa_insnbuf_word)));
355 xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf,
356 bytes_fetched);
357
358 fmt = xtensa_format_decode (isa, insn_buffer);
359 if (fmt != XTENSA_UNDEFINED
360 && ((size = xtensa_format_length (isa, fmt)) <= bytes_fetched)
361 && xtensa_instruction_fits (memaddr, size, insn_block))
43cd72b9 362 {
4b8e28c7
MF
363 /* Make sure all the opcodes are valid. */
364 valid_insn = 1;
365 nslots = xtensa_format_num_slots (isa, fmt);
366 for (n = 0; n < nslots; n++)
43cd72b9 367 {
4b8e28c7
MF
368 xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
369 if (xtensa_opcode_decode (isa, fmt, n, slot_buffer)
370 == XTENSA_UNDEFINED)
371 {
372 valid_insn = 0;
373 break;
374 }
43cd72b9
BW
375 }
376 }
377 }
e0001a05 378
43cd72b9 379 if (!valid_insn)
e0001a05 380 {
4b8e28c7
MF
381 if (insn_block && (insn_block->flags & XTENSA_PROP_LITERAL)
382 && (memaddr & 3) == 0 && bytes_fetched >= 4)
383 {
384 return 4;
385 }
386 else
387 {
388 (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
389 return 1;
390 }
e0001a05
NC
391 }
392
43cd72b9
BW
393 if (nslots > 1)
394 (*info->fprintf_func) (info->stream, "{ ");
e0001a05 395
43cd72b9
BW
396 first_slot = 1;
397 for (n = 0; n < nslots; n++)
e0001a05 398 {
43cd72b9
BW
399 if (first_slot)
400 first_slot = 0;
401 else
402 (*info->fprintf_func) (info->stream, "; ");
403
404 xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
405 opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
406 (*info->fprintf_func) (info->stream, "%s",
407 xtensa_opcode_name (isa, opc));
e0001a05 408
43cd72b9
BW
409 /* Print the operands (if any). */
410 noperands = xtensa_opcode_num_operands (isa, opc);
411 first = 1;
e0001a05
NC
412 for (i = 0; i < noperands; i++)
413 {
43cd72b9
BW
414 if (xtensa_operand_is_visible (isa, opc, i) == 0)
415 continue;
e0001a05 416 if (first)
43cd72b9
BW
417 {
418 (*info->fprintf_func) (info->stream, "\t");
419 first = 0;
420 }
e0001a05
NC
421 else
422 (*info->fprintf_func) (info->stream, ", ");
43cd72b9
BW
423 (void) xtensa_operand_get_field (isa, opc, i, fmt, n,
424 slot_buffer, &operand_val);
425
426 print_xtensa_operand (memaddr, info, opc, i, operand_val);
427 }
e0001a05
NC
428 }
429
43cd72b9
BW
430 if (nslots > 1)
431 (*info->fprintf_func) (info->stream, " }");
432
e0001a05
NC
433 info->bytes_per_chunk = size;
434 info->display_endian = info->endian;
435
436 return size;
437}
438
This page took 0.819161 seconds and 4 git commands to generate.