xref: /openbsd-src/gnu/usr.bin/binutils-2.17/opcodes/cris-dis.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* Disassembler code for CRIS.
2*3d8817e4Smiod    Copyright 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
3*3d8817e4Smiod    Contributed by Axis Communications AB, Lund, Sweden.
4*3d8817e4Smiod    Written by Hans-Peter Nilsson.
5*3d8817e4Smiod 
6*3d8817e4Smiod    This file is part of the GNU binutils and GDB, the GNU debugger.
7*3d8817e4Smiod 
8*3d8817e4Smiod    This program is free software; you can redistribute it and/or modify it
9*3d8817e4Smiod    under the terms of the GNU General Public License as published by the
10*3d8817e4Smiod    Free Software Foundation; either version 2, or (at your option) any later
11*3d8817e4Smiod    version.
12*3d8817e4Smiod 
13*3d8817e4Smiod    This program is distributed in the hope that it will be useful, but WITHOUT
14*3d8817e4Smiod    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*3d8817e4Smiod    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16*3d8817e4Smiod    more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod    You should have received a copy of the GNU General Public License
19*3d8817e4Smiod    along with this program; if not, write to the Free Software
20*3d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*3d8817e4Smiod    MA 02110-1301, USA.  */
22*3d8817e4Smiod 
23*3d8817e4Smiod #include "dis-asm.h"
24*3d8817e4Smiod #include "sysdep.h"
25*3d8817e4Smiod #include "opcode/cris.h"
26*3d8817e4Smiod #include "libiberty.h"
27*3d8817e4Smiod 
28*3d8817e4Smiod /* No instruction will be disassembled longer than this.  In theory, and
29*3d8817e4Smiod    in silicon, address prefixes can be cascaded.  In practice, cascading
30*3d8817e4Smiod    is not used by GCC, and not supported by the assembler.  */
31*3d8817e4Smiod #ifndef MAX_BYTES_PER_CRIS_INSN
32*3d8817e4Smiod #define MAX_BYTES_PER_CRIS_INSN 8
33*3d8817e4Smiod #endif
34*3d8817e4Smiod 
35*3d8817e4Smiod /* Whether or not to decode prefixes, folding it into the following
36*3d8817e4Smiod    instruction.  FIXME: Make this optional later.  */
37*3d8817e4Smiod #ifndef PARSE_PREFIX
38*3d8817e4Smiod #define PARSE_PREFIX 1
39*3d8817e4Smiod #endif
40*3d8817e4Smiod 
41*3d8817e4Smiod /* Sometimes we prefix all registers with this character.  */
42*3d8817e4Smiod #define REGISTER_PREFIX_CHAR '$'
43*3d8817e4Smiod 
44*3d8817e4Smiod /* Whether or not to trace the following sequence:
45*3d8817e4Smiod    sub* X,r%d
46*3d8817e4Smiod    bound* Y,r%d
47*3d8817e4Smiod    adds.w [pc+r%d.w],pc
48*3d8817e4Smiod 
49*3d8817e4Smiod    This is the assembly form of a switch-statement in C.
50*3d8817e4Smiod    The "sub is optional.  If there is none, then X will be zero.
51*3d8817e4Smiod    X is the value of the first case,
52*3d8817e4Smiod    Y is the number of cases (including default).
53*3d8817e4Smiod 
54*3d8817e4Smiod    This results in case offsets printed on the form:
55*3d8817e4Smiod     case N: -> case_address
56*3d8817e4Smiod    where N is an estimation on the corresponding 'case' operand in C,
57*3d8817e4Smiod    and case_address is where execution of that case continues after the
58*3d8817e4Smiod    sequence presented above.
59*3d8817e4Smiod 
60*3d8817e4Smiod    The old style of output was to print the offsets as instructions,
61*3d8817e4Smiod    which made it hard to follow "case"-constructs in the disassembly,
62*3d8817e4Smiod    and caused a lot of annoying warnings about undefined instructions.
63*3d8817e4Smiod 
64*3d8817e4Smiod    FIXME: Make this optional later.  */
65*3d8817e4Smiod #ifndef TRACE_CASE
66*3d8817e4Smiod #define TRACE_CASE (disdata->trace_case)
67*3d8817e4Smiod #endif
68*3d8817e4Smiod 
69*3d8817e4Smiod enum cris_disass_family
70*3d8817e4Smiod  { cris_dis_v0_v10, cris_dis_common_v10_v32, cris_dis_v32 };
71*3d8817e4Smiod 
72*3d8817e4Smiod /* Stored in the disasm_info->private_data member.  */
73*3d8817e4Smiod struct cris_disasm_data
74*3d8817e4Smiod {
75*3d8817e4Smiod   /* Whether to print something less confusing if we find something
76*3d8817e4Smiod      matching a switch-construct.  */
77*3d8817e4Smiod   bfd_boolean trace_case;
78*3d8817e4Smiod 
79*3d8817e4Smiod   /* Whether this code is flagged as crisv32.  FIXME: Should be an enum
80*3d8817e4Smiod      that includes "compatible".  */
81*3d8817e4Smiod   enum cris_disass_family distype;
82*3d8817e4Smiod };
83*3d8817e4Smiod 
84*3d8817e4Smiod /* Value of first element in switch.  */
85*3d8817e4Smiod static long case_offset = 0;
86*3d8817e4Smiod 
87*3d8817e4Smiod /* How many more case-offsets to print.  */
88*3d8817e4Smiod static long case_offset_counter = 0;
89*3d8817e4Smiod 
90*3d8817e4Smiod /* Number of case offsets.  */
91*3d8817e4Smiod static long no_of_case_offsets = 0;
92*3d8817e4Smiod 
93*3d8817e4Smiod /* Candidate for next case_offset.  */
94*3d8817e4Smiod static long last_immediate = 0;
95*3d8817e4Smiod 
96*3d8817e4Smiod static int cris_constraint
97*3d8817e4Smiod   (const char *, unsigned, unsigned, struct cris_disasm_data *);
98*3d8817e4Smiod 
99*3d8817e4Smiod /* Parse disassembler options and store state in info.  FIXME: For the
100*3d8817e4Smiod    time being, we abuse static variables.  */
101*3d8817e4Smiod 
102*3d8817e4Smiod static bfd_boolean
cris_parse_disassembler_options(disassemble_info * info,enum cris_disass_family distype)103*3d8817e4Smiod cris_parse_disassembler_options (disassemble_info *info,
104*3d8817e4Smiod 				 enum cris_disass_family distype)
105*3d8817e4Smiod {
106*3d8817e4Smiod   struct cris_disasm_data *disdata;
107*3d8817e4Smiod 
108*3d8817e4Smiod   info->private_data = calloc (1, sizeof (struct cris_disasm_data));
109*3d8817e4Smiod   disdata = (struct cris_disasm_data *) info->private_data;
110*3d8817e4Smiod   if (disdata == NULL)
111*3d8817e4Smiod     return FALSE;
112*3d8817e4Smiod 
113*3d8817e4Smiod   /* Default true.  */
114*3d8817e4Smiod   disdata->trace_case
115*3d8817e4Smiod     = (info->disassembler_options == NULL
116*3d8817e4Smiod        || (strcmp (info->disassembler_options, "nocase") != 0));
117*3d8817e4Smiod 
118*3d8817e4Smiod   disdata->distype = distype;
119*3d8817e4Smiod   return TRUE;
120*3d8817e4Smiod }
121*3d8817e4Smiod 
122*3d8817e4Smiod static const struct cris_spec_reg *
spec_reg_info(unsigned int sreg,enum cris_disass_family distype)123*3d8817e4Smiod spec_reg_info (unsigned int sreg, enum cris_disass_family distype)
124*3d8817e4Smiod {
125*3d8817e4Smiod   int i;
126*3d8817e4Smiod 
127*3d8817e4Smiod   for (i = 0; cris_spec_regs[i].name != NULL; i++)
128*3d8817e4Smiod     {
129*3d8817e4Smiod       if (cris_spec_regs[i].number == sreg)
130*3d8817e4Smiod 	{
131*3d8817e4Smiod 	  if (distype == cris_dis_v32)
132*3d8817e4Smiod 	    switch (cris_spec_regs[i].applicable_version)
133*3d8817e4Smiod 	      {
134*3d8817e4Smiod 	      case cris_ver_warning:
135*3d8817e4Smiod 	      case cris_ver_version_all:
136*3d8817e4Smiod 	      case cris_ver_v3p:
137*3d8817e4Smiod 	      case cris_ver_v8p:
138*3d8817e4Smiod 	      case cris_ver_v10p:
139*3d8817e4Smiod 	      case cris_ver_v32p:
140*3d8817e4Smiod 		/* No ambiguous sizes or register names with CRISv32.  */
141*3d8817e4Smiod 		if (cris_spec_regs[i].warning == NULL)
142*3d8817e4Smiod 		  return &cris_spec_regs[i];
143*3d8817e4Smiod 	      default:
144*3d8817e4Smiod 		;
145*3d8817e4Smiod 	      }
146*3d8817e4Smiod 	  else if (cris_spec_regs[i].applicable_version != cris_ver_v32p)
147*3d8817e4Smiod 	    return &cris_spec_regs[i];
148*3d8817e4Smiod 	}
149*3d8817e4Smiod     }
150*3d8817e4Smiod 
151*3d8817e4Smiod   return NULL;
152*3d8817e4Smiod }
153*3d8817e4Smiod 
154*3d8817e4Smiod /* Return the number of bits in the argument.  */
155*3d8817e4Smiod 
156*3d8817e4Smiod static int
number_of_bits(unsigned int val)157*3d8817e4Smiod number_of_bits (unsigned int val)
158*3d8817e4Smiod {
159*3d8817e4Smiod   int bits;
160*3d8817e4Smiod 
161*3d8817e4Smiod   for (bits = 0; val != 0; val &= val - 1)
162*3d8817e4Smiod     bits++;
163*3d8817e4Smiod 
164*3d8817e4Smiod   return bits;
165*3d8817e4Smiod }
166*3d8817e4Smiod 
167*3d8817e4Smiod /* Get an entry in the opcode-table.  */
168*3d8817e4Smiod 
169*3d8817e4Smiod static const struct cris_opcode *
get_opcode_entry(unsigned int insn,unsigned int prefix_insn,struct cris_disasm_data * disdata)170*3d8817e4Smiod get_opcode_entry (unsigned int insn,
171*3d8817e4Smiod 		  unsigned int prefix_insn,
172*3d8817e4Smiod 		  struct cris_disasm_data *disdata)
173*3d8817e4Smiod {
174*3d8817e4Smiod   /* For non-prefixed insns, we keep a table of pointers, indexed by the
175*3d8817e4Smiod      insn code.  Each entry is initialized when found to be NULL.  */
176*3d8817e4Smiod   static const struct cris_opcode **opc_table = NULL;
177*3d8817e4Smiod 
178*3d8817e4Smiod   const struct cris_opcode *max_matchedp = NULL;
179*3d8817e4Smiod   const struct cris_opcode **prefix_opc_table = NULL;
180*3d8817e4Smiod 
181*3d8817e4Smiod   /* We hold a table for each prefix that need to be handled differently.  */
182*3d8817e4Smiod   static const struct cris_opcode **dip_prefixes = NULL;
183*3d8817e4Smiod   static const struct cris_opcode **bdapq_m1_prefixes = NULL;
184*3d8817e4Smiod   static const struct cris_opcode **bdapq_m2_prefixes = NULL;
185*3d8817e4Smiod   static const struct cris_opcode **bdapq_m4_prefixes = NULL;
186*3d8817e4Smiod   static const struct cris_opcode **rest_prefixes = NULL;
187*3d8817e4Smiod 
188*3d8817e4Smiod   /* Allocate and clear the opcode-table.  */
189*3d8817e4Smiod   if (opc_table == NULL)
190*3d8817e4Smiod     {
191*3d8817e4Smiod       opc_table = malloc (65536 * sizeof (opc_table[0]));
192*3d8817e4Smiod       if (opc_table == NULL)
193*3d8817e4Smiod 	return NULL;
194*3d8817e4Smiod 
195*3d8817e4Smiod       memset (opc_table, 0, 65536 * sizeof (const struct cris_opcode *));
196*3d8817e4Smiod 
197*3d8817e4Smiod       dip_prefixes
198*3d8817e4Smiod 	= malloc (65536 * sizeof (const struct cris_opcode **));
199*3d8817e4Smiod       if (dip_prefixes == NULL)
200*3d8817e4Smiod 	return NULL;
201*3d8817e4Smiod 
202*3d8817e4Smiod       memset (dip_prefixes, 0, 65536 * sizeof (dip_prefixes[0]));
203*3d8817e4Smiod 
204*3d8817e4Smiod       bdapq_m1_prefixes
205*3d8817e4Smiod 	= malloc (65536 * sizeof (const struct cris_opcode **));
206*3d8817e4Smiod       if (bdapq_m1_prefixes == NULL)
207*3d8817e4Smiod 	return NULL;
208*3d8817e4Smiod 
209*3d8817e4Smiod       memset (bdapq_m1_prefixes, 0, 65536 * sizeof (bdapq_m1_prefixes[0]));
210*3d8817e4Smiod 
211*3d8817e4Smiod       bdapq_m2_prefixes
212*3d8817e4Smiod 	= malloc (65536 * sizeof (const struct cris_opcode **));
213*3d8817e4Smiod       if (bdapq_m2_prefixes == NULL)
214*3d8817e4Smiod 	return NULL;
215*3d8817e4Smiod 
216*3d8817e4Smiod       memset (bdapq_m2_prefixes, 0, 65536 * sizeof (bdapq_m2_prefixes[0]));
217*3d8817e4Smiod 
218*3d8817e4Smiod       bdapq_m4_prefixes
219*3d8817e4Smiod 	= malloc (65536 * sizeof (const struct cris_opcode **));
220*3d8817e4Smiod       if (bdapq_m4_prefixes == NULL)
221*3d8817e4Smiod 	return NULL;
222*3d8817e4Smiod 
223*3d8817e4Smiod       memset (bdapq_m4_prefixes, 0, 65536 * sizeof (bdapq_m4_prefixes[0]));
224*3d8817e4Smiod 
225*3d8817e4Smiod       rest_prefixes
226*3d8817e4Smiod 	= malloc (65536 * sizeof (const struct cris_opcode **));
227*3d8817e4Smiod       if (rest_prefixes == NULL)
228*3d8817e4Smiod 	return NULL;
229*3d8817e4Smiod 
230*3d8817e4Smiod       memset (rest_prefixes, 0, 65536 * sizeof (rest_prefixes[0]));
231*3d8817e4Smiod     }
232*3d8817e4Smiod 
233*3d8817e4Smiod   /* Get the right table if this is a prefix.
234*3d8817e4Smiod      This code is connected to cris_constraints in that it knows what
235*3d8817e4Smiod      prefixes play a role in recognition of patterns; the necessary
236*3d8817e4Smiod      state is reflected by which table is used.  If constraints
237*3d8817e4Smiod      involving match or non-match of prefix insns are changed, then this
238*3d8817e4Smiod      probably needs changing too.  */
239*3d8817e4Smiod   if (prefix_insn != NO_CRIS_PREFIX)
240*3d8817e4Smiod     {
241*3d8817e4Smiod       const struct cris_opcode *popcodep
242*3d8817e4Smiod 	= (opc_table[prefix_insn] != NULL
243*3d8817e4Smiod 	   ? opc_table[prefix_insn]
244*3d8817e4Smiod 	   : get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata));
245*3d8817e4Smiod 
246*3d8817e4Smiod       if (popcodep == NULL)
247*3d8817e4Smiod 	return NULL;
248*3d8817e4Smiod 
249*3d8817e4Smiod       if (popcodep->match == BDAP_QUICK_OPCODE)
250*3d8817e4Smiod 	{
251*3d8817e4Smiod 	  /* Since some offsets are recognized with "push" macros, we
252*3d8817e4Smiod 	     have to have different tables for them.  */
253*3d8817e4Smiod 	  int offset = (prefix_insn & 255);
254*3d8817e4Smiod 
255*3d8817e4Smiod 	  if (offset > 127)
256*3d8817e4Smiod 	    offset -= 256;
257*3d8817e4Smiod 
258*3d8817e4Smiod 	  switch (offset)
259*3d8817e4Smiod 	    {
260*3d8817e4Smiod 	    case -4:
261*3d8817e4Smiod 	      prefix_opc_table = bdapq_m4_prefixes;
262*3d8817e4Smiod 	      break;
263*3d8817e4Smiod 
264*3d8817e4Smiod 	    case -2:
265*3d8817e4Smiod 	      prefix_opc_table = bdapq_m2_prefixes;
266*3d8817e4Smiod 	      break;
267*3d8817e4Smiod 
268*3d8817e4Smiod 	    case -1:
269*3d8817e4Smiod 	      prefix_opc_table = bdapq_m1_prefixes;
270*3d8817e4Smiod 	      break;
271*3d8817e4Smiod 
272*3d8817e4Smiod 	    default:
273*3d8817e4Smiod 	      prefix_opc_table = rest_prefixes;
274*3d8817e4Smiod 	      break;
275*3d8817e4Smiod 	    }
276*3d8817e4Smiod 	}
277*3d8817e4Smiod       else if (popcodep->match == DIP_OPCODE)
278*3d8817e4Smiod 	/* We don't allow postincrement when the prefix is DIP, so use a
279*3d8817e4Smiod 	   different table for DIP.  */
280*3d8817e4Smiod 	prefix_opc_table = dip_prefixes;
281*3d8817e4Smiod       else
282*3d8817e4Smiod 	prefix_opc_table = rest_prefixes;
283*3d8817e4Smiod     }
284*3d8817e4Smiod 
285*3d8817e4Smiod   if (prefix_insn != NO_CRIS_PREFIX
286*3d8817e4Smiod       && prefix_opc_table[insn] != NULL)
287*3d8817e4Smiod     max_matchedp = prefix_opc_table[insn];
288*3d8817e4Smiod   else if (prefix_insn == NO_CRIS_PREFIX && opc_table[insn] != NULL)
289*3d8817e4Smiod     max_matchedp = opc_table[insn];
290*3d8817e4Smiod   else
291*3d8817e4Smiod     {
292*3d8817e4Smiod       const struct cris_opcode *opcodep;
293*3d8817e4Smiod       int max_level_of_match = -1;
294*3d8817e4Smiod 
295*3d8817e4Smiod       for (opcodep = cris_opcodes;
296*3d8817e4Smiod 	   opcodep->name != NULL;
297*3d8817e4Smiod 	   opcodep++)
298*3d8817e4Smiod 	{
299*3d8817e4Smiod 	  int level_of_match;
300*3d8817e4Smiod 
301*3d8817e4Smiod 	  if (disdata->distype == cris_dis_v32)
302*3d8817e4Smiod 	    {
303*3d8817e4Smiod 	      switch (opcodep->applicable_version)
304*3d8817e4Smiod 		{
305*3d8817e4Smiod 		case cris_ver_version_all:
306*3d8817e4Smiod 		  break;
307*3d8817e4Smiod 
308*3d8817e4Smiod 		case cris_ver_v0_3:
309*3d8817e4Smiod 		case cris_ver_v0_10:
310*3d8817e4Smiod 		case cris_ver_v3_10:
311*3d8817e4Smiod 		case cris_ver_sim_v0_10:
312*3d8817e4Smiod 		case cris_ver_v8_10:
313*3d8817e4Smiod 		case cris_ver_v10:
314*3d8817e4Smiod 		case cris_ver_warning:
315*3d8817e4Smiod 		  continue;
316*3d8817e4Smiod 
317*3d8817e4Smiod 		case cris_ver_v3p:
318*3d8817e4Smiod 		case cris_ver_v8p:
319*3d8817e4Smiod 		case cris_ver_v10p:
320*3d8817e4Smiod 		case cris_ver_v32p:
321*3d8817e4Smiod 		  break;
322*3d8817e4Smiod 
323*3d8817e4Smiod 		case cris_ver_v8:
324*3d8817e4Smiod 		  abort ();
325*3d8817e4Smiod 		default:
326*3d8817e4Smiod 		  abort ();
327*3d8817e4Smiod 		}
328*3d8817e4Smiod 	    }
329*3d8817e4Smiod 	  else
330*3d8817e4Smiod 	    {
331*3d8817e4Smiod 	      switch (opcodep->applicable_version)
332*3d8817e4Smiod 		{
333*3d8817e4Smiod 		case cris_ver_version_all:
334*3d8817e4Smiod 		case cris_ver_v0_3:
335*3d8817e4Smiod 		case cris_ver_v3p:
336*3d8817e4Smiod 		case cris_ver_v0_10:
337*3d8817e4Smiod 		case cris_ver_v8p:
338*3d8817e4Smiod 		case cris_ver_v8_10:
339*3d8817e4Smiod 		case cris_ver_v10:
340*3d8817e4Smiod 		case cris_ver_sim_v0_10:
341*3d8817e4Smiod 		case cris_ver_v10p:
342*3d8817e4Smiod 		case cris_ver_warning:
343*3d8817e4Smiod 		  break;
344*3d8817e4Smiod 
345*3d8817e4Smiod 		case cris_ver_v32p:
346*3d8817e4Smiod 		  continue;
347*3d8817e4Smiod 
348*3d8817e4Smiod 		case cris_ver_v8:
349*3d8817e4Smiod 		  abort ();
350*3d8817e4Smiod 		default:
351*3d8817e4Smiod 		  abort ();
352*3d8817e4Smiod 		}
353*3d8817e4Smiod 	    }
354*3d8817e4Smiod 
355*3d8817e4Smiod 	  /* We give a double lead for bits matching the template in
356*3d8817e4Smiod 	     cris_opcodes.  Not even, because then "move p8,r10" would
357*3d8817e4Smiod 	     be given 2 bits lead over "clear.d r10".  When there's a
358*3d8817e4Smiod 	     tie, the first entry in the table wins.  This is
359*3d8817e4Smiod 	     deliberate, to avoid a more complicated recognition
360*3d8817e4Smiod 	     formula.  */
361*3d8817e4Smiod 	  if ((opcodep->match & insn) == opcodep->match
362*3d8817e4Smiod 	      && (opcodep->lose & insn) == 0
363*3d8817e4Smiod 	      && ((level_of_match
364*3d8817e4Smiod 		   = cris_constraint (opcodep->args,
365*3d8817e4Smiod 				      insn,
366*3d8817e4Smiod 				      prefix_insn,
367*3d8817e4Smiod 				      disdata))
368*3d8817e4Smiod 		  >= 0)
369*3d8817e4Smiod 	      && ((level_of_match
370*3d8817e4Smiod 		   += 2 * number_of_bits (opcodep->match
371*3d8817e4Smiod 					  | opcodep->lose))
372*3d8817e4Smiod 			  > max_level_of_match))
373*3d8817e4Smiod 		    {
374*3d8817e4Smiod 		      max_matchedp = opcodep;
375*3d8817e4Smiod 		      max_level_of_match = level_of_match;
376*3d8817e4Smiod 
377*3d8817e4Smiod 		      /* If there was a full match, never mind looking
378*3d8817e4Smiod 			 further.  */
379*3d8817e4Smiod 		      if (level_of_match >= 2 * 16)
380*3d8817e4Smiod 			break;
381*3d8817e4Smiod 		    }
382*3d8817e4Smiod 		}
383*3d8817e4Smiod       /* Fill in the new entry.
384*3d8817e4Smiod 
385*3d8817e4Smiod 	 If there are changes to the opcode-table involving prefixes, and
386*3d8817e4Smiod 	 disassembly then does not work correctly, try removing the
387*3d8817e4Smiod 	 else-clause below that fills in the prefix-table.  If that
388*3d8817e4Smiod 	 helps, you need to change the prefix_opc_table setting above, or
389*3d8817e4Smiod 	 something related.  */
390*3d8817e4Smiod       if (prefix_insn == NO_CRIS_PREFIX)
391*3d8817e4Smiod 	opc_table[insn] = max_matchedp;
392*3d8817e4Smiod       else
393*3d8817e4Smiod 	prefix_opc_table[insn] = max_matchedp;
394*3d8817e4Smiod     }
395*3d8817e4Smiod 
396*3d8817e4Smiod   return max_matchedp;
397*3d8817e4Smiod }
398*3d8817e4Smiod 
399*3d8817e4Smiod /* Return -1 if the constraints of a bitwise-matched instruction say
400*3d8817e4Smiod    that there is no match.  Otherwise return a nonnegative number
401*3d8817e4Smiod    indicating the confidence in the match (higher is better).  */
402*3d8817e4Smiod 
403*3d8817e4Smiod static int
cris_constraint(const char * cs,unsigned int insn,unsigned int prefix_insn,struct cris_disasm_data * disdata)404*3d8817e4Smiod cris_constraint (const char *cs,
405*3d8817e4Smiod 		 unsigned int insn,
406*3d8817e4Smiod 		 unsigned int prefix_insn,
407*3d8817e4Smiod 		 struct cris_disasm_data *disdata)
408*3d8817e4Smiod {
409*3d8817e4Smiod   int retval = 0;
410*3d8817e4Smiod   int tmp;
411*3d8817e4Smiod   int prefix_ok = 0;
412*3d8817e4Smiod   const char *s;
413*3d8817e4Smiod 
414*3d8817e4Smiod   for (s = cs; *s; s++)
415*3d8817e4Smiod     switch (*s)
416*3d8817e4Smiod       {
417*3d8817e4Smiod       case '!':
418*3d8817e4Smiod 	/* Do not recognize "pop" if there's a prefix and then only for
419*3d8817e4Smiod            v0..v10.  */
420*3d8817e4Smiod 	if (prefix_insn != NO_CRIS_PREFIX
421*3d8817e4Smiod 	    || disdata->distype != cris_dis_v0_v10)
422*3d8817e4Smiod 	  return -1;
423*3d8817e4Smiod 	break;
424*3d8817e4Smiod 
425*3d8817e4Smiod       case 'U':
426*3d8817e4Smiod 	/* Not recognized at disassembly.  */
427*3d8817e4Smiod 	return -1;
428*3d8817e4Smiod 
429*3d8817e4Smiod       case 'M':
430*3d8817e4Smiod 	/* Size modifier for "clear", i.e. special register 0, 4 or 8.
431*3d8817e4Smiod 	   Check that it is one of them.  Only special register 12 could
432*3d8817e4Smiod 	   be mismatched, but checking for matches is more logical than
433*3d8817e4Smiod 	   checking for mismatches when there are only a few cases.  */
434*3d8817e4Smiod 	tmp = ((insn >> 12) & 0xf);
435*3d8817e4Smiod 	if (tmp != 0 && tmp != 4 && tmp != 8)
436*3d8817e4Smiod 	  return -1;
437*3d8817e4Smiod 	break;
438*3d8817e4Smiod 
439*3d8817e4Smiod       case 'm':
440*3d8817e4Smiod 	if ((insn & 0x30) == 0x30)
441*3d8817e4Smiod 	  return -1;
442*3d8817e4Smiod 	break;
443*3d8817e4Smiod 
444*3d8817e4Smiod       case 'S':
445*3d8817e4Smiod 	/* A prefix operand without side-effect.  */
446*3d8817e4Smiod 	if (prefix_insn != NO_CRIS_PREFIX && (insn & 0x400) == 0)
447*3d8817e4Smiod 	  {
448*3d8817e4Smiod 	    prefix_ok = 1;
449*3d8817e4Smiod 	    break;
450*3d8817e4Smiod 	  }
451*3d8817e4Smiod 	else
452*3d8817e4Smiod 	  return -1;
453*3d8817e4Smiod 
454*3d8817e4Smiod       case 's':
455*3d8817e4Smiod       case 'y':
456*3d8817e4Smiod       case 'Y':
457*3d8817e4Smiod 	/* If this is a prefixed insn with postincrement (side-effect),
458*3d8817e4Smiod 	   the prefix must not be DIP.  */
459*3d8817e4Smiod 	if (prefix_insn != NO_CRIS_PREFIX)
460*3d8817e4Smiod 	  {
461*3d8817e4Smiod 	    if (insn & 0x400)
462*3d8817e4Smiod 	      {
463*3d8817e4Smiod 		const struct cris_opcode *prefix_opcodep
464*3d8817e4Smiod 		  = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata);
465*3d8817e4Smiod 
466*3d8817e4Smiod 		if (prefix_opcodep->match == DIP_OPCODE)
467*3d8817e4Smiod 		  return -1;
468*3d8817e4Smiod 	      }
469*3d8817e4Smiod 
470*3d8817e4Smiod 	    prefix_ok = 1;
471*3d8817e4Smiod 	  }
472*3d8817e4Smiod 	break;
473*3d8817e4Smiod 
474*3d8817e4Smiod       case 'B':
475*3d8817e4Smiod 	/* If we don't fall through, then the prefix is ok.  */
476*3d8817e4Smiod 	prefix_ok = 1;
477*3d8817e4Smiod 
478*3d8817e4Smiod 	/* A "push" prefix.  Check for valid "push" size.
479*3d8817e4Smiod 	   In case of special register, it may be != 4.  */
480*3d8817e4Smiod 	if (prefix_insn != NO_CRIS_PREFIX)
481*3d8817e4Smiod 	  {
482*3d8817e4Smiod 	    /* Match the prefix insn to BDAPQ.  */
483*3d8817e4Smiod 	    const struct cris_opcode *prefix_opcodep
484*3d8817e4Smiod 	      = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata);
485*3d8817e4Smiod 
486*3d8817e4Smiod 	    if (prefix_opcodep->match == BDAP_QUICK_OPCODE)
487*3d8817e4Smiod 	      {
488*3d8817e4Smiod 		int pushsize = (prefix_insn & 255);
489*3d8817e4Smiod 
490*3d8817e4Smiod 		if (pushsize > 127)
491*3d8817e4Smiod 		  pushsize -= 256;
492*3d8817e4Smiod 
493*3d8817e4Smiod 		if (s[1] == 'P')
494*3d8817e4Smiod 		  {
495*3d8817e4Smiod 		    unsigned int spec_reg = (insn >> 12) & 15;
496*3d8817e4Smiod 		    const struct cris_spec_reg *sregp
497*3d8817e4Smiod 		      = spec_reg_info (spec_reg, disdata->distype);
498*3d8817e4Smiod 
499*3d8817e4Smiod 		    /* For a special-register, the "prefix size" must
500*3d8817e4Smiod 		       match the size of the register.  */
501*3d8817e4Smiod 		    if (sregp && sregp->reg_size == (unsigned int) -pushsize)
502*3d8817e4Smiod 		      break;
503*3d8817e4Smiod 		  }
504*3d8817e4Smiod 		else if (s[1] == 'R')
505*3d8817e4Smiod 		  {
506*3d8817e4Smiod 		    if ((insn & 0x30) == 0x20 && pushsize == -4)
507*3d8817e4Smiod 		      break;
508*3d8817e4Smiod 		  }
509*3d8817e4Smiod 		/* FIXME:  Should abort here; next constraint letter
510*3d8817e4Smiod 		   *must* be 'P' or 'R'.  */
511*3d8817e4Smiod 	      }
512*3d8817e4Smiod 	  }
513*3d8817e4Smiod 	return -1;
514*3d8817e4Smiod 
515*3d8817e4Smiod       case 'D':
516*3d8817e4Smiod 	retval = (((insn >> 12) & 15) == (insn & 15));
517*3d8817e4Smiod 	if (!retval)
518*3d8817e4Smiod 	  return -1;
519*3d8817e4Smiod 	else
520*3d8817e4Smiod 	  retval += 4;
521*3d8817e4Smiod 	break;
522*3d8817e4Smiod 
523*3d8817e4Smiod       case 'P':
524*3d8817e4Smiod 	{
525*3d8817e4Smiod 	  const struct cris_spec_reg *sregp
526*3d8817e4Smiod 	    = spec_reg_info ((insn >> 12) & 15, disdata->distype);
527*3d8817e4Smiod 
528*3d8817e4Smiod 	  /* Since we match four bits, we will give a value of 4-1 = 3
529*3d8817e4Smiod 	     in a match.  If there is a corresponding exact match of a
530*3d8817e4Smiod 	     special register in another pattern, it will get a value of
531*3d8817e4Smiod 	     4, which will be higher.  This should be correct in that an
532*3d8817e4Smiod 	     exact pattern would match better than a general pattern.
533*3d8817e4Smiod 
534*3d8817e4Smiod 	     Note that there is a reason for not returning zero; the
535*3d8817e4Smiod 	     pattern for "clear" is partly  matched in the bit-pattern
536*3d8817e4Smiod 	     (the two lower bits must be zero), while the bit-pattern
537*3d8817e4Smiod 	     for a move from a special register is matched in the
538*3d8817e4Smiod 	     register constraint.  */
539*3d8817e4Smiod 
540*3d8817e4Smiod 	  if (sregp != NULL)
541*3d8817e4Smiod 	    {
542*3d8817e4Smiod 	      retval += 3;
543*3d8817e4Smiod 	      break;
544*3d8817e4Smiod 	    }
545*3d8817e4Smiod 	  else
546*3d8817e4Smiod 	    return -1;
547*3d8817e4Smiod 	}
548*3d8817e4Smiod       }
549*3d8817e4Smiod 
550*3d8817e4Smiod   if (prefix_insn != NO_CRIS_PREFIX && ! prefix_ok)
551*3d8817e4Smiod     return -1;
552*3d8817e4Smiod 
553*3d8817e4Smiod   return retval;
554*3d8817e4Smiod }
555*3d8817e4Smiod 
556*3d8817e4Smiod /* Format number as hex with a leading "0x" into outbuffer.  */
557*3d8817e4Smiod 
558*3d8817e4Smiod static char *
format_hex(unsigned long number,char * outbuffer,struct cris_disasm_data * disdata)559*3d8817e4Smiod format_hex (unsigned long number,
560*3d8817e4Smiod 	    char *outbuffer,
561*3d8817e4Smiod 	    struct cris_disasm_data *disdata)
562*3d8817e4Smiod {
563*3d8817e4Smiod   /* Truncate negative numbers on >32-bit hosts.  */
564*3d8817e4Smiod   number &= 0xffffffff;
565*3d8817e4Smiod 
566*3d8817e4Smiod   sprintf (outbuffer, "0x%lx", number);
567*3d8817e4Smiod 
568*3d8817e4Smiod   /* Save this value for the "case" support.  */
569*3d8817e4Smiod   if (TRACE_CASE)
570*3d8817e4Smiod     last_immediate = number;
571*3d8817e4Smiod 
572*3d8817e4Smiod   return outbuffer + strlen (outbuffer);
573*3d8817e4Smiod }
574*3d8817e4Smiod 
575*3d8817e4Smiod /* Format number as decimal into outbuffer.  Parameter signedp says
576*3d8817e4Smiod    whether the number should be formatted as signed (!= 0) or
577*3d8817e4Smiod    unsigned (== 0).  */
578*3d8817e4Smiod 
579*3d8817e4Smiod static char *
format_dec(long number,char * outbuffer,int signedp)580*3d8817e4Smiod format_dec (long number, char *outbuffer, int signedp)
581*3d8817e4Smiod {
582*3d8817e4Smiod   last_immediate = number;
583*3d8817e4Smiod   sprintf (outbuffer, signedp ? "%ld" : "%lu", number);
584*3d8817e4Smiod 
585*3d8817e4Smiod   return outbuffer + strlen (outbuffer);
586*3d8817e4Smiod }
587*3d8817e4Smiod 
588*3d8817e4Smiod /* Format the name of the general register regno into outbuffer.  */
589*3d8817e4Smiod 
590*3d8817e4Smiod static char *
format_reg(struct cris_disasm_data * disdata,int regno,char * outbuffer_start,bfd_boolean with_reg_prefix)591*3d8817e4Smiod format_reg (struct cris_disasm_data *disdata,
592*3d8817e4Smiod 	    int regno,
593*3d8817e4Smiod 	    char *outbuffer_start,
594*3d8817e4Smiod 	    bfd_boolean with_reg_prefix)
595*3d8817e4Smiod {
596*3d8817e4Smiod   char *outbuffer = outbuffer_start;
597*3d8817e4Smiod 
598*3d8817e4Smiod   if (with_reg_prefix)
599*3d8817e4Smiod     *outbuffer++ = REGISTER_PREFIX_CHAR;
600*3d8817e4Smiod 
601*3d8817e4Smiod   switch (regno)
602*3d8817e4Smiod     {
603*3d8817e4Smiod     case 15:
604*3d8817e4Smiod       /* For v32, there is no context in which we output PC.  */
605*3d8817e4Smiod       if (disdata->distype == cris_dis_v32)
606*3d8817e4Smiod 	strcpy (outbuffer, "acr");
607*3d8817e4Smiod       else
608*3d8817e4Smiod 	strcpy (outbuffer, "pc");
609*3d8817e4Smiod       break;
610*3d8817e4Smiod 
611*3d8817e4Smiod     case 14:
612*3d8817e4Smiod       strcpy (outbuffer, "sp");
613*3d8817e4Smiod       break;
614*3d8817e4Smiod 
615*3d8817e4Smiod     default:
616*3d8817e4Smiod       sprintf (outbuffer, "r%d", regno);
617*3d8817e4Smiod       break;
618*3d8817e4Smiod     }
619*3d8817e4Smiod 
620*3d8817e4Smiod   return outbuffer_start + strlen (outbuffer_start);
621*3d8817e4Smiod }
622*3d8817e4Smiod 
623*3d8817e4Smiod /* Format the name of a support register into outbuffer.  */
624*3d8817e4Smiod 
625*3d8817e4Smiod static char *
format_sup_reg(unsigned int regno,char * outbuffer_start,bfd_boolean with_reg_prefix)626*3d8817e4Smiod format_sup_reg (unsigned int regno,
627*3d8817e4Smiod 		char *outbuffer_start,
628*3d8817e4Smiod 		bfd_boolean with_reg_prefix)
629*3d8817e4Smiod {
630*3d8817e4Smiod   char *outbuffer = outbuffer_start;
631*3d8817e4Smiod   int i;
632*3d8817e4Smiod 
633*3d8817e4Smiod   if (with_reg_prefix)
634*3d8817e4Smiod     *outbuffer++ = REGISTER_PREFIX_CHAR;
635*3d8817e4Smiod 
636*3d8817e4Smiod   for (i = 0; cris_support_regs[i].name != NULL; i++)
637*3d8817e4Smiod     if (cris_support_regs[i].number == regno)
638*3d8817e4Smiod       {
639*3d8817e4Smiod 	sprintf (outbuffer, "%s", cris_support_regs[i].name);
640*3d8817e4Smiod 	return outbuffer_start + strlen (outbuffer_start);
641*3d8817e4Smiod       }
642*3d8817e4Smiod 
643*3d8817e4Smiod   /* There's supposed to be register names covering all numbers, though
644*3d8817e4Smiod      some may be generic names.  */
645*3d8817e4Smiod   sprintf (outbuffer, "format_sup_reg-BUG");
646*3d8817e4Smiod   return outbuffer_start + strlen (outbuffer_start);
647*3d8817e4Smiod }
648*3d8817e4Smiod 
649*3d8817e4Smiod /* Return the length of an instruction.  */
650*3d8817e4Smiod 
651*3d8817e4Smiod static unsigned
bytes_to_skip(unsigned int insn,const struct cris_opcode * matchedp,enum cris_disass_family distype,const struct cris_opcode * prefix_matchedp)652*3d8817e4Smiod bytes_to_skip (unsigned int insn,
653*3d8817e4Smiod 	       const struct cris_opcode *matchedp,
654*3d8817e4Smiod 	       enum cris_disass_family distype,
655*3d8817e4Smiod 	       const struct cris_opcode *prefix_matchedp)
656*3d8817e4Smiod {
657*3d8817e4Smiod   /* Each insn is a word plus "immediate" operands.  */
658*3d8817e4Smiod   unsigned to_skip = 2;
659*3d8817e4Smiod   const char *template = matchedp->args;
660*3d8817e4Smiod   const char *s;
661*3d8817e4Smiod 
662*3d8817e4Smiod   for (s = template; *s; s++)
663*3d8817e4Smiod     if ((*s == 's' || *s == 'N' || *s == 'Y')
664*3d8817e4Smiod 	&& (insn & 0x400) && (insn & 15) == 15
665*3d8817e4Smiod 	&& prefix_matchedp == NULL)
666*3d8817e4Smiod       {
667*3d8817e4Smiod 	/* Immediate via [pc+], so we have to check the size of the
668*3d8817e4Smiod 	   operand.  */
669*3d8817e4Smiod 	int mode_size = 1 << ((insn >> 4) & (*template == 'z' ? 1 : 3));
670*3d8817e4Smiod 
671*3d8817e4Smiod 	if (matchedp->imm_oprnd_size == SIZE_FIX_32)
672*3d8817e4Smiod 	  to_skip += 4;
673*3d8817e4Smiod 	else if (matchedp->imm_oprnd_size == SIZE_SPEC_REG)
674*3d8817e4Smiod 	  {
675*3d8817e4Smiod 	    const struct cris_spec_reg *sregp
676*3d8817e4Smiod 	      = spec_reg_info ((insn >> 12) & 15, distype);
677*3d8817e4Smiod 
678*3d8817e4Smiod 	    /* FIXME: Improve error handling; should have been caught
679*3d8817e4Smiod 	       earlier.  */
680*3d8817e4Smiod 	    if (sregp == NULL)
681*3d8817e4Smiod 	      return 2;
682*3d8817e4Smiod 
683*3d8817e4Smiod 	    /* PC is incremented by two, not one, for a byte.  Except on
684*3d8817e4Smiod 	       CRISv32, where constants are always DWORD-size for
685*3d8817e4Smiod 	       special registers.  */
686*3d8817e4Smiod 	    to_skip +=
687*3d8817e4Smiod 	      distype == cris_dis_v32 ? 4 : (sregp->reg_size + 1) & ~1;
688*3d8817e4Smiod 	  }
689*3d8817e4Smiod 	else
690*3d8817e4Smiod 	  to_skip += (mode_size + 1) & ~1;
691*3d8817e4Smiod       }
692*3d8817e4Smiod     else if (*s == 'n')
693*3d8817e4Smiod       to_skip += 4;
694*3d8817e4Smiod     else if (*s == 'b')
695*3d8817e4Smiod       to_skip += 2;
696*3d8817e4Smiod 
697*3d8817e4Smiod   return to_skip;
698*3d8817e4Smiod }
699*3d8817e4Smiod 
700*3d8817e4Smiod /* Print condition code flags.  */
701*3d8817e4Smiod 
702*3d8817e4Smiod static char *
print_flags(struct cris_disasm_data * disdata,unsigned int insn,char * cp)703*3d8817e4Smiod print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp)
704*3d8817e4Smiod {
705*3d8817e4Smiod   /* Use the v8 (Etrax 100) flag definitions for disassembly.
706*3d8817e4Smiod      The differences with v0 (Etrax 1..4) vs. Svinto are:
707*3d8817e4Smiod       v0 'd' <=> v8 'm'
708*3d8817e4Smiod       v0 'e' <=> v8 'b'.
709*3d8817e4Smiod      FIXME: Emit v0..v3 flag names somehow.  */
710*3d8817e4Smiod   static const char v8_fnames[] = "cvznxibm";
711*3d8817e4Smiod   static const char v32_fnames[] = "cvznxiup";
712*3d8817e4Smiod   const char *fnames
713*3d8817e4Smiod     = disdata->distype == cris_dis_v32 ? v32_fnames : v8_fnames;
714*3d8817e4Smiod 
715*3d8817e4Smiod   unsigned char flagbits = (((insn >> 8) & 0xf0) | (insn & 15));
716*3d8817e4Smiod   int i;
717*3d8817e4Smiod 
718*3d8817e4Smiod   for (i = 0; i < 8; i++)
719*3d8817e4Smiod     if (flagbits & (1 << i))
720*3d8817e4Smiod       *cp++ = fnames[i];
721*3d8817e4Smiod 
722*3d8817e4Smiod   return cp;
723*3d8817e4Smiod }
724*3d8817e4Smiod 
725*3d8817e4Smiod /* Print out an insn with its operands, and update the info->insn_type
726*3d8817e4Smiod    fields.  The prefix_opcodep and the rest hold a prefix insn that is
727*3d8817e4Smiod    supposed to be output as an address mode.  */
728*3d8817e4Smiod 
729*3d8817e4Smiod static void
print_with_operands(const struct cris_opcode * opcodep,unsigned int insn,unsigned char * buffer,bfd_vma addr,disassemble_info * info,const struct cris_opcode * prefix_opcodep,unsigned int prefix_insn,unsigned char * prefix_buffer,bfd_boolean with_reg_prefix)730*3d8817e4Smiod print_with_operands (const struct cris_opcode *opcodep,
731*3d8817e4Smiod 		     unsigned int insn,
732*3d8817e4Smiod 		     unsigned char *buffer,
733*3d8817e4Smiod 		     bfd_vma addr,
734*3d8817e4Smiod 		     disassemble_info *info,
735*3d8817e4Smiod 		     /* If a prefix insn was before this insn (and is supposed
736*3d8817e4Smiod 			to be output as an address), here is a description of
737*3d8817e4Smiod 			it.  */
738*3d8817e4Smiod 		     const struct cris_opcode *prefix_opcodep,
739*3d8817e4Smiod 		     unsigned int prefix_insn,
740*3d8817e4Smiod 		     unsigned char *prefix_buffer,
741*3d8817e4Smiod 		     bfd_boolean with_reg_prefix)
742*3d8817e4Smiod {
743*3d8817e4Smiod   /* Get a buffer of somewhat reasonable size where we store
744*3d8817e4Smiod      intermediate parts of the insn.  */
745*3d8817e4Smiod   char temp[sizeof (".d [$r13=$r12-2147483648],$r10") * 2];
746*3d8817e4Smiod   char *tp = temp;
747*3d8817e4Smiod   static const char mode_char[] = "bwd?";
748*3d8817e4Smiod   const char *s;
749*3d8817e4Smiod   const char *cs;
750*3d8817e4Smiod   struct cris_disasm_data *disdata
751*3d8817e4Smiod     = (struct cris_disasm_data *) info->private_data;
752*3d8817e4Smiod 
753*3d8817e4Smiod   /* Print out the name first thing we do.  */
754*3d8817e4Smiod   (*info->fprintf_func) (info->stream, "%s", opcodep->name);
755*3d8817e4Smiod 
756*3d8817e4Smiod   cs = opcodep->args;
757*3d8817e4Smiod   s = cs;
758*3d8817e4Smiod 
759*3d8817e4Smiod   /* Ignore any prefix indicator.  */
760*3d8817e4Smiod   if (*s == 'p')
761*3d8817e4Smiod     s++;
762*3d8817e4Smiod 
763*3d8817e4Smiod   if (*s == 'm' || *s == 'M' || *s == 'z')
764*3d8817e4Smiod     {
765*3d8817e4Smiod       *tp++ = '.';
766*3d8817e4Smiod 
767*3d8817e4Smiod       /* Get the size-letter.  */
768*3d8817e4Smiod       *tp++ = *s == 'M'
769*3d8817e4Smiod 	? (insn & 0x8000 ? 'd'
770*3d8817e4Smiod 	   : insn & 0x4000 ? 'w' : 'b')
771*3d8817e4Smiod 	: mode_char[(insn >> 4) & (*s == 'z' ? 1 : 3)];
772*3d8817e4Smiod 
773*3d8817e4Smiod       /* Ignore the size and the space character that follows.  */
774*3d8817e4Smiod       s += 2;
775*3d8817e4Smiod     }
776*3d8817e4Smiod 
777*3d8817e4Smiod   /* Add a space if this isn't a long-branch, because for those will add
778*3d8817e4Smiod      the condition part of the name later.  */
779*3d8817e4Smiod   if (opcodep->match != (BRANCH_PC_LOW + BRANCH_INCR_HIGH * 256))
780*3d8817e4Smiod     *tp++ = ' ';
781*3d8817e4Smiod 
782*3d8817e4Smiod   /* Fill in the insn-type if deducible from the name (and there's no
783*3d8817e4Smiod      better way).  */
784*3d8817e4Smiod   if (opcodep->name[0] == 'j')
785*3d8817e4Smiod     {
786*3d8817e4Smiod       if (strncmp (opcodep->name, "jsr", 3) == 0)
787*3d8817e4Smiod 	/* It's "jsr" or "jsrc".  */
788*3d8817e4Smiod 	info->insn_type = dis_jsr;
789*3d8817e4Smiod       else
790*3d8817e4Smiod 	/* Any other jump-type insn is considered a branch.  */
791*3d8817e4Smiod 	info->insn_type = dis_branch;
792*3d8817e4Smiod     }
793*3d8817e4Smiod 
794*3d8817e4Smiod   /* We might know some more fields right now.  */
795*3d8817e4Smiod   info->branch_delay_insns = opcodep->delayed;
796*3d8817e4Smiod 
797*3d8817e4Smiod   /* Handle operands.  */
798*3d8817e4Smiod   for (; *s; s++)
799*3d8817e4Smiod     {
800*3d8817e4Smiod     switch (*s)
801*3d8817e4Smiod       {
802*3d8817e4Smiod       case 'T':
803*3d8817e4Smiod 	tp = format_sup_reg ((insn >> 12) & 15, tp, with_reg_prefix);
804*3d8817e4Smiod 	break;
805*3d8817e4Smiod 
806*3d8817e4Smiod       case 'A':
807*3d8817e4Smiod 	if (with_reg_prefix)
808*3d8817e4Smiod 	  *tp++ = REGISTER_PREFIX_CHAR;
809*3d8817e4Smiod 	*tp++ = 'a';
810*3d8817e4Smiod 	*tp++ = 'c';
811*3d8817e4Smiod 	*tp++ = 'r';
812*3d8817e4Smiod 	break;
813*3d8817e4Smiod 
814*3d8817e4Smiod       case '[':
815*3d8817e4Smiod       case ']':
816*3d8817e4Smiod       case ',':
817*3d8817e4Smiod 	*tp++ = *s;
818*3d8817e4Smiod 	break;
819*3d8817e4Smiod 
820*3d8817e4Smiod       case '!':
821*3d8817e4Smiod 	/* Ignore at this point; used at earlier stages to avoid
822*3d8817e4Smiod 	   recognition if there's a prefix at something that in other
823*3d8817e4Smiod 	   ways looks like a "pop".  */
824*3d8817e4Smiod 	break;
825*3d8817e4Smiod 
826*3d8817e4Smiod       case 'd':
827*3d8817e4Smiod 	/* Ignore.  This is an optional ".d " on the large one of
828*3d8817e4Smiod 	   relaxable insns.  */
829*3d8817e4Smiod 	break;
830*3d8817e4Smiod 
831*3d8817e4Smiod       case 'B':
832*3d8817e4Smiod 	/* This was the prefix that made this a "push".  We've already
833*3d8817e4Smiod 	   handled it by recognizing it, so signal that the prefix is
834*3d8817e4Smiod 	   handled by setting it to NULL.  */
835*3d8817e4Smiod 	prefix_opcodep = NULL;
836*3d8817e4Smiod 	break;
837*3d8817e4Smiod 
838*3d8817e4Smiod       case 'D':
839*3d8817e4Smiod       case 'r':
840*3d8817e4Smiod 	tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
841*3d8817e4Smiod 	break;
842*3d8817e4Smiod 
843*3d8817e4Smiod       case 'R':
844*3d8817e4Smiod 	tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
845*3d8817e4Smiod 	break;
846*3d8817e4Smiod 
847*3d8817e4Smiod       case 'n':
848*3d8817e4Smiod 	{
849*3d8817e4Smiod 	  /* Like N but pc-relative to the start of the insn.  */
850*3d8817e4Smiod 	  unsigned long number
851*3d8817e4Smiod 	    = (buffer[2] + buffer[3] * 256 + buffer[4] * 65536
852*3d8817e4Smiod 	       + buffer[5] * 0x1000000 + addr);
853*3d8817e4Smiod 
854*3d8817e4Smiod 	  /* Finish off and output previous formatted bytes.  */
855*3d8817e4Smiod 	  *tp = 0;
856*3d8817e4Smiod 	  if (temp[0])
857*3d8817e4Smiod 	    (*info->fprintf_func) (info->stream, "%s", temp);
858*3d8817e4Smiod 	  tp = temp;
859*3d8817e4Smiod 
860*3d8817e4Smiod 	  (*info->print_address_func) ((bfd_vma) number, info);
861*3d8817e4Smiod 	}
862*3d8817e4Smiod 	break;
863*3d8817e4Smiod 
864*3d8817e4Smiod       case 'u':
865*3d8817e4Smiod 	{
866*3d8817e4Smiod 	  /* Like n but the offset is bits <3:0> in the instruction.  */
867*3d8817e4Smiod 	  unsigned long number = (buffer[0] & 0xf) * 2 + addr;
868*3d8817e4Smiod 
869*3d8817e4Smiod 	  /* Finish off and output previous formatted bytes.  */
870*3d8817e4Smiod 	  *tp = 0;
871*3d8817e4Smiod 	  if (temp[0])
872*3d8817e4Smiod 	    (*info->fprintf_func) (info->stream, "%s", temp);
873*3d8817e4Smiod 	  tp = temp;
874*3d8817e4Smiod 
875*3d8817e4Smiod 	  (*info->print_address_func) ((bfd_vma) number, info);
876*3d8817e4Smiod 	}
877*3d8817e4Smiod 	break;
878*3d8817e4Smiod 
879*3d8817e4Smiod       case 'N':
880*3d8817e4Smiod       case 'y':
881*3d8817e4Smiod       case 'Y':
882*3d8817e4Smiod       case 'S':
883*3d8817e4Smiod       case 's':
884*3d8817e4Smiod 	/* Any "normal" memory operand.  */
885*3d8817e4Smiod 	if ((insn & 0x400) && (insn & 15) == 15 && prefix_opcodep == NULL)
886*3d8817e4Smiod 	  {
887*3d8817e4Smiod 	    /* We're looking at [pc+], i.e. we need to output an immediate
888*3d8817e4Smiod 	       number, where the size can depend on different things.  */
889*3d8817e4Smiod 	    long number;
890*3d8817e4Smiod 	    int signedp
891*3d8817e4Smiod 	      = ((*cs == 'z' && (insn & 0x20))
892*3d8817e4Smiod 		 || opcodep->match == BDAP_QUICK_OPCODE);
893*3d8817e4Smiod 	    int nbytes;
894*3d8817e4Smiod 
895*3d8817e4Smiod 	    if (opcodep->imm_oprnd_size == SIZE_FIX_32)
896*3d8817e4Smiod 	      nbytes = 4;
897*3d8817e4Smiod 	    else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG)
898*3d8817e4Smiod 	      {
899*3d8817e4Smiod 		const struct cris_spec_reg *sregp
900*3d8817e4Smiod 		  = spec_reg_info ((insn >> 12) & 15, disdata->distype);
901*3d8817e4Smiod 
902*3d8817e4Smiod 		/* A NULL return should have been as a non-match earlier,
903*3d8817e4Smiod 		   so catch it as an internal error in the error-case
904*3d8817e4Smiod 		   below.  */
905*3d8817e4Smiod 		if (sregp == NULL)
906*3d8817e4Smiod 		  /* Whatever non-valid size.  */
907*3d8817e4Smiod 		  nbytes = 42;
908*3d8817e4Smiod 		else
909*3d8817e4Smiod 		  /* PC is always incremented by a multiple of two.
910*3d8817e4Smiod 		     For CRISv32, immediates are always 4 bytes for
911*3d8817e4Smiod 		     special registers.  */
912*3d8817e4Smiod 		  nbytes = disdata->distype == cris_dis_v32
913*3d8817e4Smiod 		    ? 4 : (sregp->reg_size + 1) & ~1;
914*3d8817e4Smiod 	      }
915*3d8817e4Smiod 	    else
916*3d8817e4Smiod 	      {
917*3d8817e4Smiod 		int mode_size = 1 << ((insn >> 4) & (*cs == 'z' ? 1 : 3));
918*3d8817e4Smiod 
919*3d8817e4Smiod 		if (mode_size == 1)
920*3d8817e4Smiod 		  nbytes = 2;
921*3d8817e4Smiod 		else
922*3d8817e4Smiod 		  nbytes = mode_size;
923*3d8817e4Smiod 	      }
924*3d8817e4Smiod 
925*3d8817e4Smiod 	    switch (nbytes)
926*3d8817e4Smiod 	      {
927*3d8817e4Smiod 	      case 1:
928*3d8817e4Smiod 		number = buffer[2];
929*3d8817e4Smiod 		if (signedp && number > 127)
930*3d8817e4Smiod 		  number -= 256;
931*3d8817e4Smiod 		break;
932*3d8817e4Smiod 
933*3d8817e4Smiod 	      case 2:
934*3d8817e4Smiod 		number = buffer[2] + buffer[3] * 256;
935*3d8817e4Smiod 		if (signedp && number > 32767)
936*3d8817e4Smiod 		  number -= 65536;
937*3d8817e4Smiod 		break;
938*3d8817e4Smiod 
939*3d8817e4Smiod 	      case 4:
940*3d8817e4Smiod 		number
941*3d8817e4Smiod 		  = buffer[2] + buffer[3] * 256 + buffer[4] * 65536
942*3d8817e4Smiod 		  + buffer[5] * 0x1000000;
943*3d8817e4Smiod 		break;
944*3d8817e4Smiod 
945*3d8817e4Smiod 	      default:
946*3d8817e4Smiod 		strcpy (tp, "bug");
947*3d8817e4Smiod 		tp += 3;
948*3d8817e4Smiod 		number = 42;
949*3d8817e4Smiod 	      }
950*3d8817e4Smiod 
951*3d8817e4Smiod 	    if ((*cs == 'z' && (insn & 0x20))
952*3d8817e4Smiod 		|| (opcodep->match == BDAP_QUICK_OPCODE
953*3d8817e4Smiod 		    && (nbytes <= 2 || buffer[1 + nbytes] == 0)))
954*3d8817e4Smiod 	      tp = format_dec (number, tp, signedp);
955*3d8817e4Smiod 	    else
956*3d8817e4Smiod 	      {
957*3d8817e4Smiod 		unsigned int highbyte = (number >> 24) & 0xff;
958*3d8817e4Smiod 
959*3d8817e4Smiod 		/* Either output this as an address or as a number.  If it's
960*3d8817e4Smiod 		   a dword with the same high-byte as the address of the
961*3d8817e4Smiod 		   insn, assume it's an address, and also if it's a non-zero
962*3d8817e4Smiod 		   non-0xff high-byte.  If this is a jsr or a jump, then
963*3d8817e4Smiod 		   it's definitely an address.  */
964*3d8817e4Smiod 		if (nbytes == 4
965*3d8817e4Smiod 		    && (highbyte == ((addr >> 24) & 0xff)
966*3d8817e4Smiod 			|| (highbyte != 0 && highbyte != 0xff)
967*3d8817e4Smiod 			|| info->insn_type == dis_branch
968*3d8817e4Smiod 			|| info->insn_type == dis_jsr))
969*3d8817e4Smiod 		  {
970*3d8817e4Smiod 		    /* Finish off and output previous formatted bytes.  */
971*3d8817e4Smiod 		    *tp = 0;
972*3d8817e4Smiod 		    tp = temp;
973*3d8817e4Smiod 		    if (temp[0])
974*3d8817e4Smiod 		      (*info->fprintf_func) (info->stream, "%s", temp);
975*3d8817e4Smiod 
976*3d8817e4Smiod 		    (*info->print_address_func) ((bfd_vma) number, info);
977*3d8817e4Smiod 
978*3d8817e4Smiod 		    info->target = number;
979*3d8817e4Smiod 		  }
980*3d8817e4Smiod 		else
981*3d8817e4Smiod 		  tp = format_hex (number, tp, disdata);
982*3d8817e4Smiod 	      }
983*3d8817e4Smiod 	  }
984*3d8817e4Smiod 	else
985*3d8817e4Smiod 	  {
986*3d8817e4Smiod 	    /* Not an immediate number.  Then this is a (possibly
987*3d8817e4Smiod 	       prefixed) memory operand.  */
988*3d8817e4Smiod 	    if (info->insn_type != dis_nonbranch)
989*3d8817e4Smiod 	      {
990*3d8817e4Smiod 		int mode_size
991*3d8817e4Smiod 		  = 1 << ((insn >> 4)
992*3d8817e4Smiod 			  & (opcodep->args[0] == 'z' ? 1 : 3));
993*3d8817e4Smiod 		int size;
994*3d8817e4Smiod 		info->insn_type = dis_dref;
995*3d8817e4Smiod 		info->flags |= CRIS_DIS_FLAG_MEMREF;
996*3d8817e4Smiod 
997*3d8817e4Smiod 		if (opcodep->imm_oprnd_size == SIZE_FIX_32)
998*3d8817e4Smiod 		  size = 4;
999*3d8817e4Smiod 		else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG)
1000*3d8817e4Smiod 		  {
1001*3d8817e4Smiod 		    const struct cris_spec_reg *sregp
1002*3d8817e4Smiod 		      = spec_reg_info ((insn >> 12) & 15, disdata->distype);
1003*3d8817e4Smiod 
1004*3d8817e4Smiod 		    /* FIXME: Improve error handling; should have been caught
1005*3d8817e4Smiod 		       earlier.  */
1006*3d8817e4Smiod 		    if (sregp == NULL)
1007*3d8817e4Smiod 		      size = 4;
1008*3d8817e4Smiod 		    else
1009*3d8817e4Smiod 		      size = sregp->reg_size;
1010*3d8817e4Smiod 		  }
1011*3d8817e4Smiod 		else
1012*3d8817e4Smiod 		  size = mode_size;
1013*3d8817e4Smiod 
1014*3d8817e4Smiod 		info->data_size = size;
1015*3d8817e4Smiod 	      }
1016*3d8817e4Smiod 
1017*3d8817e4Smiod 	    *tp++ = '[';
1018*3d8817e4Smiod 
1019*3d8817e4Smiod 	    if (prefix_opcodep
1020*3d8817e4Smiod 		/* We don't match dip with a postincremented field
1021*3d8817e4Smiod 		   as a side-effect address mode.  */
1022*3d8817e4Smiod 		&& ((insn & 0x400) == 0
1023*3d8817e4Smiod 		    || prefix_opcodep->match != DIP_OPCODE))
1024*3d8817e4Smiod 	      {
1025*3d8817e4Smiod 		if (insn & 0x400)
1026*3d8817e4Smiod 		  {
1027*3d8817e4Smiod 		    tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
1028*3d8817e4Smiod 		    *tp++ = '=';
1029*3d8817e4Smiod 		  }
1030*3d8817e4Smiod 
1031*3d8817e4Smiod 
1032*3d8817e4Smiod 		/* We mainly ignore the prefix format string when the
1033*3d8817e4Smiod 		   address-mode syntax is output.  */
1034*3d8817e4Smiod 		switch (prefix_opcodep->match)
1035*3d8817e4Smiod 		  {
1036*3d8817e4Smiod 		  case DIP_OPCODE:
1037*3d8817e4Smiod 		    /* It's [r], [r+] or [pc+].  */
1038*3d8817e4Smiod 		    if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15)
1039*3d8817e4Smiod 		      {
1040*3d8817e4Smiod 			/* It's [pc+].  This cannot possibly be anything
1041*3d8817e4Smiod 			   but an address.  */
1042*3d8817e4Smiod 			unsigned long number
1043*3d8817e4Smiod 			  = prefix_buffer[2] + prefix_buffer[3] * 256
1044*3d8817e4Smiod 			  + prefix_buffer[4] * 65536
1045*3d8817e4Smiod 			  + prefix_buffer[5] * 0x1000000;
1046*3d8817e4Smiod 
1047*3d8817e4Smiod 			info->target = (bfd_vma) number;
1048*3d8817e4Smiod 
1049*3d8817e4Smiod 			/* Finish off and output previous formatted
1050*3d8817e4Smiod 			   data.  */
1051*3d8817e4Smiod 			*tp = 0;
1052*3d8817e4Smiod 			tp = temp;
1053*3d8817e4Smiod 			if (temp[0])
1054*3d8817e4Smiod 			  (*info->fprintf_func) (info->stream, "%s", temp);
1055*3d8817e4Smiod 
1056*3d8817e4Smiod 			(*info->print_address_func) ((bfd_vma) number, info);
1057*3d8817e4Smiod 		      }
1058*3d8817e4Smiod 		    else
1059*3d8817e4Smiod 		      {
1060*3d8817e4Smiod 			/* For a memref in an address, we use target2.
1061*3d8817e4Smiod 			   In this case, target is zero.  */
1062*3d8817e4Smiod 			info->flags
1063*3d8817e4Smiod 			  |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
1064*3d8817e4Smiod 			      | CRIS_DIS_FLAG_MEM_TARGET2_MEM);
1065*3d8817e4Smiod 
1066*3d8817e4Smiod 			info->target2 = prefix_insn & 15;
1067*3d8817e4Smiod 
1068*3d8817e4Smiod 			*tp++ = '[';
1069*3d8817e4Smiod 			tp = format_reg (disdata, prefix_insn & 15, tp,
1070*3d8817e4Smiod 					 with_reg_prefix);
1071*3d8817e4Smiod 			if (prefix_insn & 0x400)
1072*3d8817e4Smiod 			  *tp++ = '+';
1073*3d8817e4Smiod 			*tp++ = ']';
1074*3d8817e4Smiod 		      }
1075*3d8817e4Smiod 		    break;
1076*3d8817e4Smiod 
1077*3d8817e4Smiod 		  case BDAP_QUICK_OPCODE:
1078*3d8817e4Smiod 		    {
1079*3d8817e4Smiod 		      int number;
1080*3d8817e4Smiod 
1081*3d8817e4Smiod 		      number = prefix_buffer[0];
1082*3d8817e4Smiod 		      if (number > 127)
1083*3d8817e4Smiod 			number -= 256;
1084*3d8817e4Smiod 
1085*3d8817e4Smiod 		      /* Output "reg+num" or, if num < 0, "reg-num".  */
1086*3d8817e4Smiod 		      tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
1087*3d8817e4Smiod 				       with_reg_prefix);
1088*3d8817e4Smiod 		      if (number >= 0)
1089*3d8817e4Smiod 			*tp++ = '+';
1090*3d8817e4Smiod 		      tp = format_dec (number, tp, 1);
1091*3d8817e4Smiod 
1092*3d8817e4Smiod 		      info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
1093*3d8817e4Smiod 		      info->target = (prefix_insn >> 12) & 15;
1094*3d8817e4Smiod 		      info->target2 = (bfd_vma) number;
1095*3d8817e4Smiod 		      break;
1096*3d8817e4Smiod 		    }
1097*3d8817e4Smiod 
1098*3d8817e4Smiod 		  case BIAP_OPCODE:
1099*3d8817e4Smiod 		    /* Output "r+R.m".  */
1100*3d8817e4Smiod 		    tp = format_reg (disdata, prefix_insn & 15, tp,
1101*3d8817e4Smiod 				     with_reg_prefix);
1102*3d8817e4Smiod 		    *tp++ = '+';
1103*3d8817e4Smiod 		    tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
1104*3d8817e4Smiod 				     with_reg_prefix);
1105*3d8817e4Smiod 		    *tp++ = '.';
1106*3d8817e4Smiod 		    *tp++ = mode_char[(prefix_insn >> 4) & 3];
1107*3d8817e4Smiod 
1108*3d8817e4Smiod 		    info->flags
1109*3d8817e4Smiod 		      |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
1110*3d8817e4Smiod 			  | CRIS_DIS_FLAG_MEM_TARGET_IS_REG
1111*3d8817e4Smiod 
1112*3d8817e4Smiod 			  | ((prefix_insn & 0x8000)
1113*3d8817e4Smiod 			     ? CRIS_DIS_FLAG_MEM_TARGET2_MULT4
1114*3d8817e4Smiod 			     : ((prefix_insn & 0x8000)
1115*3d8817e4Smiod 				? CRIS_DIS_FLAG_MEM_TARGET2_MULT2 : 0)));
1116*3d8817e4Smiod 
1117*3d8817e4Smiod 		    /* Is it the casejump?  It's a "adds.w [pc+r%d.w],pc".  */
1118*3d8817e4Smiod 		    if (insn == 0xf83f && (prefix_insn & ~0xf000) == 0x55f)
1119*3d8817e4Smiod 		      /* Then start interpreting data as offsets.  */
1120*3d8817e4Smiod 		      case_offset_counter = no_of_case_offsets;
1121*3d8817e4Smiod 		    break;
1122*3d8817e4Smiod 
1123*3d8817e4Smiod 		  case BDAP_INDIR_OPCODE:
1124*3d8817e4Smiod 		    /* Output "r+s.m", or, if "s" is [pc+], "r+s" or
1125*3d8817e4Smiod 		       "r-s".  */
1126*3d8817e4Smiod 		    tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
1127*3d8817e4Smiod 				     with_reg_prefix);
1128*3d8817e4Smiod 
1129*3d8817e4Smiod 		    if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15)
1130*3d8817e4Smiod 		      {
1131*3d8817e4Smiod 			long number;
1132*3d8817e4Smiod 			unsigned int nbytes;
1133*3d8817e4Smiod 
1134*3d8817e4Smiod 			/* It's a value.  Get its size.  */
1135*3d8817e4Smiod 			int mode_size = 1 << ((prefix_insn >> 4) & 3);
1136*3d8817e4Smiod 
1137*3d8817e4Smiod 			if (mode_size == 1)
1138*3d8817e4Smiod 			  nbytes = 2;
1139*3d8817e4Smiod 			else
1140*3d8817e4Smiod 			  nbytes = mode_size;
1141*3d8817e4Smiod 
1142*3d8817e4Smiod 			switch (nbytes)
1143*3d8817e4Smiod 			  {
1144*3d8817e4Smiod 			  case 1:
1145*3d8817e4Smiod 			    number = prefix_buffer[2];
1146*3d8817e4Smiod 			    if (number > 127)
1147*3d8817e4Smiod 			      number -= 256;
1148*3d8817e4Smiod 			    break;
1149*3d8817e4Smiod 
1150*3d8817e4Smiod 			  case 2:
1151*3d8817e4Smiod 			    number = prefix_buffer[2] + prefix_buffer[3] * 256;
1152*3d8817e4Smiod 			    if (number > 32767)
1153*3d8817e4Smiod 			      number -= 65536;
1154*3d8817e4Smiod 			    break;
1155*3d8817e4Smiod 
1156*3d8817e4Smiod 			  case 4:
1157*3d8817e4Smiod 			    number
1158*3d8817e4Smiod 			      = prefix_buffer[2] + prefix_buffer[3] * 256
1159*3d8817e4Smiod 			      + prefix_buffer[4] * 65536
1160*3d8817e4Smiod 			      + prefix_buffer[5] * 0x1000000;
1161*3d8817e4Smiod 			    break;
1162*3d8817e4Smiod 
1163*3d8817e4Smiod 			  default:
1164*3d8817e4Smiod 			    strcpy (tp, "bug");
1165*3d8817e4Smiod 			    tp += 3;
1166*3d8817e4Smiod 			    number = 42;
1167*3d8817e4Smiod 			  }
1168*3d8817e4Smiod 
1169*3d8817e4Smiod 			info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
1170*3d8817e4Smiod 			info->target2 = (bfd_vma) number;
1171*3d8817e4Smiod 
1172*3d8817e4Smiod 			/* If the size is dword, then assume it's an
1173*3d8817e4Smiod 			   address.  */
1174*3d8817e4Smiod 			if (nbytes == 4)
1175*3d8817e4Smiod 			  {
1176*3d8817e4Smiod 			    /* Finish off and output previous formatted
1177*3d8817e4Smiod 			       bytes.  */
1178*3d8817e4Smiod 			    *tp++ = '+';
1179*3d8817e4Smiod 			    *tp = 0;
1180*3d8817e4Smiod 			    tp = temp;
1181*3d8817e4Smiod 			    (*info->fprintf_func) (info->stream, "%s", temp);
1182*3d8817e4Smiod 
1183*3d8817e4Smiod 			    (*info->print_address_func) ((bfd_vma) number, info);
1184*3d8817e4Smiod 			  }
1185*3d8817e4Smiod 			else
1186*3d8817e4Smiod 			  {
1187*3d8817e4Smiod 			    if (number >= 0)
1188*3d8817e4Smiod 			      *tp++ = '+';
1189*3d8817e4Smiod 			    tp = format_dec (number, tp, 1);
1190*3d8817e4Smiod 			  }
1191*3d8817e4Smiod 		      }
1192*3d8817e4Smiod 		    else
1193*3d8817e4Smiod 		      {
1194*3d8817e4Smiod 			/* Output "r+[R].m" or "r+[R+].m".  */
1195*3d8817e4Smiod 			*tp++ = '+';
1196*3d8817e4Smiod 			*tp++ = '[';
1197*3d8817e4Smiod 			tp = format_reg (disdata, prefix_insn & 15, tp,
1198*3d8817e4Smiod 					 with_reg_prefix);
1199*3d8817e4Smiod 			if (prefix_insn & 0x400)
1200*3d8817e4Smiod 			  *tp++ = '+';
1201*3d8817e4Smiod 			*tp++ = ']';
1202*3d8817e4Smiod 			*tp++ = '.';
1203*3d8817e4Smiod 			*tp++ = mode_char[(prefix_insn >> 4) & 3];
1204*3d8817e4Smiod 
1205*3d8817e4Smiod 			info->flags
1206*3d8817e4Smiod 			  |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
1207*3d8817e4Smiod 			      | CRIS_DIS_FLAG_MEM_TARGET2_MEM
1208*3d8817e4Smiod 			      | CRIS_DIS_FLAG_MEM_TARGET_IS_REG
1209*3d8817e4Smiod 
1210*3d8817e4Smiod 			      | (((prefix_insn >> 4) == 2)
1211*3d8817e4Smiod 				 ? 0
1212*3d8817e4Smiod 				 : (((prefix_insn >> 4) & 3) == 1
1213*3d8817e4Smiod 				    ? CRIS_DIS_FLAG_MEM_TARGET2_MEM_WORD
1214*3d8817e4Smiod 				    : CRIS_DIS_FLAG_MEM_TARGET2_MEM_BYTE)));
1215*3d8817e4Smiod 		      }
1216*3d8817e4Smiod 		    break;
1217*3d8817e4Smiod 
1218*3d8817e4Smiod 		  default:
1219*3d8817e4Smiod 		    (*info->fprintf_func) (info->stream, "?prefix-bug");
1220*3d8817e4Smiod 		  }
1221*3d8817e4Smiod 
1222*3d8817e4Smiod 		/* To mark that the prefix is used, reset it.  */
1223*3d8817e4Smiod 		prefix_opcodep = NULL;
1224*3d8817e4Smiod 	      }
1225*3d8817e4Smiod 	    else
1226*3d8817e4Smiod 	      {
1227*3d8817e4Smiod 		tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
1228*3d8817e4Smiod 
1229*3d8817e4Smiod 		info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
1230*3d8817e4Smiod 		info->target = insn & 15;
1231*3d8817e4Smiod 
1232*3d8817e4Smiod 		if (insn & 0x400)
1233*3d8817e4Smiod 		  *tp++ = '+';
1234*3d8817e4Smiod 	      }
1235*3d8817e4Smiod 	    *tp++ = ']';
1236*3d8817e4Smiod 	  }
1237*3d8817e4Smiod 	break;
1238*3d8817e4Smiod 
1239*3d8817e4Smiod       case 'x':
1240*3d8817e4Smiod 	tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
1241*3d8817e4Smiod 	*tp++ = '.';
1242*3d8817e4Smiod 	*tp++ = mode_char[(insn >> 4) & 3];
1243*3d8817e4Smiod 	break;
1244*3d8817e4Smiod 
1245*3d8817e4Smiod       case 'I':
1246*3d8817e4Smiod 	tp = format_dec (insn & 63, tp, 0);
1247*3d8817e4Smiod 	break;
1248*3d8817e4Smiod 
1249*3d8817e4Smiod       case 'b':
1250*3d8817e4Smiod 	{
1251*3d8817e4Smiod 	  int where = buffer[2] + buffer[3] * 256;
1252*3d8817e4Smiod 
1253*3d8817e4Smiod 	  if (where > 32767)
1254*3d8817e4Smiod 	    where -= 65536;
1255*3d8817e4Smiod 
1256*3d8817e4Smiod 	  where += addr + ((disdata->distype == cris_dis_v32) ? 0 : 4);
1257*3d8817e4Smiod 
1258*3d8817e4Smiod 	  if (insn == BA_PC_INCR_OPCODE)
1259*3d8817e4Smiod 	    info->insn_type = dis_branch;
1260*3d8817e4Smiod 	  else
1261*3d8817e4Smiod 	    info->insn_type = dis_condbranch;
1262*3d8817e4Smiod 
1263*3d8817e4Smiod 	  info->target = (bfd_vma) where;
1264*3d8817e4Smiod 
1265*3d8817e4Smiod 	  *tp = 0;
1266*3d8817e4Smiod 	  tp = temp;
1267*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%s%s ",
1268*3d8817e4Smiod 				 temp, cris_cc_strings[insn >> 12]);
1269*3d8817e4Smiod 
1270*3d8817e4Smiod 	  (*info->print_address_func) ((bfd_vma) where, info);
1271*3d8817e4Smiod 	}
1272*3d8817e4Smiod       break;
1273*3d8817e4Smiod 
1274*3d8817e4Smiod     case 'c':
1275*3d8817e4Smiod       tp = format_dec (insn & 31, tp, 0);
1276*3d8817e4Smiod       break;
1277*3d8817e4Smiod 
1278*3d8817e4Smiod     case 'C':
1279*3d8817e4Smiod       tp = format_dec (insn & 15, tp, 0);
1280*3d8817e4Smiod       break;
1281*3d8817e4Smiod 
1282*3d8817e4Smiod     case 'o':
1283*3d8817e4Smiod       {
1284*3d8817e4Smiod 	long offset = insn & 0xfe;
1285*3d8817e4Smiod 	bfd_vma target;
1286*3d8817e4Smiod 
1287*3d8817e4Smiod 	if (insn & 1)
1288*3d8817e4Smiod 	  offset |= ~0xff;
1289*3d8817e4Smiod 
1290*3d8817e4Smiod 	if (opcodep->match == BA_QUICK_OPCODE)
1291*3d8817e4Smiod 	  info->insn_type = dis_branch;
1292*3d8817e4Smiod 	else
1293*3d8817e4Smiod 	  info->insn_type = dis_condbranch;
1294*3d8817e4Smiod 
1295*3d8817e4Smiod 	target = addr + ((disdata->distype == cris_dis_v32) ? 0 : 2) + offset;
1296*3d8817e4Smiod 	info->target = target;
1297*3d8817e4Smiod 	*tp = 0;
1298*3d8817e4Smiod 	tp = temp;
1299*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "%s", temp);
1300*3d8817e4Smiod 	(*info->print_address_func) (target, info);
1301*3d8817e4Smiod       }
1302*3d8817e4Smiod       break;
1303*3d8817e4Smiod 
1304*3d8817e4Smiod     case 'Q':
1305*3d8817e4Smiod     case 'O':
1306*3d8817e4Smiod       {
1307*3d8817e4Smiod 	long number = buffer[0];
1308*3d8817e4Smiod 
1309*3d8817e4Smiod 	if (number > 127)
1310*3d8817e4Smiod 	  number = number - 256;
1311*3d8817e4Smiod 
1312*3d8817e4Smiod 	tp = format_dec (number, tp, 1);
1313*3d8817e4Smiod 	*tp++ = ',';
1314*3d8817e4Smiod 	tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
1315*3d8817e4Smiod       }
1316*3d8817e4Smiod       break;
1317*3d8817e4Smiod 
1318*3d8817e4Smiod     case 'f':
1319*3d8817e4Smiod       tp = print_flags (disdata, insn, tp);
1320*3d8817e4Smiod       break;
1321*3d8817e4Smiod 
1322*3d8817e4Smiod     case 'i':
1323*3d8817e4Smiod       tp = format_dec ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1);
1324*3d8817e4Smiod       break;
1325*3d8817e4Smiod 
1326*3d8817e4Smiod     case 'P':
1327*3d8817e4Smiod       {
1328*3d8817e4Smiod 	const struct cris_spec_reg *sregp
1329*3d8817e4Smiod 	  = spec_reg_info ((insn >> 12) & 15, disdata->distype);
1330*3d8817e4Smiod 
1331*3d8817e4Smiod 	if (sregp->name == NULL)
1332*3d8817e4Smiod 	  /* Should have been caught as a non-match eariler.  */
1333*3d8817e4Smiod 	  *tp++ = '?';
1334*3d8817e4Smiod 	else
1335*3d8817e4Smiod 	  {
1336*3d8817e4Smiod 	    if (with_reg_prefix)
1337*3d8817e4Smiod 	      *tp++ = REGISTER_PREFIX_CHAR;
1338*3d8817e4Smiod 	    strcpy (tp, sregp->name);
1339*3d8817e4Smiod 	    tp += strlen (tp);
1340*3d8817e4Smiod 	  }
1341*3d8817e4Smiod       }
1342*3d8817e4Smiod       break;
1343*3d8817e4Smiod 
1344*3d8817e4Smiod     default:
1345*3d8817e4Smiod       strcpy (tp, "???");
1346*3d8817e4Smiod       tp += 3;
1347*3d8817e4Smiod     }
1348*3d8817e4Smiod   }
1349*3d8817e4Smiod 
1350*3d8817e4Smiod   *tp = 0;
1351*3d8817e4Smiod 
1352*3d8817e4Smiod   if (prefix_opcodep)
1353*3d8817e4Smiod     (*info->fprintf_func) (info->stream, " (OOPS unused prefix \"%s: %s\")",
1354*3d8817e4Smiod 			   prefix_opcodep->name, prefix_opcodep->args);
1355*3d8817e4Smiod 
1356*3d8817e4Smiod   (*info->fprintf_func) (info->stream, "%s", temp);
1357*3d8817e4Smiod 
1358*3d8817e4Smiod   /* Get info for matching case-tables, if we don't have any active.
1359*3d8817e4Smiod      We assume that the last constant seen is used; either in the insn
1360*3d8817e4Smiod      itself or in a "move.d const,rN, sub.d rN,rM"-like sequence.  */
1361*3d8817e4Smiod   if (TRACE_CASE && case_offset_counter == 0)
1362*3d8817e4Smiod     {
1363*3d8817e4Smiod       if (strncmp (opcodep->name, "sub", 3) == 0)
1364*3d8817e4Smiod 	case_offset = last_immediate;
1365*3d8817e4Smiod 
1366*3d8817e4Smiod       /* It could also be an "add", if there are negative case-values.  */
1367*3d8817e4Smiod       else if (strncmp (opcodep->name, "add", 3) == 0)
1368*3d8817e4Smiod 	/* The first case is the negated operand to the add.  */
1369*3d8817e4Smiod 	case_offset = -last_immediate;
1370*3d8817e4Smiod 
1371*3d8817e4Smiod       /* A bound insn will tell us the number of cases.  */
1372*3d8817e4Smiod       else if (strncmp (opcodep->name, "bound", 5) == 0)
1373*3d8817e4Smiod 	no_of_case_offsets = last_immediate + 1;
1374*3d8817e4Smiod 
1375*3d8817e4Smiod       /* A jump or jsr or branch breaks the chain of insns for a
1376*3d8817e4Smiod 	 case-table, so assume default first-case again.  */
1377*3d8817e4Smiod       else if (info->insn_type == dis_jsr
1378*3d8817e4Smiod 	       || info->insn_type == dis_branch
1379*3d8817e4Smiod 	       || info->insn_type == dis_condbranch)
1380*3d8817e4Smiod 	case_offset = 0;
1381*3d8817e4Smiod     }
1382*3d8817e4Smiod }
1383*3d8817e4Smiod 
1384*3d8817e4Smiod 
1385*3d8817e4Smiod /* Print the CRIS instruction at address memaddr on stream.  Returns
1386*3d8817e4Smiod    length of the instruction, in bytes.  Prefix register names with `$' if
1387*3d8817e4Smiod    WITH_REG_PREFIX.  */
1388*3d8817e4Smiod 
1389*3d8817e4Smiod static int
print_insn_cris_generic(bfd_vma memaddr,disassemble_info * info,bfd_boolean with_reg_prefix)1390*3d8817e4Smiod print_insn_cris_generic (bfd_vma memaddr,
1391*3d8817e4Smiod 			 disassemble_info *info,
1392*3d8817e4Smiod 			 bfd_boolean with_reg_prefix)
1393*3d8817e4Smiod {
1394*3d8817e4Smiod   int nbytes;
1395*3d8817e4Smiod   unsigned int insn;
1396*3d8817e4Smiod   const struct cris_opcode *matchedp;
1397*3d8817e4Smiod   int advance = 0;
1398*3d8817e4Smiod   struct cris_disasm_data *disdata
1399*3d8817e4Smiod     = (struct cris_disasm_data *) info->private_data;
1400*3d8817e4Smiod 
1401*3d8817e4Smiod   /* No instruction will be disassembled as longer than this number of
1402*3d8817e4Smiod      bytes; stacked prefixes will not be expanded.  */
1403*3d8817e4Smiod   unsigned char buffer[MAX_BYTES_PER_CRIS_INSN];
1404*3d8817e4Smiod   unsigned char *bufp;
1405*3d8817e4Smiod   int status = 0;
1406*3d8817e4Smiod   bfd_vma addr;
1407*3d8817e4Smiod 
1408*3d8817e4Smiod   /* There will be an "out of range" error after the last instruction.
1409*3d8817e4Smiod      Reading pairs of bytes in decreasing number, we hope that we will get
1410*3d8817e4Smiod      at least the amount that we will consume.
1411*3d8817e4Smiod 
1412*3d8817e4Smiod      If we can't get any data, or we do not get enough data, we print
1413*3d8817e4Smiod      the error message.  */
1414*3d8817e4Smiod 
1415*3d8817e4Smiod   for (nbytes = MAX_BYTES_PER_CRIS_INSN; nbytes > 0; nbytes -= 2)
1416*3d8817e4Smiod     {
1417*3d8817e4Smiod       status = (*info->read_memory_func) (memaddr, buffer, nbytes, info);
1418*3d8817e4Smiod       if (status == 0)
1419*3d8817e4Smiod 	break;
1420*3d8817e4Smiod     }
1421*3d8817e4Smiod 
1422*3d8817e4Smiod   /* If we did not get all we asked for, then clear the rest.
1423*3d8817e4Smiod      Hopefully this makes a reproducible result in case of errors.  */
1424*3d8817e4Smiod   if (nbytes != MAX_BYTES_PER_CRIS_INSN)
1425*3d8817e4Smiod     memset (buffer + nbytes, 0, MAX_BYTES_PER_CRIS_INSN - nbytes);
1426*3d8817e4Smiod 
1427*3d8817e4Smiod   addr = memaddr;
1428*3d8817e4Smiod   bufp = buffer;
1429*3d8817e4Smiod 
1430*3d8817e4Smiod   /* Set some defaults for the insn info.  */
1431*3d8817e4Smiod   info->insn_info_valid = 1;
1432*3d8817e4Smiod   info->branch_delay_insns = 0;
1433*3d8817e4Smiod   info->data_size = 0;
1434*3d8817e4Smiod   info->insn_type = dis_nonbranch;
1435*3d8817e4Smiod   info->flags = 0;
1436*3d8817e4Smiod   info->target = 0;
1437*3d8817e4Smiod   info->target2 = 0;
1438*3d8817e4Smiod 
1439*3d8817e4Smiod   /* If we got any data, disassemble it.  */
1440*3d8817e4Smiod   if (nbytes != 0)
1441*3d8817e4Smiod     {
1442*3d8817e4Smiod       matchedp = NULL;
1443*3d8817e4Smiod 
1444*3d8817e4Smiod       insn = bufp[0] + bufp[1] * 256;
1445*3d8817e4Smiod 
1446*3d8817e4Smiod       /* If we're in a case-table, don't disassemble the offsets.  */
1447*3d8817e4Smiod       if (TRACE_CASE && case_offset_counter != 0)
1448*3d8817e4Smiod 	{
1449*3d8817e4Smiod 	  info->insn_type = dis_noninsn;
1450*3d8817e4Smiod 	  advance += 2;
1451*3d8817e4Smiod 
1452*3d8817e4Smiod 	  /* If to print data as offsets, then shortcut here.  */
1453*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "case %ld%s: -> ",
1454*3d8817e4Smiod 				 case_offset + no_of_case_offsets
1455*3d8817e4Smiod 				 - case_offset_counter,
1456*3d8817e4Smiod 				 case_offset_counter == 1 ? "/default" :
1457*3d8817e4Smiod 				 "");
1458*3d8817e4Smiod 
1459*3d8817e4Smiod 	  (*info->print_address_func) ((bfd_vma)
1460*3d8817e4Smiod 				       ((short) (insn)
1461*3d8817e4Smiod 					+ (long) (addr
1462*3d8817e4Smiod 						  - (no_of_case_offsets
1463*3d8817e4Smiod 						     - case_offset_counter)
1464*3d8817e4Smiod 						  * 2)), info);
1465*3d8817e4Smiod 	  case_offset_counter--;
1466*3d8817e4Smiod 
1467*3d8817e4Smiod 	  /* The default case start (without a "sub" or "add") must be
1468*3d8817e4Smiod 	     zero.  */
1469*3d8817e4Smiod 	  if (case_offset_counter == 0)
1470*3d8817e4Smiod 	    case_offset = 0;
1471*3d8817e4Smiod 	}
1472*3d8817e4Smiod       else if (insn == 0)
1473*3d8817e4Smiod 	{
1474*3d8817e4Smiod 	  /* We're often called to disassemble zeroes.  While this is a
1475*3d8817e4Smiod 	     valid "bcc .+2" insn, it is also useless enough and enough
1476*3d8817e4Smiod 	     of a nuiscance that we will just output "bcc .+2" for it
1477*3d8817e4Smiod 	     and signal it as a noninsn.  */
1478*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream,
1479*3d8817e4Smiod 				 disdata->distype == cris_dis_v32
1480*3d8817e4Smiod 				 ? "bcc ." : "bcc .+2");
1481*3d8817e4Smiod 	  info->insn_type = dis_noninsn;
1482*3d8817e4Smiod 	  advance += 2;
1483*3d8817e4Smiod 	}
1484*3d8817e4Smiod       else
1485*3d8817e4Smiod 	{
1486*3d8817e4Smiod 	  const struct cris_opcode *prefix_opcodep = NULL;
1487*3d8817e4Smiod 	  unsigned char *prefix_buffer = bufp;
1488*3d8817e4Smiod 	  unsigned int prefix_insn = insn;
1489*3d8817e4Smiod 	  int prefix_size = 0;
1490*3d8817e4Smiod 
1491*3d8817e4Smiod 	  matchedp = get_opcode_entry (insn, NO_CRIS_PREFIX, disdata);
1492*3d8817e4Smiod 
1493*3d8817e4Smiod 	  /* Check if we're supposed to write out prefixes as address
1494*3d8817e4Smiod 	     modes and if this was a prefix.  */
1495*3d8817e4Smiod 	  if (matchedp != NULL && PARSE_PREFIX && matchedp->args[0] == 'p')
1496*3d8817e4Smiod 	    {
1497*3d8817e4Smiod 	      /* If it's a prefix, put it into the prefix vars and get the
1498*3d8817e4Smiod 		 main insn.  */
1499*3d8817e4Smiod 	      prefix_size = bytes_to_skip (prefix_insn, matchedp,
1500*3d8817e4Smiod 					   disdata->distype, NULL);
1501*3d8817e4Smiod 	      prefix_opcodep = matchedp;
1502*3d8817e4Smiod 
1503*3d8817e4Smiod 	      insn = bufp[prefix_size] + bufp[prefix_size + 1] * 256;
1504*3d8817e4Smiod 	      matchedp = get_opcode_entry (insn, prefix_insn, disdata);
1505*3d8817e4Smiod 
1506*3d8817e4Smiod 	      if (matchedp != NULL)
1507*3d8817e4Smiod 		{
1508*3d8817e4Smiod 		  addr += prefix_size;
1509*3d8817e4Smiod 		  bufp += prefix_size;
1510*3d8817e4Smiod 		  advance += prefix_size;
1511*3d8817e4Smiod 		}
1512*3d8817e4Smiod 	      else
1513*3d8817e4Smiod 		{
1514*3d8817e4Smiod 		  /* The "main" insn wasn't valid, at least not when
1515*3d8817e4Smiod 		     prefixed.  Put back things enough to output the
1516*3d8817e4Smiod 		     prefix insn only, as a normal insn.  */
1517*3d8817e4Smiod 		  matchedp = prefix_opcodep;
1518*3d8817e4Smiod 		  insn = prefix_insn;
1519*3d8817e4Smiod 		  prefix_opcodep = NULL;
1520*3d8817e4Smiod 		}
1521*3d8817e4Smiod 	    }
1522*3d8817e4Smiod 
1523*3d8817e4Smiod 	  if (matchedp == NULL)
1524*3d8817e4Smiod 	    {
1525*3d8817e4Smiod 	      (*info->fprintf_func) (info->stream, "??0x%x", insn);
1526*3d8817e4Smiod 	      advance += 2;
1527*3d8817e4Smiod 
1528*3d8817e4Smiod 	      info->insn_type = dis_noninsn;
1529*3d8817e4Smiod 	    }
1530*3d8817e4Smiod 	  else
1531*3d8817e4Smiod 	    {
1532*3d8817e4Smiod 	      advance
1533*3d8817e4Smiod 		+= bytes_to_skip (insn, matchedp, disdata->distype,
1534*3d8817e4Smiod 				  prefix_opcodep);
1535*3d8817e4Smiod 
1536*3d8817e4Smiod 	      /* The info_type and assorted fields will be set according
1537*3d8817e4Smiod 		 to the operands.   */
1538*3d8817e4Smiod 	      print_with_operands (matchedp, insn, bufp, addr, info,
1539*3d8817e4Smiod 				   prefix_opcodep, prefix_insn,
1540*3d8817e4Smiod 				   prefix_buffer, with_reg_prefix);
1541*3d8817e4Smiod 	    }
1542*3d8817e4Smiod 	}
1543*3d8817e4Smiod     }
1544*3d8817e4Smiod   else
1545*3d8817e4Smiod     info->insn_type = dis_noninsn;
1546*3d8817e4Smiod 
1547*3d8817e4Smiod   /* If we read less than MAX_BYTES_PER_CRIS_INSN, i.e. we got an error
1548*3d8817e4Smiod      status when reading that much, and the insn decoding indicated a
1549*3d8817e4Smiod      length exceeding what we read, there is an error.  */
1550*3d8817e4Smiod   if (status != 0 && (nbytes == 0 || advance > nbytes))
1551*3d8817e4Smiod     {
1552*3d8817e4Smiod       (*info->memory_error_func) (status, memaddr, info);
1553*3d8817e4Smiod       return -1;
1554*3d8817e4Smiod     }
1555*3d8817e4Smiod 
1556*3d8817e4Smiod   /* Max supported insn size with one folded prefix insn.  */
1557*3d8817e4Smiod   info->bytes_per_line = MAX_BYTES_PER_CRIS_INSN;
1558*3d8817e4Smiod 
1559*3d8817e4Smiod   /* I would like to set this to a fixed value larger than the actual
1560*3d8817e4Smiod      number of bytes to print in order to avoid spaces between bytes,
1561*3d8817e4Smiod      but objdump.c (2.9.1) does not like that, so we print 16-bit
1562*3d8817e4Smiod      chunks, which is the next choice.  */
1563*3d8817e4Smiod   info->bytes_per_chunk = 2;
1564*3d8817e4Smiod 
1565*3d8817e4Smiod   /* Printing bytes in order of increasing addresses makes sense,
1566*3d8817e4Smiod      especially on a little-endian target.
1567*3d8817e4Smiod      This is completely the opposite of what you think; setting this to
1568*3d8817e4Smiod      BFD_ENDIAN_LITTLE will print bytes in order N..0 rather than the 0..N
1569*3d8817e4Smiod      we want.  */
1570*3d8817e4Smiod   info->display_endian = BFD_ENDIAN_BIG;
1571*3d8817e4Smiod 
1572*3d8817e4Smiod   return advance;
1573*3d8817e4Smiod }
1574*3d8817e4Smiod 
1575*3d8817e4Smiod /* Disassemble, prefixing register names with `$'.  CRIS v0..v10.  */
1576*3d8817e4Smiod 
1577*3d8817e4Smiod static int
print_insn_cris_with_register_prefix(bfd_vma vma,disassemble_info * info)1578*3d8817e4Smiod print_insn_cris_with_register_prefix (bfd_vma vma,
1579*3d8817e4Smiod 				      disassemble_info *info)
1580*3d8817e4Smiod {
1581*3d8817e4Smiod   if (info->private_data == NULL
1582*3d8817e4Smiod       && !cris_parse_disassembler_options (info, cris_dis_v0_v10))
1583*3d8817e4Smiod     return -1;
1584*3d8817e4Smiod   return print_insn_cris_generic (vma, info, TRUE);
1585*3d8817e4Smiod }
1586*3d8817e4Smiod 
1587*3d8817e4Smiod /* Disassemble, prefixing register names with `$'.  CRIS v32.  */
1588*3d8817e4Smiod 
1589*3d8817e4Smiod static int
print_insn_crisv32_with_register_prefix(bfd_vma vma,disassemble_info * info)1590*3d8817e4Smiod print_insn_crisv32_with_register_prefix (bfd_vma vma,
1591*3d8817e4Smiod 					 disassemble_info *info)
1592*3d8817e4Smiod {
1593*3d8817e4Smiod   if (info->private_data == NULL
1594*3d8817e4Smiod       && !cris_parse_disassembler_options (info, cris_dis_v32))
1595*3d8817e4Smiod     return -1;
1596*3d8817e4Smiod   return print_insn_cris_generic (vma, info, TRUE);
1597*3d8817e4Smiod }
1598*3d8817e4Smiod 
1599*3d8817e4Smiod /* Disassemble, prefixing register names with `$'.
1600*3d8817e4Smiod    Common v10 and v32 subset.  */
1601*3d8817e4Smiod 
1602*3d8817e4Smiod static int
print_insn_crisv10_v32_with_register_prefix(bfd_vma vma,disassemble_info * info)1603*3d8817e4Smiod print_insn_crisv10_v32_with_register_prefix (bfd_vma vma,
1604*3d8817e4Smiod 					     disassemble_info *info)
1605*3d8817e4Smiod {
1606*3d8817e4Smiod   if (info->private_data == NULL
1607*3d8817e4Smiod       && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
1608*3d8817e4Smiod     return -1;
1609*3d8817e4Smiod   return print_insn_cris_generic (vma, info, TRUE);
1610*3d8817e4Smiod }
1611*3d8817e4Smiod 
1612*3d8817e4Smiod /* Disassemble, no prefixes on register names.  CRIS v0..v10.  */
1613*3d8817e4Smiod 
1614*3d8817e4Smiod static int
print_insn_cris_without_register_prefix(bfd_vma vma,disassemble_info * info)1615*3d8817e4Smiod print_insn_cris_without_register_prefix (bfd_vma vma,
1616*3d8817e4Smiod 					 disassemble_info *info)
1617*3d8817e4Smiod {
1618*3d8817e4Smiod   if (info->private_data == NULL
1619*3d8817e4Smiod       && !cris_parse_disassembler_options (info, cris_dis_v0_v10))
1620*3d8817e4Smiod     return -1;
1621*3d8817e4Smiod   return print_insn_cris_generic (vma, info, FALSE);
1622*3d8817e4Smiod }
1623*3d8817e4Smiod 
1624*3d8817e4Smiod /* Disassemble, no prefixes on register names.  CRIS v32.  */
1625*3d8817e4Smiod 
1626*3d8817e4Smiod static int
print_insn_crisv32_without_register_prefix(bfd_vma vma,disassemble_info * info)1627*3d8817e4Smiod print_insn_crisv32_without_register_prefix (bfd_vma vma,
1628*3d8817e4Smiod 					    disassemble_info *info)
1629*3d8817e4Smiod {
1630*3d8817e4Smiod   if (info->private_data == NULL
1631*3d8817e4Smiod       && !cris_parse_disassembler_options (info, cris_dis_v32))
1632*3d8817e4Smiod     return -1;
1633*3d8817e4Smiod   return print_insn_cris_generic (vma, info, FALSE);
1634*3d8817e4Smiod }
1635*3d8817e4Smiod 
1636*3d8817e4Smiod /* Disassemble, no prefixes on register names.
1637*3d8817e4Smiod    Common v10 and v32 subset.  */
1638*3d8817e4Smiod 
1639*3d8817e4Smiod static int
print_insn_crisv10_v32_without_register_prefix(bfd_vma vma,disassemble_info * info)1640*3d8817e4Smiod print_insn_crisv10_v32_without_register_prefix (bfd_vma vma,
1641*3d8817e4Smiod 						disassemble_info *info)
1642*3d8817e4Smiod {
1643*3d8817e4Smiod   if (info->private_data == NULL
1644*3d8817e4Smiod       && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
1645*3d8817e4Smiod     return -1;
1646*3d8817e4Smiod   return print_insn_cris_generic (vma, info, FALSE);
1647*3d8817e4Smiod }
1648*3d8817e4Smiod 
1649*3d8817e4Smiod /* Return a disassembler-function that prints registers with a `$' prefix,
1650*3d8817e4Smiod    or one that prints registers without a prefix.
1651*3d8817e4Smiod    FIXME: We should improve the solution to avoid the multitude of
1652*3d8817e4Smiod    functions seen above.  */
1653*3d8817e4Smiod 
1654*3d8817e4Smiod disassembler_ftype
cris_get_disassembler(bfd * abfd)1655*3d8817e4Smiod cris_get_disassembler (bfd *abfd)
1656*3d8817e4Smiod {
1657*3d8817e4Smiod   /* If there's no bfd in sight, we return what is valid as input in all
1658*3d8817e4Smiod      contexts if fed back to the assembler: disassembly *with* register
1659*3d8817e4Smiod      prefix.  Unfortunately this will be totally wrong for v32.  */
1660*3d8817e4Smiod   if (abfd == NULL)
1661*3d8817e4Smiod     return print_insn_cris_with_register_prefix;
1662*3d8817e4Smiod 
1663*3d8817e4Smiod   if (bfd_get_symbol_leading_char (abfd) == 0)
1664*3d8817e4Smiod     {
1665*3d8817e4Smiod       if (bfd_get_mach (abfd) == bfd_mach_cris_v32)
1666*3d8817e4Smiod 	return print_insn_crisv32_with_register_prefix;
1667*3d8817e4Smiod       if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32)
1668*3d8817e4Smiod 	return print_insn_crisv10_v32_with_register_prefix;
1669*3d8817e4Smiod 
1670*3d8817e4Smiod       /* We default to v10.  This may be specifically specified in the
1671*3d8817e4Smiod 	 bfd mach, but is also the default setting.  */
1672*3d8817e4Smiod       return print_insn_cris_with_register_prefix;
1673*3d8817e4Smiod     }
1674*3d8817e4Smiod 
1675*3d8817e4Smiod   if (bfd_get_mach (abfd) == bfd_mach_cris_v32)
1676*3d8817e4Smiod     return print_insn_crisv32_without_register_prefix;
1677*3d8817e4Smiod   if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32)
1678*3d8817e4Smiod     return print_insn_crisv10_v32_without_register_prefix;
1679*3d8817e4Smiod   return print_insn_cris_without_register_prefix;
1680*3d8817e4Smiod }
1681*3d8817e4Smiod 
1682*3d8817e4Smiod /* Local variables:
1683*3d8817e4Smiod    eval: (c-set-style "gnu")
1684*3d8817e4Smiod    indent-tabs-mode: t
1685*3d8817e4Smiod    End:  */
1686