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