1 /* xtensa-dis.c. Disassembly functions for Xtensa.
2 Copyright (C) 2003-2019 Free Software Foundation, Inc.
3 Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com)
5 This file is part of the GNU opcodes library.
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)
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.
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. */
25 #include <sys/types.h>
27 #include "xtensa-isa.h"
29 #include "libiberty.h"
31 #include "elf/xtensa.h"
32 #include "disassemble.h"
36 extern xtensa_isa xtensa_default_isa
;
39 #define MAX(a,b) (a > b ? a : b)
47 OPCODES_SIGJMP_BUF bailout
;
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
;
58 xtensa_coalesce_insn_tables (struct dis_private
*priv
)
60 const int mask
= ~(XTENSA_PROP_DATA
| XTENSA_PROP_NO_TRANSFORM
);
61 int count
= priv
->insn_table_entry_count
;
64 /* Loop over all entries, combining adjacent ones that differ only in
65 the flag bits XTENSA_PROP_DATA and XTENSA_PROP_NO_TRANSFORM. */
67 for (i
= j
= 0; j
< count
; ++i
)
69 property_table_entry
*entry
= priv
->insn_table_entries
+ i
;
71 *entry
= priv
->insn_table_entries
[j
];
73 for (++j
; j
< count
; ++j
)
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
;
79 if (entry
->address
+ size
== next
->address
)
81 int entry_flags
= entry
->flags
& mask
;
82 int next_flags
= next
->flags
& mask
;
84 if (next_flags
== entry_flags
)
85 entry
->size
= next
->address
- entry
->address
+ next
->size
;
95 priv
->insn_table_entry_count
= i
;
98 static property_table_entry
*
99 xtensa_find_table_entry (bfd_vma memaddr
, struct disassemble_info
*info
)
101 struct dis_private
*priv
= (struct dis_private
*) info
->private_data
;
104 if (priv
->insn_table_entries
== NULL
105 || priv
->insn_table_entry_count
< 0)
108 if (memaddr
< priv
->insn_table_cur_addr
)
109 priv
->insn_table_cur_idx
= 0;
111 for (i
= priv
->insn_table_cur_idx
; i
< priv
->insn_table_entry_count
; ++i
)
113 property_table_entry
*block
= priv
->insn_table_entries
+ i
;
115 if (block
->size
!= 0)
117 if ((memaddr
>= block
->address
118 && memaddr
< block
->address
+ block
->size
)
119 || memaddr
< block
->address
)
121 priv
->insn_table_cur_addr
= memaddr
;
122 priv
->insn_table_cur_idx
= i
;
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. */
135 xtensa_instruction_fits (bfd_vma memaddr
, int size
,
136 property_table_entry
*insn_block
)
140 /* If no property table info, assume it fits. */
141 if (insn_block
== NULL
|| size
<= 0)
144 /* If too high, limit nextstop by the next insn address. */
145 if (insn_block
->address
> memaddr
)
147 /* memaddr is not in an instruction block, but is followed by one. */
148 max_size
= insn_block
->address
- memaddr
;
152 /* memaddr is in an instruction block, go no further than the end. */
153 max_size
= insn_block
->address
+ insn_block
->size
- memaddr
;
156 /* Crossing a boundary, doesn't "fit". */
157 if ((unsigned)size
> max_size
)
163 fetch_data (struct disassemble_info
*info
, bfd_vma memaddr
)
165 int length
, status
= 0;
166 struct dis_private
*priv
= (struct dis_private
*) info
->private_data
;
167 int insn_size
= xtensa_isa_maxlength (xtensa_default_isa
);
169 insn_size
= MAX (insn_size
, 4);
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. */
175 memset (priv
->byte_buf
, 0, insn_size
);
176 for (length
= insn_size
; length
> 0; length
--)
178 status
= (*info
->read_memory_func
) (memaddr
, priv
->byte_buf
, length
,
183 (*info
->memory_error_func
) (status
, memaddr
, info
);
184 OPCODES_SIGLONGJMP (priv
->bailout
, 1);
190 print_xtensa_operand (bfd_vma memaddr
,
191 struct disassemble_info
*info
,
194 unsigned operand_val
)
196 xtensa_isa isa
= xtensa_default_isa
;
197 int signed_operand_val
;
201 if (operand_val
< 0xa)
202 (*info
->fprintf_func
) (info
->stream
, "%u", operand_val
);
204 (*info
->fprintf_func
) (info
->stream
, "0x%x", operand_val
);
208 (void) xtensa_operand_decode (isa
, opc
, opnd
, &operand_val
);
209 signed_operand_val
= (int) operand_val
;
211 if (xtensa_operand_is_register (isa
, opc
, opnd
) == 0)
213 if (xtensa_operand_is_PCrelative (isa
, opc
, opnd
) == 1)
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
);
222 if ((signed_operand_val
> -256) && (signed_operand_val
< 256))
223 (*info
->fprintf_func
) (info
->stream
, "%d", signed_operand_val
);
225 (*info
->fprintf_func
) (info
->stream
, "0x%x", signed_operand_val
);
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
),
235 while (i
< xtensa_operand_num_regs (isa
, opc
, opnd
))
238 (*info
->fprintf_func
) (info
->stream
, ":%s%u",
239 xtensa_regfile_shortname (isa
, opnd_rf
),
247 /* Print the Xtensa instruction at address MEMADDR on info->stream.
248 Returns length of the instruction in bytes. */
251 print_insn_xtensa (bfd_vma memaddr
, struct disassemble_info
*info
)
253 unsigned operand_val
;
254 int bytes_fetched
, size
, maxsize
, i
, n
, noperands
, nslots
;
258 static struct dis_private priv
;
259 static bfd_byte
*byte_buf
= NULL
;
260 static xtensa_insnbuf insn_buffer
= NULL
;
261 static xtensa_insnbuf slot_buffer
= NULL
;
262 int first
, first_slot
, valid_insn
;
263 property_table_entry
*insn_block
;
265 if (!xtensa_default_isa
)
266 xtensa_default_isa
= xtensa_isa_init (0, 0);
269 maxsize
= xtensa_isa_maxlength (xtensa_default_isa
);
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
281 info
->bytes_per_line
= MAX (maxsize
, 4);
283 /* Allocate buffers the first time through. */
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));
291 priv
.byte_buf
= byte_buf
;
293 info
->private_data
= (void *) &priv
;
295 /* Prepare instruction tables. */
297 if (info
->section
!= NULL
)
299 asection
*section
= info
->section
;
301 if (priv
.last_section
!= section
)
303 bfd
*abfd
= section
->owner
;
305 if (priv
.last_section
!= NULL
)
307 /* Reset insn_table_entries. */
308 priv
.insn_table_entry_count
= 0;
309 if (priv
.insn_table_entries
)
310 free (priv
.insn_table_entries
);
311 priv
.insn_table_entries
= NULL
;
313 priv
.last_section
= section
;
315 /* Read insn_table_entries. */
316 priv
.insn_table_entry_count
=
317 xtensa_read_table_entries (abfd
, section
,
318 &priv
.insn_table_entries
,
319 XTENSA_PROP_SEC_NAME
, FALSE
);
320 if (priv
.insn_table_entry_count
== 0)
322 if (priv
.insn_table_entries
)
323 free (priv
.insn_table_entries
);
324 priv
.insn_table_entries
= NULL
;
325 /* Backwards compatibility support. */
326 priv
.insn_table_entry_count
=
327 xtensa_read_table_entries (abfd
, section
,
328 &priv
.insn_table_entries
,
329 XTENSA_INSN_SEC_NAME
, FALSE
);
331 priv
.insn_table_cur_idx
= 0;
332 xtensa_coalesce_insn_tables (&priv
);
334 /* Else nothing to do, same section as last time. */
337 if (OPCODES_SIGSETJMP (priv
.bailout
) != 0)
341 /* Fetch the maximum size instruction. */
342 bytes_fetched
= fetch_data (info
, memaddr
);
344 insn_block
= xtensa_find_table_entry (memaddr
, info
);
346 /* Don't set "isa" before the setjmp to keep the compiler from griping. */
347 isa
= xtensa_default_isa
;
352 if (!insn_block
|| (insn_block
->flags
& XTENSA_PROP_INSN
))
354 /* Copy the bytes into the decode buffer. */
355 memset (insn_buffer
, 0, (xtensa_insnbuf_size (isa
) *
356 sizeof (xtensa_insnbuf_word
)));
357 xtensa_insnbuf_from_chars (isa
, insn_buffer
, priv
.byte_buf
,
360 fmt
= xtensa_format_decode (isa
, insn_buffer
);
361 if (fmt
!= XTENSA_UNDEFINED
362 && ((size
= xtensa_format_length (isa
, fmt
)) <= bytes_fetched
)
363 && xtensa_instruction_fits (memaddr
, size
, insn_block
))
365 /* Make sure all the opcodes are valid. */
367 nslots
= xtensa_format_num_slots (isa
, fmt
);
368 for (n
= 0; n
< nslots
; n
++)
370 xtensa_format_get_slot (isa
, fmt
, n
, insn_buffer
, slot_buffer
);
371 if (xtensa_opcode_decode (isa
, fmt
, n
, slot_buffer
)
383 if (insn_block
&& (insn_block
->flags
& XTENSA_PROP_LITERAL
)
384 && (memaddr
& 3) == 0 && bytes_fetched
>= 4)
390 (*info
->fprintf_func
) (info
->stream
, ".byte %#02x", priv
.byte_buf
[0]);
396 (*info
->fprintf_func
) (info
->stream
, "{ ");
399 for (n
= 0; n
< nslots
; n
++)
404 (*info
->fprintf_func
) (info
->stream
, "; ");
406 xtensa_format_get_slot (isa
, fmt
, n
, insn_buffer
, slot_buffer
);
407 opc
= xtensa_opcode_decode (isa
, fmt
, n
, slot_buffer
);
408 (*info
->fprintf_func
) (info
->stream
, "%s",
409 xtensa_opcode_name (isa
, opc
));
411 /* Print the operands (if any). */
412 noperands
= xtensa_opcode_num_operands (isa
, opc
);
414 for (i
= 0; i
< noperands
; i
++)
416 if (xtensa_operand_is_visible (isa
, opc
, i
) == 0)
420 (*info
->fprintf_func
) (info
->stream
, "\t");
424 (*info
->fprintf_func
) (info
->stream
, ", ");
425 (void) xtensa_operand_get_field (isa
, opc
, i
, fmt
, n
,
426 slot_buffer
, &operand_val
);
428 print_xtensa_operand (memaddr
, info
, opc
, i
, operand_val
);
433 (*info
->fprintf_func
) (info
->stream
, " }");
435 info
->bytes_per_chunk
= size
;
436 info
->display_endian
= info
->endian
;