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