X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Fxtensa-dis.c;h=ecef0c55edf541a3379b964055b826bcb9edb072;hb=a6e5765ff1c5fdebaf4953eed619a717178cc7e6;hp=8c310854a8a98b7575219a32bb1136c6fa003f00;hpb=118fecd30767bc6fdd71e8d29304d65d061e12c1;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/xtensa-dis.c b/opcodes/xtensa-dis.c index 8c310854a8..ecef0c55ed 100644 --- a/opcodes/xtensa-dis.c +++ b/opcodes/xtensa-dis.c @@ -1,360 +1,172 @@ /* xtensa-dis.c. Disassembly functions for Xtensa. - Copyright 2003 Free Software Foundation, Inc. + Copyright (C) 2003-2019 Free Software Foundation, Inc. Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com) - This file is part of GDB, GAS, and the GNU binutils. + This file is part of the GNU opcodes library. - GDB, GAS, and the GNU binutils are free software; you can redistribute - them and/or modify them under the terms of the GNU General Public - License as published by the Free Software Foundation; either version 2, - or (at your option) any later version. + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. - GDB, GAS, and the GNU binutils are distributed in the hope that they - will be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - the GNU General Public License for more details. + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. - You should have received a copy of the GNU General Public License along - with this file; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ + You should have received a copy of the GNU General Public License + along with this file; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ +#include "sysdep.h" #include #include #include #include #include "xtensa-isa.h" #include "ansidecl.h" -#include "sysdep.h" -#include "dis-asm.h" +#include "libiberty.h" +#include "bfd.h" +#include "elf/xtensa.h" +#include "disassemble.h" #include +extern xtensa_isa xtensa_default_isa; + #ifndef MAX #define MAX(a,b) (a > b ? a : b) #endif -static char* state_names[256] = +int show_raw_fields; + +struct dis_private { - "lbeg", /* 0 */ - "lend", /* 1 */ - "lcount", /* 2 */ - "sar", /* 3 */ - "br", /* 4 */ - - "reserved_5", /* 5 */ - "reserved_6", /* 6 */ - "reserved_7", /* 7 */ - - "av", /* 8 */ - "avh", /* 9 */ - "bv", /* 10 */ - "sav", /* 11 */ - "scompare1", /* 12 */ - - "reserved_13", /* 13 */ - "reserved_14", /* 14 */ - "reserved_15", /* 15 */ - - "acclo", /* 16 */ - "acchi", /* 17 */ - - "reserved_18", /* 18 */ - "reserved_19", /* 19 */ - "reserved_20", /* 20 */ - "reserved_21", /* 21 */ - "reserved_22", /* 22 */ - "reserved_23", /* 23 */ - "reserved_24", /* 24 */ - "reserved_25", /* 25 */ - "reserved_26", /* 26 */ - "reserved_27", /* 27 */ - "reserved_28", /* 28 */ - "reserved_29", /* 29 */ - "reserved_30", /* 30 */ - "reserved_31", /* 31 */ - - "mr0", /* 32 */ - "mr1", /* 33 */ - "mr2", /* 34 */ - "mr3", /* 35 */ - - "reserved_36", /* 36 */ - "reserved_37", /* 37 */ - "reserved_38", /* 38 */ - "reserved_39", /* 39 */ - "reserved_40", /* 40 */ - "reserved_41", /* 41 */ - "reserved_42", /* 42 */ - "reserved_43", /* 43 */ - "reserved_44", /* 44 */ - "reserved_45", /* 45 */ - "reserved_46", /* 46 */ - "reserved_47", /* 47 */ - "reserved_48", /* 48 */ - "reserved_49", /* 49 */ - "reserved_50", /* 50 */ - "reserved_51", /* 51 */ - "reserved_52", /* 52 */ - "reserved_53", /* 53 */ - "reserved_54", /* 54 */ - "reserved_55", /* 55 */ - "reserved_56", /* 56 */ - "reserved_57", /* 57 */ - "reserved_58", /* 58 */ - "reserved_59", /* 59 */ - "reserved_60", /* 60 */ - "reserved_61", /* 61 */ - "reserved_62", /* 62 */ - "reserved_63", /* 63 */ - - "reserved_64", /* 64 */ - "reserved_65", /* 65 */ - "reserved_66", /* 66 */ - "reserved_67", /* 67 */ - "reserved_68", /* 68 */ - "reserved_69", /* 69 */ - "reserved_70", /* 70 */ - "reserved_71", /* 71 */ - - "wb", /* 72 */ - "ws", /* 73 */ - - "reserved_74", /* 74 */ - "reserved_75", /* 75 */ - "reserved_76", /* 76 */ - "reserved_77", /* 77 */ - "reserved_78", /* 78 */ - "reserved_79", /* 79 */ - "reserved_80", /* 80 */ - "reserved_81", /* 81 */ - "reserved_82", /* 82 */ - - "ptevaddr", /* 83 */ - - "reserved_84", /* 84 */ - "reserved_85", /* 85 */ - "reserved_86", /* 86 */ - "reserved_87", /* 87 */ - "reserved_88", /* 88 */ - "reserved_89", /* 89 */ - - "rasid", /* 90 */ - "itlbcfg", /* 91 */ - "dtlbcfg", /* 92 */ - - "reserved_93", /* 93 */ - "reserved_94", /* 94 */ - "reserved_95", /* 95 */ - - "ibreakenable", /* 96 */ - - "reserved_97", /* 97 */ - - "cacheattr", /* 98 */ - - "reserved_99", /* 99 */ - "reserved_100", /* 100 */ - "reserved_101", /* 101 */ - "reserved_102", /* 102 */ - "reserved_103", /* 103 */ - - "ddr", /* 104 */ - - "reserved_105", /* 105 */ - "reserved_106", /* 106 */ - "reserved_107", /* 107 */ - "reserved_108", /* 108 */ - "reserved_109", /* 109 */ - "reserved_110", /* 110 */ - "reserved_111", /* 111 */ - "reserved_112", /* 112 */ - "reserved_113", /* 113 */ - "reserved_114", /* 114 */ - "reserved_115", /* 115 */ - "reserved_116", /* 116 */ - "reserved_117", /* 117 */ - "reserved_118", /* 118 */ - "reserved_119", /* 119 */ - "reserved_120", /* 120 */ - "reserved_121", /* 121 */ - "reserved_122", /* 122 */ - "reserved_123", /* 123 */ - "reserved_124", /* 124 */ - "reserved_125", /* 125 */ - "reserved_126", /* 126 */ - "reserved_127", /* 127 */ - - "ibreaka0", /* 128 */ - "ibreaka1", /* 129 */ - "ibreaka2", /* 130 */ - "ibreaka3", /* 131 */ - "ibreaka4", /* 132 */ - "ibreaka5", /* 133 */ - "ibreaka6", /* 134 */ - "ibreaka7", /* 135 */ - "ibreaka8", /* 136 */ - "ibreaka9", /* 137 */ - "ibreaka10", /* 138 */ - "ibreaka11", /* 139 */ - "ibreaka12", /* 140 */ - "ibreaka13", /* 141 */ - "ibreaka14", /* 142 */ - "ibreaka15", /* 143 */ - - "dbreaka0", /* 144 */ - "dbreaka1", /* 145 */ - "dbreaka2", /* 146 */ - "dbreaka3", /* 147 */ - "dbreaka4", /* 148 */ - "dbreaka5", /* 149 */ - "dbreaka6", /* 150 */ - "dbreaka7", /* 151 */ - "dbreaka8", /* 152 */ - "dbreaka9", /* 153 */ - "dbreaka10", /* 154 */ - "dbreaka11", /* 155 */ - "dbreaka12", /* 156 */ - "dbreaka13", /* 157 */ - "dbreaka14", /* 158 */ - "dbreaka15", /* 159 */ - - "dbreakc0", /* 160 */ - "dbreakc1", /* 161 */ - "dbreakc2", /* 162 */ - "dbreakc3", /* 163 */ - "dbreakc4", /* 164 */ - "dbreakc5", /* 165 */ - "dbreakc6", /* 166 */ - "dbreakc7", /* 167 */ - "dbreakc8", /* 168 */ - "dbreakc9", /* 169 */ - "dbreakc10", /* 170 */ - "dbreakc11", /* 171 */ - "dbreakc12", /* 172 */ - "dbreakc13", /* 173 */ - "dbreakc14", /* 174 */ - "dbreakc15", /* 175 */ - - "reserved_176", /* 176 */ - - "epc1", /* 177 */ - "epc2", /* 178 */ - "epc3", /* 179 */ - "epc4", /* 180 */ - "epc5", /* 181 */ - "epc6", /* 182 */ - "epc7", /* 183 */ - "epc8", /* 184 */ - "epc9", /* 185 */ - "epc10", /* 186 */ - "epc11", /* 187 */ - "epc12", /* 188 */ - "epc13", /* 189 */ - "epc14", /* 190 */ - "epc15", /* 191 */ - "depc", /* 192 */ - - "reserved_193", /* 193 */ - - "eps2", /* 194 */ - "eps3", /* 195 */ - "eps4", /* 196 */ - "eps5", /* 197 */ - "eps6", /* 198 */ - "eps7", /* 199 */ - "eps8", /* 200 */ - "eps9", /* 201 */ - "eps10", /* 202 */ - "eps11", /* 203 */ - "eps12", /* 204 */ - "eps13", /* 205 */ - "eps14", /* 206 */ - "eps15", /* 207 */ - - "reserved_208", /* 208 */ - - "excsave1", /* 209 */ - "excsave2", /* 210 */ - "excsave3", /* 211 */ - "excsave4", /* 212 */ - "excsave5", /* 213 */ - "excsave6", /* 214 */ - "excsave7", /* 215 */ - "excsave8", /* 216 */ - "excsave9", /* 217 */ - "excsave10", /* 218 */ - "excsave11", /* 219 */ - "excsave12", /* 220 */ - "excsave13", /* 221 */ - "excsave14", /* 222 */ - "excsave15", /* 223 */ - "cpenable", /* 224 */ - - "reserved_225", /* 225 */ - - "interrupt", /* 226 */ - "interrupt2", /* 227 */ - "intenable", /* 228 */ - - "reserved_229", /* 229 */ - - "ps", /* 230 */ - - "reserved_231", /* 231 */ - - "exccause", /* 232 */ - "debugcause", /* 233 */ - "ccount", /* 234 */ - "prid", /* 235 */ - "icount", /* 236 */ - "icountlvl", /* 237 */ - "excvaddr", /* 238 */ - - "reserved_239", /* 239 */ - - "ccompare0", /* 240 */ - "ccompare1", /* 241 */ - "ccompare2", /* 242 */ - "ccompare3", /* 243 */ - - "misc0", /* 244 */ - "misc1", /* 245 */ - "misc2", /* 246 */ - "misc3", /* 247 */ - - "reserved_248", /* 248 */ - "reserved_249", /* 249 */ - "reserved_250", /* 250 */ - "reserved_251", /* 251 */ - "reserved_252", /* 252 */ - "reserved_253", /* 253 */ - "reserved_254", /* 254 */ - "reserved_255", /* 255 */ + bfd_byte *byte_buf; + OPCODES_SIGJMP_BUF bailout; + /* Persistent fields, valid for last_section only. */ + asection *last_section; + property_table_entry *insn_table_entries; + int insn_table_entry_count; + /* Cached property table search position. */ + bfd_vma insn_table_cur_addr; + int insn_table_cur_idx; }; +static void +xtensa_coalesce_insn_tables (struct dis_private *priv) +{ + const int mask = ~(XTENSA_PROP_DATA | XTENSA_PROP_NO_TRANSFORM); + int count = priv->insn_table_entry_count; + int i, j; -int show_raw_fields; + /* Loop over all entries, combining adjacent ones that differ only in + the flag bits XTENSA_PROP_DATA and XTENSA_PROP_NO_TRANSFORM. */ -static int fetch_data - PARAMS ((struct disassemble_info *info, bfd_vma memaddr)); -static void print_xtensa_operand - PARAMS ((bfd_vma, struct disassemble_info *, xtensa_operand, - unsigned operand_val, int print_sr_name)); + for (i = j = 0; j < count; ++i) + { + property_table_entry *entry = priv->insn_table_entries + i; -struct dis_private { - bfd_byte *byte_buf; - jmp_buf bailout; -}; + *entry = priv->insn_table_entries[j]; + + for (++j; j < count; ++j) + { + property_table_entry *next = priv->insn_table_entries + j; + int fill = xtensa_compute_fill_extra_space (entry); + int size = entry->size + fill; + + if (entry->address + size == next->address) + { + int entry_flags = entry->flags & mask; + int next_flags = next->flags & mask; + + if (next_flags == entry_flags) + entry->size = next->address - entry->address + next->size; + else + break; + } + else + { + break; + } + } + } + priv->insn_table_entry_count = i; +} + +static property_table_entry * +xtensa_find_table_entry (bfd_vma memaddr, struct disassemble_info *info) +{ + struct dis_private *priv = (struct dis_private *) info->private_data; + int i; + + if (priv->insn_table_entries == NULL + || priv->insn_table_entry_count < 0) + return NULL; + + if (memaddr < priv->insn_table_cur_addr) + priv->insn_table_cur_idx = 0; + + for (i = priv->insn_table_cur_idx; i < priv->insn_table_entry_count; ++i) + { + property_table_entry *block = priv->insn_table_entries + i; + + if (block->size != 0) + { + if ((memaddr >= block->address + && memaddr < block->address + block->size) + || memaddr < block->address) + { + priv->insn_table_cur_addr = memaddr; + priv->insn_table_cur_idx = i; + return block; + } + } + } + return NULL; +} + +/* Check whether an instruction crosses an instruction block boundary + (according to property tables). + If it does, return 0 (doesn't fit), else return 1. */ + +static int +xtensa_instruction_fits (bfd_vma memaddr, int size, + property_table_entry *insn_block) +{ + unsigned max_size; + + /* If no property table info, assume it fits. */ + if (insn_block == NULL || size <= 0) + return 1; + + /* If too high, limit nextstop by the next insn address. */ + if (insn_block->address > memaddr) + { + /* memaddr is not in an instruction block, but is followed by one. */ + max_size = insn_block->address - memaddr; + } + else + { + /* memaddr is in an instruction block, go no further than the end. */ + max_size = insn_block->address + insn_block->size - memaddr; + } + + /* Crossing a boundary, doesn't "fit". */ + if ((unsigned)size > max_size) + return 0; + return 1; +} static int -fetch_data (info, memaddr) - struct disassemble_info *info; - bfd_vma memaddr; +fetch_data (struct disassemble_info *info, bfd_vma memaddr) { int length, status = 0; struct dis_private *priv = (struct dis_private *) info->private_data; - int insn_size = xtensa_insn_maxlength (xtensa_default_isa); + int insn_size = xtensa_isa_maxlength (xtensa_default_isa); + + insn_size = MAX (insn_size, 4); /* Read the maximum instruction size, padding with zeros if we go past the end of the text section. This code will automatically adjust @@ -369,22 +181,21 @@ fetch_data (info, memaddr) return length; } (*info->memory_error_func) (status, memaddr, info); - longjmp (priv->bailout, 1); + OPCODES_SIGLONGJMP (priv->bailout, 1); /*NOTREACHED*/ } static void -print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name) - bfd_vma memaddr; - struct disassemble_info *info; - xtensa_operand opnd; - unsigned operand_val; - int print_sr_name; +print_xtensa_operand (bfd_vma memaddr, + struct disassemble_info *info, + xtensa_opcode opc, + int opnd, + unsigned operand_val) { - char *kind = xtensa_operand_kind (opnd); + xtensa_isa isa = xtensa_default_isa; int signed_operand_val; - + if (show_raw_fields) { if (operand_val < 0xa) @@ -394,29 +205,42 @@ print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name) return; } - operand_val = xtensa_operand_decode (opnd, operand_val); + (void) xtensa_operand_decode (isa, opc, opnd, &operand_val); signed_operand_val = (int) operand_val; - if (xtensa_operand_isPCRelative (opnd)) + if (xtensa_operand_is_register (isa, opc, opnd) == 0) { - operand_val = xtensa_operand_undo_reloc (opnd, operand_val, memaddr); - info->target = operand_val; - (*info->print_address_func) (info->target, info); - } - else if (!strcmp (kind, "i")) - { - if (print_sr_name - && signed_operand_val >= 0 - && signed_operand_val <= 255) - (*info->fprintf_func) (info->stream, "%s", - state_names[signed_operand_val]); - else if ((signed_operand_val > -256) && (signed_operand_val < 256)) - (*info->fprintf_func) (info->stream, "%d", signed_operand_val); + if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1) + { + (void) xtensa_operand_undo_reloc (isa, opc, opnd, + &operand_val, memaddr); + info->target = operand_val; + (*info->print_address_func) (info->target, info); + } else - (*info->fprintf_func) (info->stream, "0x%x",signed_operand_val); + { + if ((signed_operand_val > -256) && (signed_operand_val < 256)) + (*info->fprintf_func) (info->stream, "%d", signed_operand_val); + else + (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val); + } } else - (*info->fprintf_func) (info->stream, "%s%u", kind, operand_val); + { + int i = 1; + xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd); + (*info->fprintf_func) (info->stream, "%s%u", + xtensa_regfile_shortname (isa, opnd_rf), + operand_val); + while (i < xtensa_operand_num_regs (isa, opc, opnd)) + { + operand_val++; + (*info->fprintf_func) (info->stream, ":%s%u", + xtensa_regfile_shortname (isa, opnd_rf), + operand_val); + i++; + } + } } @@ -424,25 +248,25 @@ print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name) Returns length of the instruction in bytes. */ int -print_insn_xtensa (memaddr, info) - bfd_vma memaddr; - struct disassemble_info *info; +print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info) { unsigned operand_val; - int bytes_fetched, size, maxsize, i, noperands; + int bytes_fetched, size, maxsize, i, n, noperands, nslots; xtensa_isa isa; xtensa_opcode opc; - char *op_name; - int print_sr_name; - struct dis_private priv; + xtensa_format fmt; + static struct dis_private priv; static bfd_byte *byte_buf = NULL; static xtensa_insnbuf insn_buffer = NULL; + static xtensa_insnbuf slot_buffer = NULL; + int first, first_slot, valid_insn; + property_table_entry *insn_block; if (!xtensa_default_isa) - (void) xtensa_isa_init (); + xtensa_default_isa = xtensa_isa_init (0, 0); info->target = 0; - maxsize = xtensa_insn_maxlength (xtensa_default_isa); + maxsize = xtensa_isa_maxlength (xtensa_default_isa); /* Set bytes_per_line to control the amount of whitespace between the hex values and the opcode. For Xtensa, we always print one "chunk" and we @@ -458,64 +282,156 @@ print_insn_xtensa (memaddr, info) /* Allocate buffers the first time through. */ if (!insn_buffer) - insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa); - if (!byte_buf) - byte_buf = (bfd_byte *) malloc (MAX (maxsize, 4)); + { + insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa); + slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa); + byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4)); + } priv.byte_buf = byte_buf; - info->private_data = (PTR) &priv; - if (setjmp (priv.bailout) != 0) + info->private_data = (void *) &priv; + + /* Prepare instruction tables. */ + + if (info->section != NULL) + { + asection *section = info->section; + + if (priv.last_section != section) + { + bfd *abfd = section->owner; + + if (priv.last_section != NULL) + { + /* Reset insn_table_entries. */ + priv.insn_table_entry_count = 0; + if (priv.insn_table_entries) + free (priv.insn_table_entries); + priv.insn_table_entries = NULL; + } + priv.last_section = section; + + /* Read insn_table_entries. */ + priv.insn_table_entry_count = + xtensa_read_table_entries (abfd, section, + &priv.insn_table_entries, + XTENSA_PROP_SEC_NAME, FALSE); + if (priv.insn_table_entry_count == 0) + { + if (priv.insn_table_entries) + free (priv.insn_table_entries); + priv.insn_table_entries = NULL; + /* Backwards compatibility support. */ + priv.insn_table_entry_count = + xtensa_read_table_entries (abfd, section, + &priv.insn_table_entries, + XTENSA_INSN_SEC_NAME, FALSE); + } + priv.insn_table_cur_idx = 0; + xtensa_coalesce_insn_tables (&priv); + } + /* Else nothing to do, same section as last time. */ + } + + if (OPCODES_SIGSETJMP (priv.bailout) != 0) /* Error return. */ return -1; - /* Don't set "isa" before the setjmp to keep the compiler from griping. */ - isa = xtensa_default_isa; - /* Fetch the maximum size instruction. */ bytes_fetched = fetch_data (info, memaddr); - /* Copy the bytes into the decode buffer. */ - memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) * - sizeof (xtensa_insnbuf_word))); - xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf); + insn_block = xtensa_find_table_entry (memaddr, info); - opc = xtensa_decode_insn (isa, insn_buffer); - if (opc == XTENSA_UNDEFINED - || ((size = xtensa_insn_length (isa, opc)) > bytes_fetched)) + /* Don't set "isa" before the setjmp to keep the compiler from griping. */ + isa = xtensa_default_isa; + size = 0; + nslots = 0; + valid_insn = 0; + fmt = 0; + if (!insn_block || (insn_block->flags & XTENSA_PROP_INSN)) { - (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]); - return 1; + /* Copy the bytes into the decode buffer. */ + memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) * + sizeof (xtensa_insnbuf_word))); + xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf, + bytes_fetched); + + fmt = xtensa_format_decode (isa, insn_buffer); + if (fmt != XTENSA_UNDEFINED + && ((size = xtensa_format_length (isa, fmt)) <= bytes_fetched) + && xtensa_instruction_fits (memaddr, size, insn_block)) + { + /* Make sure all the opcodes are valid. */ + valid_insn = 1; + nslots = xtensa_format_num_slots (isa, fmt); + for (n = 0; n < nslots; n++) + { + xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer); + if (xtensa_opcode_decode (isa, fmt, n, slot_buffer) + == XTENSA_UNDEFINED) + { + valid_insn = 0; + break; + } + } + } } - op_name = (char *) xtensa_opcode_name (isa, opc); - (*info->fprintf_func) (info->stream, "%s", op_name); + if (!valid_insn) + { + if (insn_block && (insn_block->flags & XTENSA_PROP_LITERAL) + && (memaddr & 3) == 0 && bytes_fetched >= 4) + { + return 4; + } + else + { + (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]); + return 1; + } + } - print_sr_name = (!strcasecmp (op_name, "wsr") - || !strcasecmp (op_name, "xsr") - || !strcasecmp (op_name, "rsr")); + if (nslots > 1) + (*info->fprintf_func) (info->stream, "{ "); - /* Print the operands (if any). */ - noperands = xtensa_num_operands (isa, opc); - if (noperands > 0) + first_slot = 1; + for (n = 0; n < nslots; n++) { - int first = 1; + if (first_slot) + first_slot = 0; + else + (*info->fprintf_func) (info->stream, "; "); - (*info->fprintf_func) (info->stream, "\t"); + xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer); + opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer); + (*info->fprintf_func) (info->stream, "%s", + xtensa_opcode_name (isa, opc)); + + /* Print the operands (if any). */ + noperands = xtensa_opcode_num_operands (isa, opc); + first = 1; for (i = 0; i < noperands; i++) { - xtensa_operand opnd = xtensa_get_operand (isa, opc, i); - + if (xtensa_operand_is_visible (isa, opc, i) == 0) + continue; if (first) - first = 0; + { + (*info->fprintf_func) (info->stream, "\t"); + first = 0; + } else (*info->fprintf_func) (info->stream, ", "); - operand_val = xtensa_operand_get_field (opnd, insn_buffer); - print_xtensa_operand (memaddr, info, opnd, operand_val, - print_sr_name); - } + (void) xtensa_operand_get_field (isa, opc, i, fmt, n, + slot_buffer, &operand_val); + + print_xtensa_operand (memaddr, info, opc, i, operand_val); + } } + if (nslots > 1) + (*info->fprintf_func) (info->stream, " }"); + info->bytes_per_chunk = size; info->display_endian = info->endian;