• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* xtensa-dis.c.  Disassembly functions for Xtensa.
2    Copyright (C) 2003-2014 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 "dis-asm.h"
31 
32 #include <setjmp.h>
33 
34 extern xtensa_isa xtensa_default_isa;
35 
36 #ifndef MAX
37 #define MAX(a,b) (a > b ? a : b)
38 #endif
39 
40 int show_raw_fields;
41 
42 struct dis_private
43 {
44   bfd_byte *byte_buf;
45   OPCODES_SIGJMP_BUF bailout;
46 };
47 
48 
49 static int
fetch_data(struct disassemble_info * info,bfd_vma memaddr)50 fetch_data (struct disassemble_info *info, bfd_vma memaddr)
51 {
52   int length, status = 0;
53   struct dis_private *priv = (struct dis_private *) info->private_data;
54   int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
55 
56   /* Read the maximum instruction size, padding with zeros if we go past
57      the end of the text section.  This code will automatically adjust
58      length when we hit the end of the buffer.  */
59 
60   memset (priv->byte_buf, 0, insn_size);
61   for (length = insn_size; length > 0; length--)
62     {
63       status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
64 					  info);
65       if (status == 0)
66 	return length;
67     }
68   (*info->memory_error_func) (status, memaddr, info);
69   OPCODES_SIGLONGJMP (priv->bailout, 1);
70   /*NOTREACHED*/
71 }
72 
73 
74 static void
print_xtensa_operand(bfd_vma memaddr,struct disassemble_info * info,xtensa_opcode opc,int opnd,unsigned operand_val)75 print_xtensa_operand (bfd_vma memaddr,
76 		      struct disassemble_info *info,
77 		      xtensa_opcode opc,
78 		      int opnd,
79 		      unsigned operand_val)
80 {
81   xtensa_isa isa = xtensa_default_isa;
82   int signed_operand_val;
83 
84   if (show_raw_fields)
85     {
86       if (operand_val < 0xa)
87 	(*info->fprintf_func) (info->stream, "%u", operand_val);
88       else
89 	(*info->fprintf_func) (info->stream, "0x%x", operand_val);
90       return;
91     }
92 
93   (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
94   signed_operand_val = (int) operand_val;
95 
96   if (xtensa_operand_is_register (isa, opc, opnd) == 0)
97     {
98       if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
99 	{
100 	  (void) xtensa_operand_undo_reloc (isa, opc, opnd,
101 					    &operand_val, memaddr);
102 	  info->target = operand_val;
103 	  (*info->print_address_func) (info->target, info);
104 	}
105       else
106 	{
107 	  if ((signed_operand_val > -256) && (signed_operand_val < 256))
108 	    (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
109 	  else
110 	    (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
111 	}
112     }
113   else
114     {
115       int i = 1;
116       xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
117       (*info->fprintf_func) (info->stream, "%s%u",
118 			     xtensa_regfile_shortname (isa, opnd_rf),
119 			     operand_val);
120       while (i < xtensa_operand_num_regs (isa, opc, opnd))
121 	{
122 	  operand_val++;
123 	  (*info->fprintf_func) (info->stream, ":%s%u",
124 				 xtensa_regfile_shortname (isa, opnd_rf),
125 				 operand_val);
126 	  i++;
127 	}
128     }
129 }
130 
131 
132 /* Print the Xtensa instruction at address MEMADDR on info->stream.
133    Returns length of the instruction in bytes.  */
134 
135 int
print_insn_xtensa(bfd_vma memaddr,struct disassemble_info * info)136 print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info)
137 {
138   unsigned operand_val;
139   int bytes_fetched, size, maxsize, i, n, noperands, nslots;
140   xtensa_isa isa;
141   xtensa_opcode opc;
142   xtensa_format fmt;
143   struct dis_private priv;
144   static bfd_byte *byte_buf = NULL;
145   static xtensa_insnbuf insn_buffer = NULL;
146   static xtensa_insnbuf slot_buffer = NULL;
147   int first, first_slot, valid_insn;
148 
149   if (!xtensa_default_isa)
150     xtensa_default_isa = xtensa_isa_init (0, 0);
151 
152   info->target = 0;
153   maxsize = xtensa_isa_maxlength (xtensa_default_isa);
154 
155   /* Set bytes_per_line to control the amount of whitespace between the hex
156      values and the opcode.  For Xtensa, we always print one "chunk" and we
157      vary bytes_per_chunk to determine how many bytes to print.  (objdump
158      would apparently prefer that we set bytes_per_chunk to 1 and vary
159      bytes_per_line but that makes it hard to fit 64-bit instructions on
160      an 80-column screen.)  The value of bytes_per_line here is not exactly
161      right, because objdump adds an extra space for each chunk so that the
162      amount of whitespace depends on the chunk size.  Oh well, it's good
163      enough....  Note that we set the minimum size to 4 to accomodate
164      literal pools.  */
165   info->bytes_per_line = MAX (maxsize, 4);
166 
167   /* Allocate buffers the first time through.  */
168   if (!insn_buffer)
169     {
170       insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
171       slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
172       byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
173     }
174 
175   priv.byte_buf = byte_buf;
176 
177   info->private_data = (void *) &priv;
178   if (OPCODES_SIGSETJMP (priv.bailout) != 0)
179       /* Error return.  */
180       return -1;
181 
182   /* Don't set "isa" before the setjmp to keep the compiler from griping.  */
183   isa = xtensa_default_isa;
184   size = 0;
185   nslots = 0;
186 
187   /* Fetch the maximum size instruction.  */
188   bytes_fetched = fetch_data (info, memaddr);
189 
190   /* Copy the bytes into the decode buffer.  */
191   memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
192 			   sizeof (xtensa_insnbuf_word)));
193   xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf, bytes_fetched);
194 
195   fmt = xtensa_format_decode (isa, insn_buffer);
196   if (fmt == XTENSA_UNDEFINED
197       || ((size = xtensa_format_length (isa, fmt)) > bytes_fetched))
198     valid_insn = 0;
199   else
200     {
201       /* Make sure all the opcodes are valid.  */
202       valid_insn = 1;
203       nslots = xtensa_format_num_slots (isa, fmt);
204       for (n = 0; n < nslots; n++)
205 	{
206 	  xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
207 	  if (xtensa_opcode_decode (isa, fmt, n, slot_buffer)
208 	      == XTENSA_UNDEFINED)
209 	    {
210 	      valid_insn = 0;
211 	      break;
212 	    }
213 	}
214     }
215 
216   if (!valid_insn)
217     {
218       (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
219       return 1;
220     }
221 
222   if (nslots > 1)
223     (*info->fprintf_func) (info->stream, "{ ");
224 
225   first_slot = 1;
226   for (n = 0; n < nslots; n++)
227     {
228       if (first_slot)
229 	first_slot = 0;
230       else
231 	(*info->fprintf_func) (info->stream, "; ");
232 
233       xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
234       opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
235       (*info->fprintf_func) (info->stream, "%s",
236 			     xtensa_opcode_name (isa, opc));
237 
238       /* Print the operands (if any).  */
239       noperands = xtensa_opcode_num_operands (isa, opc);
240       first = 1;
241       for (i = 0; i < noperands; i++)
242 	{
243 	  if (xtensa_operand_is_visible (isa, opc, i) == 0)
244 	    continue;
245 	  if (first)
246 	    {
247 	      (*info->fprintf_func) (info->stream, "\t");
248 	      first = 0;
249 	    }
250 	  else
251 	    (*info->fprintf_func) (info->stream, ", ");
252 	  (void) xtensa_operand_get_field (isa, opc, i, fmt, n,
253 					   slot_buffer, &operand_val);
254 
255 	  print_xtensa_operand (memaddr, info, opc, i, operand_val);
256 	}
257     }
258 
259   if (nslots > 1)
260     (*info->fprintf_func) (info->stream, " }");
261 
262   info->bytes_per_chunk = size;
263   info->display_endian = info->endian;
264 
265   return size;
266 }
267 
268