xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/xtensa-dis.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* xtensa-dis.c.  Disassembly functions for Xtensa.
2*e992f068Schristos    Copyright (C) 2003-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com)
475fd0b74Schristos 
575fd0b74Schristos    This file is part of the GNU opcodes library.
675fd0b74Schristos 
775fd0b74Schristos    This library is free software; you can redistribute it and/or modify
875fd0b74Schristos    it under the terms of the GNU General Public License as published by
975fd0b74Schristos    the Free Software Foundation; either version 3, or (at your option)
1075fd0b74Schristos    any later version.
1175fd0b74Schristos 
1275fd0b74Schristos    It is distributed in the hope that it will be useful, but WITHOUT
1375fd0b74Schristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1475fd0b74Schristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1575fd0b74Schristos    License for more details.
1675fd0b74Schristos 
1775fd0b74Schristos    You should have received a copy of the GNU General Public License
1875fd0b74Schristos    along with this file; see the file COPYING.  If not, write to the
1975fd0b74Schristos    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
2075fd0b74Schristos    MA 02110-1301, USA.  */
2175fd0b74Schristos 
2275fd0b74Schristos #include "sysdep.h"
2375fd0b74Schristos #include <stdlib.h>
2475fd0b74Schristos #include <stdio.h>
2575fd0b74Schristos #include <sys/types.h>
2675fd0b74Schristos #include <string.h>
2775fd0b74Schristos #include "xtensa-isa.h"
2875fd0b74Schristos #include "ansidecl.h"
2975fd0b74Schristos #include "libiberty.h"
30ede78133Schristos #include "bfd.h"
31ede78133Schristos #include "elf/xtensa.h"
32ede78133Schristos #include "disassemble.h"
3375fd0b74Schristos 
3475fd0b74Schristos #include <setjmp.h>
3575fd0b74Schristos 
3675fd0b74Schristos extern xtensa_isa xtensa_default_isa;
3775fd0b74Schristos 
3875fd0b74Schristos #ifndef MAX
3975fd0b74Schristos #define MAX(a,b) (a > b ? a : b)
4075fd0b74Schristos #endif
4175fd0b74Schristos 
4275fd0b74Schristos int show_raw_fields;
4375fd0b74Schristos 
4475fd0b74Schristos struct dis_private
4575fd0b74Schristos {
4675fd0b74Schristos   bfd_byte *byte_buf;
4775fd0b74Schristos   OPCODES_SIGJMP_BUF bailout;
48ede78133Schristos   /* Persistent fields, valid for last_section only.  */
49ede78133Schristos   asection *last_section;
50ede78133Schristos   property_table_entry *insn_table_entries;
51ede78133Schristos   int insn_table_entry_count;
52ede78133Schristos   /* Cached property table search position.  */
53ede78133Schristos   bfd_vma insn_table_cur_addr;
54ede78133Schristos   int insn_table_cur_idx;
5575fd0b74Schristos };
5675fd0b74Schristos 
57ede78133Schristos static void
xtensa_coalesce_insn_tables(struct dis_private * priv)58ede78133Schristos xtensa_coalesce_insn_tables (struct dis_private *priv)
59ede78133Schristos {
60ede78133Schristos   const int mask = ~(XTENSA_PROP_DATA | XTENSA_PROP_NO_TRANSFORM);
61ede78133Schristos   int count = priv->insn_table_entry_count;
62ede78133Schristos   int i, j;
63ede78133Schristos 
64ede78133Schristos   /* Loop over all entries, combining adjacent ones that differ only in
65ede78133Schristos      the flag bits XTENSA_PROP_DATA and XTENSA_PROP_NO_TRANSFORM.  */
66ede78133Schristos 
67ede78133Schristos   for (i = j = 0; j < count; ++i)
68ede78133Schristos     {
69ede78133Schristos       property_table_entry *entry = priv->insn_table_entries + i;
70ede78133Schristos 
71ede78133Schristos       *entry = priv->insn_table_entries[j];
72ede78133Schristos 
73ede78133Schristos       for (++j; j < count; ++j)
74ede78133Schristos 	{
75ede78133Schristos 	  property_table_entry *next = priv->insn_table_entries + j;
76ede78133Schristos 	  int fill = xtensa_compute_fill_extra_space (entry);
77ede78133Schristos 	  int size = entry->size + fill;
78ede78133Schristos 
79ede78133Schristos 	  if (entry->address + size == next->address)
80ede78133Schristos 	    {
81ede78133Schristos 	      int entry_flags = entry->flags & mask;
82ede78133Schristos 	      int next_flags = next->flags & mask;
83ede78133Schristos 
84ede78133Schristos 	      if (next_flags == entry_flags)
85ede78133Schristos 		entry->size = next->address - entry->address + next->size;
86ede78133Schristos 	      else
87ede78133Schristos 		break;
88ede78133Schristos 	    }
89ede78133Schristos 	  else
90ede78133Schristos 	    {
91ede78133Schristos 	      break;
92ede78133Schristos 	    }
93ede78133Schristos 	}
94ede78133Schristos     }
95ede78133Schristos   priv->insn_table_entry_count = i;
96ede78133Schristos }
97ede78133Schristos 
98ede78133Schristos static property_table_entry *
xtensa_find_table_entry(bfd_vma memaddr,struct disassemble_info * info)99ede78133Schristos xtensa_find_table_entry (bfd_vma memaddr, struct disassemble_info *info)
100ede78133Schristos {
101ede78133Schristos   struct dis_private *priv = (struct dis_private *) info->private_data;
102ede78133Schristos   int i;
103ede78133Schristos 
104ede78133Schristos   if (priv->insn_table_entries == NULL
105ede78133Schristos       || priv->insn_table_entry_count < 0)
106ede78133Schristos     return NULL;
107ede78133Schristos 
108ede78133Schristos   if (memaddr < priv->insn_table_cur_addr)
109ede78133Schristos     priv->insn_table_cur_idx = 0;
110ede78133Schristos 
111ede78133Schristos   for (i = priv->insn_table_cur_idx; i < priv->insn_table_entry_count; ++i)
112ede78133Schristos     {
113ede78133Schristos       property_table_entry *block = priv->insn_table_entries + i;
114ede78133Schristos 
115ede78133Schristos       if (block->size != 0)
116ede78133Schristos 	{
117ede78133Schristos 	  if ((memaddr >= block->address
118ede78133Schristos 	       && memaddr < block->address + block->size)
119ede78133Schristos 	      || memaddr < block->address)
120ede78133Schristos 	    {
121ede78133Schristos 	      priv->insn_table_cur_addr = memaddr;
122ede78133Schristos 	      priv->insn_table_cur_idx = i;
123ede78133Schristos 	      return block;
124ede78133Schristos 	    }
125ede78133Schristos 	}
126ede78133Schristos     }
127ede78133Schristos   return NULL;
128ede78133Schristos }
129ede78133Schristos 
130ede78133Schristos /* Check whether an instruction crosses an instruction block boundary
131ede78133Schristos    (according to property tables).
132ede78133Schristos    If it does, return 0 (doesn't fit), else return 1.  */
133ede78133Schristos 
134ede78133Schristos static int
xtensa_instruction_fits(bfd_vma memaddr,int size,property_table_entry * insn_block)135ede78133Schristos xtensa_instruction_fits (bfd_vma memaddr, int size,
136ede78133Schristos 			 property_table_entry *insn_block)
137ede78133Schristos {
138ede78133Schristos   unsigned max_size;
139ede78133Schristos 
140ede78133Schristos   /* If no property table info, assume it fits.  */
141ede78133Schristos   if (insn_block == NULL || size <= 0)
142ede78133Schristos     return 1;
143ede78133Schristos 
144ede78133Schristos   /* If too high, limit nextstop by the next insn address.  */
145ede78133Schristos   if (insn_block->address > memaddr)
146ede78133Schristos     {
147ede78133Schristos       /* memaddr is not in an instruction block, but is followed by one.  */
148ede78133Schristos       max_size = insn_block->address - memaddr;
149ede78133Schristos     }
150ede78133Schristos   else
151ede78133Schristos     {
152ede78133Schristos       /* memaddr is in an instruction block, go no further than the end.  */
153ede78133Schristos       max_size = insn_block->address + insn_block->size - memaddr;
154ede78133Schristos     }
155ede78133Schristos 
156ede78133Schristos   /* Crossing a boundary, doesn't "fit".  */
157ede78133Schristos   if ((unsigned)size > max_size)
158ede78133Schristos     return 0;
159ede78133Schristos   return 1;
160ede78133Schristos }
16175fd0b74Schristos 
16275fd0b74Schristos static int
fetch_data(struct disassemble_info * info,bfd_vma memaddr)16375fd0b74Schristos fetch_data (struct disassemble_info *info, bfd_vma memaddr)
16475fd0b74Schristos {
16575fd0b74Schristos   int length, status = 0;
16675fd0b74Schristos   struct dis_private *priv = (struct dis_private *) info->private_data;
16775fd0b74Schristos   int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
16875fd0b74Schristos 
169ede78133Schristos   insn_size = MAX (insn_size, 4);
170ede78133Schristos 
17175fd0b74Schristos   /* Read the maximum instruction size, padding with zeros if we go past
17275fd0b74Schristos      the end of the text section.  This code will automatically adjust
17375fd0b74Schristos      length when we hit the end of the buffer.  */
17475fd0b74Schristos 
17575fd0b74Schristos   memset (priv->byte_buf, 0, insn_size);
17675fd0b74Schristos   for (length = insn_size; length > 0; length--)
17775fd0b74Schristos     {
17875fd0b74Schristos       status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
17975fd0b74Schristos 					  info);
18075fd0b74Schristos       if (status == 0)
18175fd0b74Schristos 	return length;
18275fd0b74Schristos     }
18375fd0b74Schristos   (*info->memory_error_func) (status, memaddr, info);
18475fd0b74Schristos   OPCODES_SIGLONGJMP (priv->bailout, 1);
18575fd0b74Schristos   /*NOTREACHED*/
18675fd0b74Schristos }
18775fd0b74Schristos 
18875fd0b74Schristos 
18975fd0b74Schristos static void
print_xtensa_operand(bfd_vma memaddr,struct disassemble_info * info,xtensa_opcode opc,int opnd,unsigned operand_val)19075fd0b74Schristos print_xtensa_operand (bfd_vma memaddr,
19175fd0b74Schristos 		      struct disassemble_info *info,
19275fd0b74Schristos 		      xtensa_opcode opc,
19375fd0b74Schristos 		      int opnd,
19475fd0b74Schristos 		      unsigned operand_val)
19575fd0b74Schristos {
19675fd0b74Schristos   xtensa_isa isa = xtensa_default_isa;
197*e992f068Schristos   int signed_operand_val, status;
198*e992f068Schristos   bfd_byte litbuf[4];
19975fd0b74Schristos 
20075fd0b74Schristos   if (show_raw_fields)
20175fd0b74Schristos     {
20275fd0b74Schristos       if (operand_val < 0xa)
20375fd0b74Schristos 	(*info->fprintf_func) (info->stream, "%u", operand_val);
20475fd0b74Schristos       else
20575fd0b74Schristos 	(*info->fprintf_func) (info->stream, "0x%x", operand_val);
20675fd0b74Schristos       return;
20775fd0b74Schristos     }
20875fd0b74Schristos 
20975fd0b74Schristos   (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
21075fd0b74Schristos   signed_operand_val = (int) operand_val;
21175fd0b74Schristos 
21275fd0b74Schristos   if (xtensa_operand_is_register (isa, opc, opnd) == 0)
21375fd0b74Schristos     {
21475fd0b74Schristos       if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
21575fd0b74Schristos 	{
21675fd0b74Schristos 	  (void) xtensa_operand_undo_reloc (isa, opc, opnd,
21775fd0b74Schristos 					    &operand_val, memaddr);
21875fd0b74Schristos 	  info->target = operand_val;
21975fd0b74Schristos 	  (*info->print_address_func) (info->target, info);
220*e992f068Schristos 	  /*  Also display value loaded by L32R (but not if reloc exists,
221*e992f068Schristos 	      those tend to be wrong):  */
222*e992f068Schristos 	  if ((info->flags & INSN_HAS_RELOC) == 0
223*e992f068Schristos 	      && !strcmp ("l32r", xtensa_opcode_name (isa, opc)))
224*e992f068Schristos 	    status = (*info->read_memory_func) (operand_val, litbuf, 4, info);
225*e992f068Schristos 	  else
226*e992f068Schristos 	    status = -1;
227*e992f068Schristos 
228*e992f068Schristos 	  if (status == 0)
229*e992f068Schristos 	    {
230*e992f068Schristos 	      unsigned literal = bfd_get_bits (litbuf, 32,
231*e992f068Schristos 					       info->endian == BFD_ENDIAN_BIG);
232*e992f068Schristos 
233*e992f068Schristos 	      (*info->fprintf_func) (info->stream, " (");
234*e992f068Schristos 	      (*info->print_address_func) (literal, info);
235*e992f068Schristos 	      (*info->fprintf_func) (info->stream, ")");
236*e992f068Schristos 	    }
23775fd0b74Schristos 	}
23875fd0b74Schristos       else
23975fd0b74Schristos 	{
24075fd0b74Schristos 	  if ((signed_operand_val > -256) && (signed_operand_val < 256))
24175fd0b74Schristos 	    (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
24275fd0b74Schristos 	  else
24375fd0b74Schristos 	    (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
24475fd0b74Schristos 	}
24575fd0b74Schristos     }
24675fd0b74Schristos   else
24775fd0b74Schristos     {
24875fd0b74Schristos       int i = 1;
24975fd0b74Schristos       xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
25075fd0b74Schristos       (*info->fprintf_func) (info->stream, "%s%u",
25175fd0b74Schristos 			     xtensa_regfile_shortname (isa, opnd_rf),
25275fd0b74Schristos 			     operand_val);
25375fd0b74Schristos       while (i < xtensa_operand_num_regs (isa, opc, opnd))
25475fd0b74Schristos 	{
25575fd0b74Schristos 	  operand_val++;
25675fd0b74Schristos 	  (*info->fprintf_func) (info->stream, ":%s%u",
25775fd0b74Schristos 				 xtensa_regfile_shortname (isa, opnd_rf),
25875fd0b74Schristos 				 operand_val);
25975fd0b74Schristos 	  i++;
26075fd0b74Schristos 	}
26175fd0b74Schristos     }
26275fd0b74Schristos }
26375fd0b74Schristos 
26475fd0b74Schristos 
26575fd0b74Schristos /* Print the Xtensa instruction at address MEMADDR on info->stream.
26675fd0b74Schristos    Returns length of the instruction in bytes.  */
26775fd0b74Schristos 
26875fd0b74Schristos int
print_insn_xtensa(bfd_vma memaddr,struct disassemble_info * info)26975fd0b74Schristos print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info)
27075fd0b74Schristos {
27175fd0b74Schristos   unsigned operand_val;
27275fd0b74Schristos   int bytes_fetched, size, maxsize, i, n, noperands, nslots;
27375fd0b74Schristos   xtensa_isa isa;
27475fd0b74Schristos   xtensa_opcode opc;
27575fd0b74Schristos   xtensa_format fmt;
276ede78133Schristos   static struct dis_private priv;
27775fd0b74Schristos   static bfd_byte *byte_buf = NULL;
27875fd0b74Schristos   static xtensa_insnbuf insn_buffer = NULL;
27975fd0b74Schristos   static xtensa_insnbuf slot_buffer = NULL;
28075fd0b74Schristos   int first, first_slot, valid_insn;
281ede78133Schristos   property_table_entry *insn_block;
28275fd0b74Schristos 
28375fd0b74Schristos   if (!xtensa_default_isa)
28475fd0b74Schristos     xtensa_default_isa = xtensa_isa_init (0, 0);
28575fd0b74Schristos 
28675fd0b74Schristos   info->target = 0;
28775fd0b74Schristos   maxsize = xtensa_isa_maxlength (xtensa_default_isa);
28875fd0b74Schristos 
28975fd0b74Schristos   /* Set bytes_per_line to control the amount of whitespace between the hex
29075fd0b74Schristos      values and the opcode.  For Xtensa, we always print one "chunk" and we
29175fd0b74Schristos      vary bytes_per_chunk to determine how many bytes to print.  (objdump
29275fd0b74Schristos      would apparently prefer that we set bytes_per_chunk to 1 and vary
29375fd0b74Schristos      bytes_per_line but that makes it hard to fit 64-bit instructions on
29475fd0b74Schristos      an 80-column screen.)  The value of bytes_per_line here is not exactly
29575fd0b74Schristos      right, because objdump adds an extra space for each chunk so that the
29675fd0b74Schristos      amount of whitespace depends on the chunk size.  Oh well, it's good
29775fd0b74Schristos      enough....  Note that we set the minimum size to 4 to accomodate
29875fd0b74Schristos      literal pools.  */
29975fd0b74Schristos   info->bytes_per_line = MAX (maxsize, 4);
30075fd0b74Schristos 
30175fd0b74Schristos   /* Allocate buffers the first time through.  */
30275fd0b74Schristos   if (!insn_buffer)
30375fd0b74Schristos     {
30475fd0b74Schristos       insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
30575fd0b74Schristos       slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
30675fd0b74Schristos       byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
30775fd0b74Schristos     }
30875fd0b74Schristos 
30975fd0b74Schristos   priv.byte_buf = byte_buf;
31075fd0b74Schristos 
31175fd0b74Schristos   info->private_data = (void *) &priv;
312ede78133Schristos 
313ede78133Schristos   /* Prepare instruction tables.  */
314ede78133Schristos 
315ede78133Schristos   if (info->section != NULL)
316ede78133Schristos     {
317ede78133Schristos       asection *section = info->section;
318ede78133Schristos 
319ede78133Schristos       if (priv.last_section != section)
320ede78133Schristos 	{
321ede78133Schristos 	  bfd *abfd = section->owner;
322ede78133Schristos 
323ede78133Schristos 	  if (priv.last_section != NULL)
324ede78133Schristos 	    {
325ede78133Schristos 	      /* Reset insn_table_entries.  */
326ede78133Schristos 	      priv.insn_table_entry_count = 0;
327ede78133Schristos 	      free (priv.insn_table_entries);
328ede78133Schristos 	      priv.insn_table_entries = NULL;
329ede78133Schristos 	    }
330ede78133Schristos 	  priv.last_section = section;
331ede78133Schristos 
332ede78133Schristos 	  /* Read insn_table_entries.  */
333ede78133Schristos 	  priv.insn_table_entry_count =
334ede78133Schristos 	    xtensa_read_table_entries (abfd, section,
335ede78133Schristos 				       &priv.insn_table_entries,
336*e992f068Schristos 				       XTENSA_PROP_SEC_NAME, false);
337ede78133Schristos 	  if (priv.insn_table_entry_count == 0)
338ede78133Schristos 	    {
339ede78133Schristos 	      free (priv.insn_table_entries);
340ede78133Schristos 	      priv.insn_table_entries = NULL;
341ede78133Schristos 	      /* Backwards compatibility support.  */
342ede78133Schristos 	      priv.insn_table_entry_count =
343ede78133Schristos 		xtensa_read_table_entries (abfd, section,
344ede78133Schristos 					   &priv.insn_table_entries,
345*e992f068Schristos 					   XTENSA_INSN_SEC_NAME, false);
346ede78133Schristos 	    }
347ede78133Schristos 	  priv.insn_table_cur_idx = 0;
348ede78133Schristos 	  xtensa_coalesce_insn_tables (&priv);
349ede78133Schristos 	}
350ede78133Schristos       /* Else nothing to do, same section as last time.  */
351ede78133Schristos     }
352ede78133Schristos 
35375fd0b74Schristos   if (OPCODES_SIGSETJMP (priv.bailout) != 0)
35475fd0b74Schristos       /* Error return.  */
35575fd0b74Schristos       return -1;
35675fd0b74Schristos 
357ede78133Schristos   /* Fetch the maximum size instruction.  */
358ede78133Schristos   bytes_fetched = fetch_data (info, memaddr);
359ede78133Schristos 
360ede78133Schristos   insn_block = xtensa_find_table_entry (memaddr, info);
361ede78133Schristos 
36275fd0b74Schristos   /* Don't set "isa" before the setjmp to keep the compiler from griping.  */
36375fd0b74Schristos   isa = xtensa_default_isa;
36475fd0b74Schristos   size = 0;
36575fd0b74Schristos   nslots = 0;
366ede78133Schristos   valid_insn = 0;
367ede78133Schristos   fmt = 0;
368ede78133Schristos   if (!insn_block || (insn_block->flags & XTENSA_PROP_INSN))
369ede78133Schristos     {
37075fd0b74Schristos       /* Copy the bytes into the decode buffer.  */
37175fd0b74Schristos       memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
37275fd0b74Schristos 			       sizeof (xtensa_insnbuf_word)));
373ede78133Schristos       xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf,
374ede78133Schristos 				 bytes_fetched);
37575fd0b74Schristos 
37675fd0b74Schristos       fmt = xtensa_format_decode (isa, insn_buffer);
377ede78133Schristos       if (fmt != XTENSA_UNDEFINED
378ede78133Schristos 	  && ((size = xtensa_format_length (isa, fmt)) <= bytes_fetched)
379ede78133Schristos 	  && xtensa_instruction_fits (memaddr, size, insn_block))
38075fd0b74Schristos 	{
38175fd0b74Schristos 	  /* Make sure all the opcodes are valid.  */
38275fd0b74Schristos 	  valid_insn = 1;
38375fd0b74Schristos 	  nslots = xtensa_format_num_slots (isa, fmt);
38475fd0b74Schristos 	  for (n = 0; n < nslots; n++)
38575fd0b74Schristos 	    {
38675fd0b74Schristos 	      xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
38775fd0b74Schristos 	      if (xtensa_opcode_decode (isa, fmt, n, slot_buffer)
38875fd0b74Schristos 		  == XTENSA_UNDEFINED)
38975fd0b74Schristos 		{
39075fd0b74Schristos 		  valid_insn = 0;
39175fd0b74Schristos 		  break;
39275fd0b74Schristos 		}
39375fd0b74Schristos 	    }
39475fd0b74Schristos 	}
395ede78133Schristos     }
39675fd0b74Schristos 
39775fd0b74Schristos   if (!valid_insn)
39875fd0b74Schristos     {
399ede78133Schristos       if (insn_block && (insn_block->flags & XTENSA_PROP_LITERAL)
400ede78133Schristos 	  && (memaddr & 3) == 0 && bytes_fetched >= 4)
401ede78133Schristos 	{
402*e992f068Schristos 	  info->bytes_per_chunk = 4;
403ede78133Schristos 	  return 4;
404ede78133Schristos 	}
405ede78133Schristos       else
406ede78133Schristos 	{
40775fd0b74Schristos 	  (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
40875fd0b74Schristos 	  return 1;
40975fd0b74Schristos 	}
410ede78133Schristos     }
41175fd0b74Schristos 
41275fd0b74Schristos   if (nslots > 1)
41375fd0b74Schristos     (*info->fprintf_func) (info->stream, "{ ");
41475fd0b74Schristos 
415*e992f068Schristos   info->insn_type = dis_nonbranch;
416*e992f068Schristos   info->insn_info_valid = 1;
417*e992f068Schristos 
41875fd0b74Schristos   first_slot = 1;
41975fd0b74Schristos   for (n = 0; n < nslots; n++)
42075fd0b74Schristos     {
42175fd0b74Schristos       if (first_slot)
42275fd0b74Schristos 	first_slot = 0;
42375fd0b74Schristos       else
42475fd0b74Schristos 	(*info->fprintf_func) (info->stream, "; ");
42575fd0b74Schristos 
42675fd0b74Schristos       xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
42775fd0b74Schristos       opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
42875fd0b74Schristos       (*info->fprintf_func) (info->stream, "%s",
42975fd0b74Schristos 			     xtensa_opcode_name (isa, opc));
43075fd0b74Schristos 
431*e992f068Schristos       if (xtensa_opcode_is_branch (isa, opc))
432*e992f068Schristos 	info->insn_type = dis_condbranch;
433*e992f068Schristos       else if (xtensa_opcode_is_jump (isa, opc))
434*e992f068Schristos 	info->insn_type = dis_branch;
435*e992f068Schristos       else if (xtensa_opcode_is_call (isa, opc))
436*e992f068Schristos 	info->insn_type = dis_jsr;
437*e992f068Schristos 
43875fd0b74Schristos       /* Print the operands (if any).  */
43975fd0b74Schristos       noperands = xtensa_opcode_num_operands (isa, opc);
44075fd0b74Schristos       first = 1;
44175fd0b74Schristos       for (i = 0; i < noperands; i++)
44275fd0b74Schristos 	{
44375fd0b74Schristos 	  if (xtensa_operand_is_visible (isa, opc, i) == 0)
44475fd0b74Schristos 	    continue;
44575fd0b74Schristos 	  if (first)
44675fd0b74Schristos 	    {
44775fd0b74Schristos 	      (*info->fprintf_func) (info->stream, "\t");
44875fd0b74Schristos 	      first = 0;
44975fd0b74Schristos 	    }
45075fd0b74Schristos 	  else
45175fd0b74Schristos 	    (*info->fprintf_func) (info->stream, ", ");
45275fd0b74Schristos 	  (void) xtensa_operand_get_field (isa, opc, i, fmt, n,
45375fd0b74Schristos 					   slot_buffer, &operand_val);
45475fd0b74Schristos 
45575fd0b74Schristos 	  print_xtensa_operand (memaddr, info, opc, i, operand_val);
45675fd0b74Schristos 	}
45775fd0b74Schristos     }
45875fd0b74Schristos 
45975fd0b74Schristos   if (nslots > 1)
46075fd0b74Schristos     (*info->fprintf_func) (info->stream, " }");
46175fd0b74Schristos 
46275fd0b74Schristos   info->bytes_per_chunk = size;
46375fd0b74Schristos   info->display_endian = info->endian;
46475fd0b74Schristos 
46575fd0b74Schristos   return size;
46675fd0b74Schristos }
46775fd0b74Schristos 
468