1 /* xtensa-dis.c. Disassembly functions for Xtensa. 2 Copyright (C) 2003-2020 Free Software Foundation, Inc. 3 Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com) 4 5 This file is part of the GNU opcodes library. 6 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. 11 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. 16 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. */ 21 22 #include "sysdep.h" 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" 29 #include "libiberty.h" 30 #include "bfd.h" 31 #include "elf/xtensa.h" 32 #include "disassemble.h" 33 34 #include <setjmp.h> 35 36 extern xtensa_isa xtensa_default_isa; 37 38 #ifndef MAX 39 #define MAX(a,b) (a > b ? a : b) 40 #endif 41 42 int show_raw_fields; 43 44 struct dis_private 45 { 46 bfd_byte *byte_buf; 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; 55 }; 56 57 static void 58 xtensa_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 98 static property_table_entry * 99 xtensa_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 134 static int 135 xtensa_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 } 161 162 static int 163 fetch_data (struct disassemble_info *info, bfd_vma memaddr) 164 { 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); 168 169 insn_size = MAX (insn_size, 4); 170 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); 184 OPCODES_SIGLONGJMP (priv->bailout, 1); 185 /*NOTREACHED*/ 186 } 187 188 189 static void 190 print_xtensa_operand (bfd_vma memaddr, 191 struct disassemble_info *info, 192 xtensa_opcode opc, 193 int opnd, 194 unsigned operand_val) 195 { 196 xtensa_isa isa = xtensa_default_isa; 197 int signed_operand_val; 198 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 208 (void) xtensa_operand_decode (isa, opc, opnd, &operand_val); 209 signed_operand_val = (int) operand_val; 210 211 if (xtensa_operand_is_register (isa, opc, opnd) == 0) 212 { 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 } 220 else 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 } 227 } 228 else 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++; 242 } 243 } 244 } 245 246 247 /* Print the Xtensa instruction at address MEMADDR on info->stream. 248 Returns length of the instruction in bytes. */ 249 250 int 251 print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info) 252 { 253 unsigned operand_val; 254 int bytes_fetched, size, maxsize, i, n, noperands, nslots; 255 xtensa_isa isa; 256 xtensa_opcode opc; 257 xtensa_format fmt; 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; 264 265 if (!xtensa_default_isa) 266 xtensa_default_isa = xtensa_isa_init (0, 0); 267 268 info->target = 0; 269 maxsize = xtensa_isa_maxlength (xtensa_default_isa); 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) 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 } 290 291 priv.byte_buf = byte_buf; 292 293 info->private_data = (void *) &priv; 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; 309 free (priv.insn_table_entries); 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 { 321 free (priv.insn_table_entries); 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 335 if (OPCODES_SIGSETJMP (priv.bailout) != 0) 336 /* Error return. */ 337 return -1; 338 339 /* Fetch the maximum size instruction. */ 340 bytes_fetched = fetch_data (info, memaddr); 341 342 insn_block = xtensa_find_table_entry (memaddr, info); 343 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; 350 if (!insn_block || (insn_block->flags & XTENSA_PROP_INSN)) 351 { 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)) 362 { 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++) 367 { 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 } 375 } 376 } 377 } 378 379 if (!valid_insn) 380 { 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 } 391 } 392 393 if (nslots > 1) 394 (*info->fprintf_func) (info->stream, "{ "); 395 396 first_slot = 1; 397 for (n = 0; n < nslots; n++) 398 { 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)); 408 409 /* Print the operands (if any). */ 410 noperands = xtensa_opcode_num_operands (isa, opc); 411 first = 1; 412 for (i = 0; i < noperands; i++) 413 { 414 if (xtensa_operand_is_visible (isa, opc, i) == 0) 415 continue; 416 if (first) 417 { 418 (*info->fprintf_func) (info->stream, "\t"); 419 first = 0; 420 } 421 else 422 (*info->fprintf_func) (info->stream, ", "); 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 } 428 } 429 430 if (nslots > 1) 431 (*info->fprintf_func) (info->stream, " }"); 432 433 info->bytes_per_chunk = size; 434 info->display_endian = info->endian; 435 436 return size; 437 } 438 439