/src/binutils-gdb/opcodes/cris-dis.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Disassembler code for CRIS. |
2 | | Copyright (C) 2000-2025 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.03M | #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 | 598k | #define PARSE_PREFIX 1 |
39 | | #endif |
40 | | |
41 | | /* Sometimes we prefix all registers with this character. */ |
42 | 410k | #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.29M | #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 | 684 | { |
106 | 684 | struct cris_disasm_data *disdata; |
107 | | |
108 | 684 | info->private_data = calloc (1, sizeof (struct cris_disasm_data)); |
109 | 684 | disdata = (struct cris_disasm_data *) info->private_data; |
110 | 684 | if (disdata == NULL) |
111 | 0 | return false; |
112 | | |
113 | | /* Default true. */ |
114 | 684 | disdata->trace_case |
115 | 684 | = (info->disassembler_options == NULL |
116 | 684 | || (strcmp (info->disassembler_options, "nocase") != 0)); |
117 | | |
118 | 684 | disdata->distype = distype; |
119 | 684 | return true; |
120 | 684 | } |
121 | | |
122 | | static const struct cris_spec_reg * |
123 | | spec_reg_info (unsigned int sreg, enum cris_disass_family distype) |
124 | 12.5k | { |
125 | 12.5k | int i; |
126 | | |
127 | 203k | for (i = 0; cris_spec_regs[i].name != NULL; i++) |
128 | 203k | { |
129 | 203k | if (cris_spec_regs[i].number == sreg) |
130 | 27.4k | { |
131 | 27.4k | 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 | 27.4k | else if (cris_spec_regs[i].applicable_version != cris_ver_v32p) |
147 | 12.5k | return &cris_spec_regs[i]; |
148 | 27.4k | } |
149 | 203k | } |
150 | | |
151 | 0 | return NULL; |
152 | 12.5k | } |
153 | | |
154 | | /* Return the number of bits in the argument. */ |
155 | | |
156 | | static int |
157 | | number_of_bits (unsigned int val) |
158 | 17.6k | { |
159 | 17.6k | int bits; |
160 | | |
161 | 127k | for (bits = 0; val != 0; val &= val - 1) |
162 | 109k | bits++; |
163 | | |
164 | 17.6k | return bits; |
165 | 17.6k | } |
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 | 346k | { |
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 | 346k | static const struct cris_opcode **opc_table = NULL; |
177 | | |
178 | 346k | const struct cris_opcode *max_matchedp = NULL; |
179 | 346k | const struct cris_opcode **prefix_opc_table = NULL; |
180 | | |
181 | | /* We hold a table for each prefix that need to be handled differently. */ |
182 | 346k | static const struct cris_opcode **dip_prefixes = NULL; |
183 | 346k | static const struct cris_opcode **bdapq_m1_prefixes = NULL; |
184 | 346k | static const struct cris_opcode **bdapq_m2_prefixes = NULL; |
185 | 346k | static const struct cris_opcode **bdapq_m4_prefixes = NULL; |
186 | 346k | static const struct cris_opcode **rest_prefixes = NULL; |
187 | | |
188 | | /* Allocate and clear the opcode-table. */ |
189 | 346k | 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 | 346k | if (prefix_insn != NO_CRIS_PREFIX) |
240 | 37.9k | { |
241 | 37.9k | const struct cris_opcode *popcodep |
242 | 37.9k | = (opc_table[prefix_insn] != NULL |
243 | 37.9k | ? opc_table[prefix_insn] |
244 | 37.9k | : get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata)); |
245 | | |
246 | 37.9k | if (popcodep == NULL) |
247 | 0 | return NULL; |
248 | | |
249 | 37.9k | if (popcodep->match == BDAP_QUICK_OPCODE) |
250 | 24.5k | { |
251 | | /* Since some offsets are recognized with "push" macros, we |
252 | | have to have different tables for them. */ |
253 | 24.5k | int offset = (prefix_insn & 255); |
254 | | |
255 | 24.5k | if (offset > 127) |
256 | 9.74k | offset -= 256; |
257 | | |
258 | 24.5k | switch (offset) |
259 | 24.5k | { |
260 | 167 | case -4: |
261 | 167 | prefix_opc_table = bdapq_m4_prefixes; |
262 | 167 | break; |
263 | | |
264 | 67 | case -2: |
265 | 67 | prefix_opc_table = bdapq_m2_prefixes; |
266 | 67 | break; |
267 | | |
268 | 1.12k | case -1: |
269 | 1.12k | prefix_opc_table = bdapq_m1_prefixes; |
270 | 1.12k | break; |
271 | | |
272 | 23.1k | default: |
273 | 23.1k | prefix_opc_table = rest_prefixes; |
274 | 23.1k | break; |
275 | 24.5k | } |
276 | 24.5k | } |
277 | 13.3k | 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 | 891 | prefix_opc_table = dip_prefixes; |
281 | 12.4k | else |
282 | 12.4k | prefix_opc_table = rest_prefixes; |
283 | 37.9k | } |
284 | | |
285 | 346k | if (prefix_insn != NO_CRIS_PREFIX |
286 | 346k | && prefix_opc_table[insn] != NULL) |
287 | 12.3k | max_matchedp = prefix_opc_table[insn]; |
288 | 334k | else if (prefix_insn == NO_CRIS_PREFIX && opc_table[insn] != NULL) |
289 | 275k | max_matchedp = opc_table[insn]; |
290 | 58.6k | else |
291 | 58.6k | { |
292 | 58.6k | const struct cris_opcode *opcodep; |
293 | 58.6k | int max_level_of_match = -1; |
294 | | |
295 | 58.6k | for (opcodep = cris_opcodes; |
296 | 14.1M | opcodep->name != NULL; |
297 | 14.0M | opcodep++) |
298 | 14.0M | { |
299 | 14.0M | int level_of_match; |
300 | | |
301 | 14.0M | 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 | 14.0M | else |
330 | 14.0M | { |
331 | 14.0M | switch (opcodep->applicable_version) |
332 | 14.0M | { |
333 | 5.92M | case cris_ver_version_all: |
334 | 6.04M | case cris_ver_v0_3: |
335 | 6.16M | case cris_ver_v3p: |
336 | 9.09M | case cris_ver_v0_10: |
337 | 9.97M | case cris_ver_v8p: |
338 | 10.6M | case cris_ver_v8_10: |
339 | 11.1M | case cris_ver_v10: |
340 | 11.3M | case cris_ver_sim_v0_10: |
341 | 11.4M | case cris_ver_v10p: |
342 | 11.6M | case cris_ver_warning: |
343 | 11.6M | break; |
344 | | |
345 | 2.46M | case cris_ver_v32p: |
346 | 2.46M | continue; |
347 | | |
348 | 0 | case cris_ver_v8: |
349 | 0 | abort (); |
350 | 0 | default: |
351 | 0 | abort (); |
352 | 14.0M | } |
353 | 14.0M | } |
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 | 11.6M | if ((opcodep->match & insn) == opcodep->match |
362 | 11.6M | && (opcodep->lose & insn) == 0 |
363 | 11.6M | && ((level_of_match |
364 | 79.5k | = cris_constraint (opcodep->args, |
365 | 79.5k | insn, |
366 | 79.5k | prefix_insn, |
367 | 79.5k | disdata)) |
368 | 79.5k | >= 0) |
369 | 11.6M | && ((level_of_match |
370 | 17.6k | += 2 * number_of_bits (opcodep->match |
371 | 17.6k | | opcodep->lose)) |
372 | 17.6k | > max_level_of_match)) |
373 | 17.0k | { |
374 | 17.0k | max_matchedp = opcodep; |
375 | 17.0k | max_level_of_match = level_of_match; |
376 | | |
377 | | /* If there was a full match, never mind looking |
378 | | further. */ |
379 | 17.0k | if (level_of_match >= 2 * 16) |
380 | 3 | break; |
381 | 17.0k | } |
382 | 11.6M | } |
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 | 58.6k | if (prefix_insn == NO_CRIS_PREFIX) |
391 | 33.1k | opc_table[insn] = max_matchedp; |
392 | 25.5k | else |
393 | 25.5k | prefix_opc_table[insn] = max_matchedp; |
394 | 58.6k | } |
395 | | |
396 | 346k | return max_matchedp; |
397 | 346k | } |
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 | 79.5k | { |
409 | 79.5k | int retval = 0; |
410 | 79.5k | int tmp; |
411 | 79.5k | int prefix_ok = 0; |
412 | 79.5k | const char *s; |
413 | | |
414 | 236k | for (s = cs; *s; s++) |
415 | 192k | switch (*s) |
416 | 192k | { |
417 | 144 | case '!': |
418 | | /* Do not recognize "pop" if there's a prefix and then only for |
419 | | v0..v10. */ |
420 | 144 | if (prefix_insn != NO_CRIS_PREFIX |
421 | 144 | || disdata->distype != cris_dis_v0_v10) |
422 | 129 | return -1; |
423 | 15 | break; |
424 | | |
425 | 15 | case 'U': |
426 | | /* Not recognized at disassembly. */ |
427 | 0 | return -1; |
428 | | |
429 | 308 | 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 | 308 | tmp = ((insn >> 12) & 0xf); |
435 | 308 | if (tmp != 0 && tmp != 4 && tmp != 8) |
436 | 53 | return -1; |
437 | 255 | break; |
438 | | |
439 | 42.2k | case 'm': |
440 | 42.2k | if ((insn & 0x30) == 0x30) |
441 | 26.1k | return -1; |
442 | 16.0k | break; |
443 | | |
444 | 16.0k | case 'S': |
445 | | /* A prefix operand without side-effect. */ |
446 | 7.81k | if (prefix_insn != NO_CRIS_PREFIX && (insn & 0x400) == 0) |
447 | 698 | { |
448 | 698 | prefix_ok = 1; |
449 | 698 | break; |
450 | 698 | } |
451 | 7.11k | else |
452 | 7.11k | return -1; |
453 | | |
454 | 6.37k | case 's': |
455 | 7.25k | case 'y': |
456 | 7.27k | case 'Y': |
457 | | /* If this is a prefixed insn with postincrement (side-effect), |
458 | | the prefix must not be DIP. */ |
459 | 7.27k | if (prefix_insn != NO_CRIS_PREFIX) |
460 | 1.35k | { |
461 | 1.35k | if (insn & 0x400) |
462 | 849 | { |
463 | 849 | const struct cris_opcode *prefix_opcodep |
464 | 849 | = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata); |
465 | | |
466 | 849 | if (prefix_opcodep->match == DIP_OPCODE) |
467 | 158 | return -1; |
468 | 849 | } |
469 | | |
470 | 1.19k | prefix_ok = 1; |
471 | 1.19k | } |
472 | 7.11k | break; |
473 | | |
474 | 7.11k | case 'B': |
475 | | /* If we don't fall through, then the prefix is ok. */ |
476 | 29 | prefix_ok = 1; |
477 | | |
478 | | /* A "push" prefix. Check for valid "push" size. |
479 | | In case of special register, it may be != 4. */ |
480 | 29 | if (prefix_insn != NO_CRIS_PREFIX) |
481 | 13 | { |
482 | | /* Match the prefix insn to BDAPQ. */ |
483 | 13 | const struct cris_opcode *prefix_opcodep |
484 | 13 | = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata); |
485 | | |
486 | 13 | if (prefix_opcodep->match == BDAP_QUICK_OPCODE) |
487 | 12 | { |
488 | 12 | int pushsize = (prefix_insn & 255); |
489 | | |
490 | 12 | if (pushsize > 127) |
491 | 3 | pushsize -= 256; |
492 | | |
493 | 12 | if (s[1] == 'P') |
494 | 9 | { |
495 | 9 | unsigned int spec_reg = (insn >> 12) & 15; |
496 | 9 | const struct cris_spec_reg *sregp |
497 | 9 | = 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 | 9 | if (sregp && sregp->reg_size == (unsigned int) -pushsize) |
502 | 2 | break; |
503 | 9 | } |
504 | 3 | else if (s[1] == 'R') |
505 | 3 | { |
506 | 3 | if ((insn & 0x30) == 0x20 && pushsize == -4) |
507 | 1 | break; |
508 | 3 | } |
509 | | /* FIXME: Should abort here; next constraint letter |
510 | | *must* be 'P' or 'R'. */ |
511 | 12 | } |
512 | 13 | } |
513 | 26 | return -1; |
514 | | |
515 | 1.43k | case 'D': |
516 | 1.43k | retval = (((insn >> 12) & 15) == (insn & 15)); |
517 | 1.43k | if (!retval) |
518 | 1.25k | return -1; |
519 | 177 | else |
520 | 177 | retval += 4; |
521 | 177 | break; |
522 | | |
523 | 1.17k | case 'P': |
524 | 1.17k | { |
525 | 1.17k | const struct cris_spec_reg *sregp |
526 | 1.17k | = 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.17k | if (sregp != NULL) |
541 | 1.17k | { |
542 | 1.17k | retval += 3; |
543 | 1.17k | break; |
544 | 1.17k | } |
545 | 0 | else |
546 | 0 | return -1; |
547 | 1.17k | } |
548 | 192k | } |
549 | | |
550 | 44.6k | if (prefix_insn != NO_CRIS_PREFIX && ! prefix_ok) |
551 | 26.9k | return -1; |
552 | | |
553 | 17.6k | return retval; |
554 | 44.6k | } |
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 | 22.6k | { |
563 | | /* Truncate negative numbers on >32-bit hosts. */ |
564 | 22.6k | number &= 0xffffffff; |
565 | | |
566 | | /* Save this value for the "case" support. */ |
567 | 22.6k | if (TRACE_CASE) |
568 | 22.6k | last_immediate = number; |
569 | | |
570 | 22.6k | return outbuffer + sprintf (outbuffer, "0x%lx", number); |
571 | 22.6k | } |
572 | | |
573 | | /* Format number as decimal into outbuffer. Parameter signedp says |
574 | | whether the number should be formatted as signed (!= 0) or |
575 | | unsigned (== 0). */ |
576 | | |
577 | | static char * |
578 | | format_dec (long number, char *outbuffer, int signedp) |
579 | 60.0k | { |
580 | 60.0k | last_immediate = number; |
581 | 60.0k | return outbuffer + sprintf (outbuffer, signedp ? "%ld" : "%lu", number); |
582 | 60.0k | } |
583 | | |
584 | | /* Format the name of the general register regno into outbuffer. */ |
585 | | |
586 | | static char * |
587 | | format_reg (struct cris_disasm_data *disdata, |
588 | | int regno, |
589 | | char *outbuffer, |
590 | | bool with_reg_prefix) |
591 | 399k | { |
592 | 399k | if (with_reg_prefix) |
593 | 399k | *outbuffer++ = REGISTER_PREFIX_CHAR; |
594 | | |
595 | 399k | switch (regno) |
596 | 399k | { |
597 | 58.3k | case 15: |
598 | | /* For v32, there is no context in which we output PC. */ |
599 | 58.3k | if (disdata->distype == cris_dis_v32) |
600 | 0 | outbuffer = stpcpy (outbuffer, "acr"); |
601 | 58.3k | else |
602 | 58.3k | outbuffer = stpcpy (outbuffer, "pc"); |
603 | 58.3k | break; |
604 | | |
605 | 25.3k | case 14: |
606 | 25.3k | outbuffer = stpcpy (outbuffer, "sp"); |
607 | 25.3k | break; |
608 | | |
609 | 315k | default: |
610 | 315k | outbuffer += sprintf (outbuffer, "r%d", regno); |
611 | 315k | break; |
612 | 399k | } |
613 | | |
614 | 399k | return outbuffer; |
615 | 399k | } |
616 | | |
617 | | /* Format the name of a support register into outbuffer. */ |
618 | | |
619 | | static char * |
620 | | format_sup_reg (unsigned int regno, |
621 | | char *outbuffer, |
622 | | bool with_reg_prefix) |
623 | 0 | { |
624 | 0 | int i; |
625 | |
|
626 | 0 | if (with_reg_prefix) |
627 | 0 | *outbuffer++ = REGISTER_PREFIX_CHAR; |
628 | |
|
629 | 0 | for (i = 0; cris_support_regs[i].name != NULL; i++) |
630 | 0 | if (cris_support_regs[i].number == regno) |
631 | 0 | return stpcpy (outbuffer, cris_support_regs[i].name); |
632 | | |
633 | | /* There's supposed to be register names covering all numbers, though |
634 | | some may be generic names. */ |
635 | 0 | return stpcpy (outbuffer, "format_sup_reg-BUG"); |
636 | 0 | } |
637 | | |
638 | | /* Return the length of an instruction. */ |
639 | | |
640 | | static unsigned |
641 | | bytes_to_skip (unsigned int insn, |
642 | | const struct cris_opcode *matchedp, |
643 | | enum cris_disass_family distype, |
644 | | const struct cris_opcode *prefix_matchedp) |
645 | 328k | { |
646 | | /* Each insn is a word plus "immediate" operands. */ |
647 | 328k | unsigned to_skip = 2; |
648 | 328k | const char *template_name = (const char *) matchedp->args; |
649 | 328k | const char *s; |
650 | | |
651 | 1.47M | for (s = template_name; *s; s++) |
652 | 1.14M | if ((*s == 's' || *s == 'N' || *s == 'Y') |
653 | 1.14M | && (insn & 0x400) && (insn & 15) == 15 |
654 | 1.14M | && prefix_matchedp == NULL) |
655 | 5.73k | { |
656 | | /* Immediate via [pc+], so we have to check the size of the |
657 | | operand. */ |
658 | 5.73k | int mode_size = 1 << ((insn >> 4) & (*template_name == 'z' ? 1 : 3)); |
659 | | |
660 | 5.73k | if (matchedp->imm_oprnd_size == SIZE_FIX_32) |
661 | 1.80k | to_skip += 4; |
662 | 3.93k | else if (matchedp->imm_oprnd_size == SIZE_SPEC_REG) |
663 | 198 | { |
664 | 198 | const struct cris_spec_reg *sregp |
665 | 198 | = spec_reg_info ((insn >> 12) & 15, distype); |
666 | | |
667 | | /* FIXME: Improve error handling; should have been caught |
668 | | earlier. */ |
669 | 198 | if (sregp == NULL) |
670 | 0 | return 2; |
671 | | |
672 | | /* PC is incremented by two, not one, for a byte. Except on |
673 | | CRISv32, where constants are always DWORD-size for |
674 | | special registers. */ |
675 | 198 | to_skip += |
676 | 198 | distype == cris_dis_v32 ? 4 : (sregp->reg_size + 1) & ~1; |
677 | 198 | } |
678 | 3.73k | else |
679 | 3.73k | to_skip += (mode_size + 1) & ~1; |
680 | 5.73k | } |
681 | 1.14M | else if (*s == 'n') |
682 | 0 | to_skip += 4; |
683 | 1.14M | else if (*s == 'b') |
684 | 1.64k | to_skip += 2; |
685 | | |
686 | 328k | return to_skip; |
687 | 328k | } |
688 | | |
689 | | /* Print condition code flags. */ |
690 | | |
691 | | static char * |
692 | | print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp) |
693 | 2.71k | { |
694 | | /* Use the v8 (Etrax 100) flag definitions for disassembly. |
695 | | The differences with v0 (Etrax 1..4) vs. Svinto are: |
696 | | v0 'd' <=> v8 'm' |
697 | | v0 'e' <=> v8 'b'. |
698 | | FIXME: Emit v0..v3 flag names somehow. */ |
699 | 2.71k | static const char v8_fnames[] = "cvznxibm"; |
700 | 2.71k | static const char v32_fnames[] = "cvznxiup"; |
701 | 2.71k | const char *fnames |
702 | 2.71k | = disdata->distype == cris_dis_v32 ? v32_fnames : v8_fnames; |
703 | | |
704 | 2.71k | unsigned char flagbits = (((insn >> 8) & 0xf0) | (insn & 15)); |
705 | 2.71k | int i; |
706 | | |
707 | 24.3k | for (i = 0; i < 8; i++) |
708 | 21.6k | if (flagbits & (1 << i)) |
709 | 13.7k | *cp++ = fnames[i]; |
710 | | |
711 | 2.71k | return cp; |
712 | 2.71k | } |
713 | | |
714 | | /* Print out an insn with its operands, and update the info->insn_type |
715 | | fields. The prefix_opcodep and the rest hold a prefix insn that is |
716 | | supposed to be output as an address mode. */ |
717 | | |
718 | | static void |
719 | | print_with_operands (const struct cris_opcode *opcodep, |
720 | | unsigned int insn, |
721 | | unsigned char *buffer, |
722 | | bfd_vma addr, |
723 | | disassemble_info *info, |
724 | | /* If a prefix insn was before this insn (and is supposed |
725 | | to be output as an address), here is a description of |
726 | | it. */ |
727 | | const struct cris_opcode *prefix_opcodep, |
728 | | unsigned int prefix_insn, |
729 | | unsigned char *prefix_buffer, |
730 | | bool with_reg_prefix) |
731 | 290k | { |
732 | | /* Get a buffer of somewhat reasonable size where we store |
733 | | intermediate parts of the insn. */ |
734 | 290k | char temp[sizeof (".d [$r13=$r12-2147483648],$r10") * 2]; |
735 | 290k | char *tp = temp; |
736 | 290k | static const char mode_char[] = "bwd?"; |
737 | 290k | const char *s; |
738 | 290k | const char *cs; |
739 | 290k | struct cris_disasm_data *disdata |
740 | 290k | = (struct cris_disasm_data *) info->private_data; |
741 | | |
742 | | /* Print out the name first thing we do. */ |
743 | 290k | (*info->fprintf_func) (info->stream, "%s", opcodep->name); |
744 | | |
745 | 290k | cs = opcodep->args; |
746 | 290k | s = cs; |
747 | | |
748 | | /* Ignore any prefix indicator. */ |
749 | 290k | if (*s == 'p') |
750 | 26.4k | s++; |
751 | | |
752 | 290k | if (*s == 'm' || *s == 'M' || *s == 'z') |
753 | 131k | { |
754 | 131k | *tp++ = '.'; |
755 | | |
756 | | /* Get the size-letter. */ |
757 | 131k | *tp++ = *s == 'M' |
758 | 131k | ? (insn & 0x8000 ? 'd' |
759 | 975 | : insn & 0x4000 ? 'w' : 'b') |
760 | 131k | : mode_char[(insn >> 4) & (*s == 'z' ? 1 : 3)]; |
761 | | |
762 | | /* Ignore the size and the space character that follows. */ |
763 | 131k | s += 2; |
764 | 131k | } |
765 | | |
766 | | /* Add a space if this isn't a long-branch, because for those will add |
767 | | the condition part of the name later. */ |
768 | 290k | if (opcodep->match != (BRANCH_PC_LOW + BRANCH_INCR_HIGH * 256)) |
769 | 288k | *tp++ = ' '; |
770 | | |
771 | | /* Fill in the insn-type if deducible from the name (and there's no |
772 | | better way). */ |
773 | 290k | if (opcodep->name[0] == 'j') |
774 | 2.86k | { |
775 | 2.86k | if (startswith (opcodep->name, "jsr")) |
776 | | /* It's "jsr" or "jsrc". */ |
777 | 2.15k | info->insn_type = dis_jsr; |
778 | 715 | else |
779 | | /* Any other jump-type insn is considered a branch. */ |
780 | 715 | info->insn_type = dis_branch; |
781 | 2.86k | } |
782 | | |
783 | | /* We might know some more fields right now. */ |
784 | 290k | info->branch_delay_insns = opcodep->delayed; |
785 | | |
786 | | /* Handle operands. */ |
787 | 1.02M | for (; *s; s++) |
788 | 730k | { |
789 | 730k | switch (*s) |
790 | 730k | { |
791 | 0 | case 'T': |
792 | 0 | tp = format_sup_reg ((insn >> 12) & 15, tp, with_reg_prefix); |
793 | 0 | break; |
794 | | |
795 | 0 | case 'A': |
796 | 0 | if (with_reg_prefix) |
797 | 0 | *tp++ = REGISTER_PREFIX_CHAR; |
798 | 0 | *tp++ = 'a'; |
799 | 0 | *tp++ = 'c'; |
800 | 0 | *tp++ = 'r'; |
801 | 0 | break; |
802 | | |
803 | 0 | case '[': |
804 | 0 | case ']': |
805 | 217k | case ',': |
806 | 217k | *tp++ = *s; |
807 | 217k | break; |
808 | | |
809 | 4.45k | case '!': |
810 | | /* Ignore at this point; used at earlier stages to avoid |
811 | | recognition if there's a prefix at something that in other |
812 | | ways looks like a "pop". */ |
813 | 4.45k | break; |
814 | | |
815 | 0 | case 'd': |
816 | | /* Ignore. This is an optional ".d " on the large one of |
817 | | relaxable insns. */ |
818 | 0 | break; |
819 | | |
820 | 68 | case 'B': |
821 | | /* This was the prefix that made this a "push". We've already |
822 | | handled it by recognizing it, so signal that the prefix is |
823 | | handled by setting it to NULL. */ |
824 | 68 | prefix_opcodep = NULL; |
825 | 68 | break; |
826 | | |
827 | 2.84k | case 'D': |
828 | 65.1k | case 'r': |
829 | 65.1k | tp = format_reg (disdata, insn & 15, tp, with_reg_prefix); |
830 | 65.1k | break; |
831 | | |
832 | 206k | case 'R': |
833 | 206k | tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix); |
834 | 206k | break; |
835 | | |
836 | 0 | case 'n': |
837 | 0 | { |
838 | | /* Like N but pc-relative to the start of the insn. */ |
839 | 0 | int32_t number = (buffer[2] + buffer[3] * 256 + buffer[4] * 65536 |
840 | 0 | + buffer[5] * 0x1000000u); |
841 | | |
842 | | /* Finish off and output previous formatted bytes. */ |
843 | 0 | *tp = 0; |
844 | 0 | if (temp[0]) |
845 | 0 | (*info->fprintf_func) (info->stream, "%s", temp); |
846 | 0 | tp = temp; |
847 | |
|
848 | 0 | (*info->print_address_func) (addr + number, info); |
849 | 0 | } |
850 | 0 | break; |
851 | | |
852 | 0 | case 'u': |
853 | 0 | { |
854 | | /* Like n but the offset is bits <3:0> in the instruction. */ |
855 | 0 | unsigned int number = (buffer[0] & 0xf) * 2; |
856 | | |
857 | | /* Finish off and output previous formatted bytes. */ |
858 | 0 | *tp = 0; |
859 | 0 | if (temp[0]) |
860 | 0 | (*info->fprintf_func) (info->stream, "%s", temp); |
861 | 0 | tp = temp; |
862 | |
|
863 | 0 | (*info->print_address_func) (addr + number, info); |
864 | 0 | } |
865 | 0 | break; |
866 | | |
867 | 0 | case 'N': |
868 | 40.6k | case 'y': |
869 | 40.9k | case 'Y': |
870 | 43.3k | case 'S': |
871 | 128k | case 's': |
872 | | /* Any "normal" memory operand. */ |
873 | 128k | if ((insn & 0x400) && (insn & 15) == 15 && prefix_opcodep == NULL) |
874 | 35.0k | { |
875 | | /* We're looking at [pc+], i.e. we need to output an immediate |
876 | | number, where the size can depend on different things. */ |
877 | 35.0k | int32_t number; |
878 | 35.0k | int signedp |
879 | 35.0k | = ((*cs == 'z' && (insn & 0x20)) |
880 | 35.0k | || opcodep->match == BDAP_QUICK_OPCODE); |
881 | 35.0k | int nbytes; |
882 | | |
883 | 35.0k | if (opcodep->imm_oprnd_size == SIZE_FIX_32) |
884 | 28.7k | nbytes = 4; |
885 | 6.32k | else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG) |
886 | 451 | { |
887 | 451 | const struct cris_spec_reg *sregp |
888 | 451 | = spec_reg_info ((insn >> 12) & 15, disdata->distype); |
889 | | |
890 | | /* A NULL return should have been as a non-match earlier, |
891 | | so catch it as an internal error in the error-case |
892 | | below. */ |
893 | 451 | if (sregp == NULL) |
894 | | /* Whatever non-valid size. */ |
895 | 0 | nbytes = 42; |
896 | 451 | else |
897 | | /* PC is always incremented by a multiple of two. |
898 | | For CRISv32, immediates are always 4 bytes for |
899 | | special registers. */ |
900 | 451 | nbytes = disdata->distype == cris_dis_v32 |
901 | 451 | ? 4 : (sregp->reg_size + 1) & ~1; |
902 | 451 | } |
903 | 5.87k | else |
904 | 5.87k | { |
905 | 5.87k | int mode_size = 1 << ((insn >> 4) & (*cs == 'z' ? 1 : 3)); |
906 | | |
907 | 5.87k | if (mode_size == 1) |
908 | 3.12k | nbytes = 2; |
909 | 2.74k | else |
910 | 2.74k | nbytes = mode_size; |
911 | 5.87k | } |
912 | | |
913 | 35.0k | switch (nbytes) |
914 | 35.0k | { |
915 | 0 | case 1: |
916 | 0 | number = buffer[2]; |
917 | 0 | if (signedp && number > 127) |
918 | 0 | number -= 256; |
919 | 0 | break; |
920 | | |
921 | 4.60k | case 2: |
922 | 4.60k | number = buffer[2] + buffer[3] * 256; |
923 | 4.60k | if (signedp && number > 32767) |
924 | 217 | number -= 65536; |
925 | 4.60k | break; |
926 | | |
927 | 29.8k | case 4: |
928 | 29.8k | number = (buffer[2] + buffer[3] * 256 + buffer[4] * 65536 |
929 | 29.8k | + buffer[5] * 0x1000000u); |
930 | 29.8k | break; |
931 | | |
932 | 592 | default: |
933 | 592 | strcpy (tp, "bug"); |
934 | 592 | tp += 3; |
935 | 592 | number = 42; |
936 | 35.0k | } |
937 | | |
938 | 35.0k | if ((*cs == 'z' && (insn & 0x20)) |
939 | 35.0k | || (opcodep->match == BDAP_QUICK_OPCODE |
940 | 34.4k | && (nbytes <= 2 || buffer[1 + nbytes] == 0))) |
941 | 568 | tp = format_dec (number, tp, signedp); |
942 | 34.4k | else |
943 | 34.4k | { |
944 | 34.4k | unsigned int highbyte = (number >> 24) & 0xff; |
945 | | |
946 | | /* Either output this as an address or as a number. If it's |
947 | | a dword with the same high-byte as the address of the |
948 | | insn, assume it's an address, and also if it's a non-zero |
949 | | non-0xff high-byte. If this is a jsr or a jump, then |
950 | | it's definitely an address. */ |
951 | 34.4k | if (nbytes == 4 |
952 | 34.4k | && (highbyte == ((addr >> 24) & 0xff) |
953 | 29.8k | || (highbyte != 0 && highbyte != 0xff) |
954 | 29.8k | || info->insn_type == dis_branch |
955 | 29.8k | || info->insn_type == dis_jsr)) |
956 | 11.7k | { |
957 | | /* Finish off and output previous formatted bytes. */ |
958 | 11.7k | *tp = 0; |
959 | 11.7k | tp = temp; |
960 | 11.7k | if (temp[0]) |
961 | 11.7k | (*info->fprintf_func) (info->stream, "%s", temp); |
962 | | |
963 | 11.7k | (*info->print_address_func) ((bfd_vma) number, info); |
964 | | |
965 | 11.7k | info->target = number; |
966 | 11.7k | } |
967 | 22.6k | else |
968 | 22.6k | tp = format_hex (number, tp, disdata); |
969 | 34.4k | } |
970 | 35.0k | } |
971 | 93.4k | else |
972 | 93.4k | { |
973 | | /* Not an immediate number. Then this is a (possibly |
974 | | prefixed) memory operand. */ |
975 | 93.4k | if (info->insn_type != dis_nonbranch) |
976 | 2.12k | { |
977 | 2.12k | int mode_size |
978 | 2.12k | = 1 << ((insn >> 4) |
979 | 2.12k | & (opcodep->args[0] == 'z' ? 1 : 3)); |
980 | 2.12k | int size; |
981 | 2.12k | info->insn_type = dis_dref; |
982 | 2.12k | info->flags |= CRIS_DIS_FLAG_MEMREF; |
983 | | |
984 | 2.12k | if (opcodep->imm_oprnd_size == SIZE_FIX_32) |
985 | 2.12k | size = 4; |
986 | 0 | else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG) |
987 | 0 | { |
988 | 0 | const struct cris_spec_reg *sregp |
989 | 0 | = spec_reg_info ((insn >> 12) & 15, disdata->distype); |
990 | | |
991 | | /* FIXME: Improve error handling; should have been caught |
992 | | earlier. */ |
993 | 0 | if (sregp == NULL) |
994 | 0 | size = 4; |
995 | 0 | else |
996 | 0 | size = sregp->reg_size; |
997 | 0 | } |
998 | 0 | else |
999 | 0 | size = mode_size; |
1000 | | |
1001 | 2.12k | info->data_size = size; |
1002 | 2.12k | } |
1003 | | |
1004 | 93.4k | *tp++ = '['; |
1005 | | |
1006 | 93.4k | if (prefix_opcodep |
1007 | | /* We don't match dip with a postincremented field |
1008 | | as a side-effect address mode. */ |
1009 | 93.4k | && ((insn & 0x400) == 0 |
1010 | 13.4k | || prefix_opcodep->match != DIP_OPCODE)) |
1011 | 13.4k | { |
1012 | 13.4k | if (insn & 0x400) |
1013 | 8.46k | { |
1014 | 8.46k | tp = format_reg (disdata, insn & 15, tp, with_reg_prefix); |
1015 | 8.46k | *tp++ = '='; |
1016 | 8.46k | } |
1017 | | |
1018 | | |
1019 | | /* We mainly ignore the prefix format string when the |
1020 | | address-mode syntax is output. */ |
1021 | 13.4k | switch (prefix_opcodep->match) |
1022 | 13.4k | { |
1023 | 261 | case DIP_OPCODE: |
1024 | | /* It's [r], [r+] or [pc+]. */ |
1025 | 261 | if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15) |
1026 | 35 | { |
1027 | | /* It's [pc+]. This cannot possibly be anything |
1028 | | but an address. */ |
1029 | 35 | int32_t number = (prefix_buffer[2] |
1030 | 35 | + prefix_buffer[3] * 256 |
1031 | 35 | + prefix_buffer[4] * 65536 |
1032 | 35 | + prefix_buffer[5] * 0x1000000u); |
1033 | | |
1034 | 35 | info->target = (bfd_vma) number; |
1035 | | |
1036 | | /* Finish off and output previous formatted |
1037 | | data. */ |
1038 | 35 | *tp = 0; |
1039 | 35 | tp = temp; |
1040 | 35 | if (temp[0]) |
1041 | 35 | (*info->fprintf_func) (info->stream, "%s", temp); |
1042 | | |
1043 | 35 | (*info->print_address_func) ((bfd_vma) number, info); |
1044 | 35 | } |
1045 | 226 | else |
1046 | 226 | { |
1047 | | /* For a memref in an address, we use target2. |
1048 | | In this case, target is zero. */ |
1049 | 226 | info->flags |
1050 | 226 | |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG |
1051 | 226 | | CRIS_DIS_FLAG_MEM_TARGET2_MEM); |
1052 | | |
1053 | 226 | info->target2 = prefix_insn & 15; |
1054 | | |
1055 | 226 | *tp++ = '['; |
1056 | 226 | tp = format_reg (disdata, prefix_insn & 15, tp, |
1057 | 226 | with_reg_prefix); |
1058 | 226 | if (prefix_insn & 0x400) |
1059 | 24 | *tp++ = '+'; |
1060 | 226 | *tp++ = ']'; |
1061 | 226 | } |
1062 | 261 | break; |
1063 | | |
1064 | 7.10k | case BDAP_QUICK_OPCODE: |
1065 | 7.10k | { |
1066 | 7.10k | int number; |
1067 | | |
1068 | 7.10k | number = prefix_buffer[0]; |
1069 | 7.10k | if (number > 127) |
1070 | 3.29k | number -= 256; |
1071 | | |
1072 | | /* Output "reg+num" or, if num < 0, "reg-num". */ |
1073 | 7.10k | tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp, |
1074 | 7.10k | with_reg_prefix); |
1075 | 7.10k | if (number >= 0) |
1076 | 3.81k | *tp++ = '+'; |
1077 | 7.10k | tp = format_dec (number, tp, 1); |
1078 | | |
1079 | 7.10k | info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG; |
1080 | 7.10k | info->target = (prefix_insn >> 12) & 15; |
1081 | 7.10k | info->target2 = (bfd_vma) number; |
1082 | 7.10k | break; |
1083 | 0 | } |
1084 | | |
1085 | 2.65k | case BIAP_OPCODE: |
1086 | | /* Output "r+R.m". */ |
1087 | 2.65k | tp = format_reg (disdata, prefix_insn & 15, tp, |
1088 | 2.65k | with_reg_prefix); |
1089 | 2.65k | *tp++ = '+'; |
1090 | 2.65k | tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp, |
1091 | 2.65k | with_reg_prefix); |
1092 | 2.65k | *tp++ = '.'; |
1093 | 2.65k | *tp++ = mode_char[(prefix_insn >> 4) & 3]; |
1094 | | |
1095 | 2.65k | info->flags |
1096 | 2.65k | |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG |
1097 | 2.65k | | CRIS_DIS_FLAG_MEM_TARGET_IS_REG |
1098 | | |
1099 | 2.65k | | ((prefix_insn & 0x8000) |
1100 | 2.65k | ? CRIS_DIS_FLAG_MEM_TARGET2_MULT4 |
1101 | 2.65k | : ((prefix_insn & 0x8000) |
1102 | 2.08k | ? CRIS_DIS_FLAG_MEM_TARGET2_MULT2 : 0))); |
1103 | | |
1104 | | /* Is it the casejump? It's a "adds.w [pc+r%d.w],pc". */ |
1105 | 2.65k | if (insn == 0xf83f && (prefix_insn & ~0xf000) == 0x55f) |
1106 | | /* Then start interpreting data as offsets. */ |
1107 | 0 | case_offset_counter = no_of_case_offsets; |
1108 | 2.65k | break; |
1109 | | |
1110 | 3.47k | case BDAP_INDIR_OPCODE: |
1111 | | /* Output "r+s.m", or, if "s" is [pc+], "r+s" or |
1112 | | "r-s". */ |
1113 | 3.47k | tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp, |
1114 | 3.47k | with_reg_prefix); |
1115 | | |
1116 | 3.47k | if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15) |
1117 | 359 | { |
1118 | 359 | int32_t number; |
1119 | 359 | unsigned int nbytes; |
1120 | | |
1121 | | /* It's a value. Get its size. */ |
1122 | 359 | int mode_size = 1 << ((prefix_insn >> 4) & 3); |
1123 | | |
1124 | 359 | if (mode_size == 1) |
1125 | 195 | nbytes = 2; |
1126 | 164 | else |
1127 | 164 | nbytes = mode_size; |
1128 | | |
1129 | 359 | switch (nbytes) |
1130 | 359 | { |
1131 | 0 | case 1: |
1132 | 0 | number = prefix_buffer[2]; |
1133 | 0 | if (number > 127) |
1134 | 0 | number -= 256; |
1135 | 0 | break; |
1136 | | |
1137 | 309 | case 2: |
1138 | 309 | number = prefix_buffer[2] + prefix_buffer[3] * 256; |
1139 | 309 | if (number > 32767) |
1140 | 156 | number -= 65536; |
1141 | 309 | break; |
1142 | | |
1143 | 50 | case 4: |
1144 | 50 | number = (prefix_buffer[2] + prefix_buffer[3] * 256 |
1145 | 50 | + prefix_buffer[4] * 65536 |
1146 | 50 | + prefix_buffer[5] * 0x1000000u); |
1147 | 50 | break; |
1148 | | |
1149 | 0 | default: |
1150 | 0 | strcpy (tp, "bug"); |
1151 | 0 | tp += 3; |
1152 | 0 | number = 42; |
1153 | 359 | } |
1154 | | |
1155 | 359 | info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG; |
1156 | 359 | info->target2 = (bfd_vma) number; |
1157 | | |
1158 | | /* If the size is dword, then assume it's an |
1159 | | address. */ |
1160 | 359 | if (nbytes == 4) |
1161 | 50 | { |
1162 | | /* Finish off and output previous formatted |
1163 | | bytes. */ |
1164 | 50 | *tp++ = '+'; |
1165 | 50 | *tp = 0; |
1166 | 50 | tp = temp; |
1167 | 50 | (*info->fprintf_func) (info->stream, "%s", temp); |
1168 | | |
1169 | 50 | (*info->print_address_func) ((bfd_vma) number, info); |
1170 | 50 | } |
1171 | 309 | else |
1172 | 309 | { |
1173 | 309 | if (number >= 0) |
1174 | 153 | *tp++ = '+'; |
1175 | 309 | tp = format_dec (number, tp, 1); |
1176 | 309 | } |
1177 | 359 | } |
1178 | 3.11k | else |
1179 | 3.11k | { |
1180 | | /* Output "r+[R].m" or "r+[R+].m". */ |
1181 | 3.11k | *tp++ = '+'; |
1182 | 3.11k | *tp++ = '['; |
1183 | 3.11k | tp = format_reg (disdata, prefix_insn & 15, tp, |
1184 | 3.11k | with_reg_prefix); |
1185 | 3.11k | if (prefix_insn & 0x400) |
1186 | 1.67k | *tp++ = '+'; |
1187 | 3.11k | *tp++ = ']'; |
1188 | 3.11k | *tp++ = '.'; |
1189 | 3.11k | *tp++ = mode_char[(prefix_insn >> 4) & 3]; |
1190 | | |
1191 | 3.11k | info->flags |
1192 | 3.11k | |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG |
1193 | 3.11k | | CRIS_DIS_FLAG_MEM_TARGET2_MEM |
1194 | 3.11k | | CRIS_DIS_FLAG_MEM_TARGET_IS_REG |
1195 | | |
1196 | 3.11k | | (((prefix_insn >> 4) == 2) |
1197 | 3.11k | ? 0 |
1198 | 3.11k | : (((prefix_insn >> 4) & 3) == 1 |
1199 | 3.11k | ? CRIS_DIS_FLAG_MEM_TARGET2_MEM_WORD |
1200 | 3.11k | : CRIS_DIS_FLAG_MEM_TARGET2_MEM_BYTE))); |
1201 | 3.11k | } |
1202 | 3.47k | break; |
1203 | | |
1204 | 3.47k | default: |
1205 | 0 | (*info->fprintf_func) (info->stream, "?prefix-bug"); |
1206 | 13.4k | } |
1207 | | |
1208 | | /* To mark that the prefix is used, reset it. */ |
1209 | 13.4k | prefix_opcodep = NULL; |
1210 | 13.4k | } |
1211 | 79.9k | else |
1212 | 79.9k | { |
1213 | 79.9k | tp = format_reg (disdata, insn & 15, tp, with_reg_prefix); |
1214 | | |
1215 | 79.9k | info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG; |
1216 | 79.9k | info->target = insn & 15; |
1217 | | |
1218 | 79.9k | if (insn & 0x400) |
1219 | 46.0k | *tp++ = '+'; |
1220 | 79.9k | } |
1221 | 93.4k | *tp++ = ']'; |
1222 | 93.4k | } |
1223 | 128k | break; |
1224 | | |
1225 | 128k | case 'x': |
1226 | 2.91k | tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix); |
1227 | 2.91k | *tp++ = '.'; |
1228 | 2.91k | *tp++ = mode_char[(insn >> 4) & 3]; |
1229 | 2.91k | break; |
1230 | | |
1231 | 13.2k | case 'I': |
1232 | 13.2k | tp = format_dec (insn & 63, tp, 0); |
1233 | 13.2k | break; |
1234 | | |
1235 | 1.64k | case 'b': |
1236 | 1.64k | { |
1237 | 1.64k | int where = buffer[2] + buffer[3] * 256; |
1238 | | |
1239 | 1.64k | if (where > 32767) |
1240 | 334 | where -= 65536; |
1241 | | |
1242 | 1.64k | where += addr + ((disdata->distype == cris_dis_v32) ? 0 : 4); |
1243 | | |
1244 | 1.64k | if (insn == BA_PC_INCR_OPCODE) |
1245 | 75 | info->insn_type = dis_branch; |
1246 | 1.56k | else |
1247 | 1.56k | info->insn_type = dis_condbranch; |
1248 | | |
1249 | 1.64k | info->target = (bfd_vma) where; |
1250 | | |
1251 | 1.64k | *tp = 0; |
1252 | 1.64k | tp = temp; |
1253 | 1.64k | (*info->fprintf_func) (info->stream, "%s%s ", |
1254 | 1.64k | temp, cris_cc_strings[insn >> 12]); |
1255 | | |
1256 | 1.64k | (*info->print_address_func) ((bfd_vma) where, info); |
1257 | 1.64k | } |
1258 | 1.64k | break; |
1259 | | |
1260 | 5.53k | case 'c': |
1261 | 5.53k | tp = format_dec (insn & 31, tp, 0); |
1262 | 5.53k | break; |
1263 | | |
1264 | 52 | case 'C': |
1265 | 52 | tp = format_dec (insn & 15, tp, 0); |
1266 | 52 | break; |
1267 | | |
1268 | 37.9k | case 'o': |
1269 | 37.9k | { |
1270 | 37.9k | long offset = insn & 0xfe; |
1271 | 37.9k | bfd_vma target; |
1272 | | |
1273 | 37.9k | if (insn & 1) |
1274 | 17.1k | offset |= ~0xff; |
1275 | | |
1276 | 37.9k | if (opcodep->match == BA_QUICK_OPCODE) |
1277 | 1.17k | info->insn_type = dis_branch; |
1278 | 36.7k | else |
1279 | 36.7k | info->insn_type = dis_condbranch; |
1280 | | |
1281 | 37.9k | target = addr + ((disdata->distype == cris_dis_v32) ? 0 : 2) + offset; |
1282 | 37.9k | info->target = target; |
1283 | 37.9k | *tp = 0; |
1284 | 37.9k | tp = temp; |
1285 | 37.9k | (*info->fprintf_func) (info->stream, "%s", temp); |
1286 | 37.9k | (*info->print_address_func) (target, info); |
1287 | 37.9k | } |
1288 | 37.9k | break; |
1289 | | |
1290 | 0 | case 'Q': |
1291 | 17.3k | case 'O': |
1292 | 17.3k | { |
1293 | 17.3k | long number = buffer[0]; |
1294 | | |
1295 | 17.3k | if (number > 127) |
1296 | 6.38k | number = number - 256; |
1297 | | |
1298 | 17.3k | tp = format_dec (number, tp, 1); |
1299 | 17.3k | *tp++ = ','; |
1300 | 17.3k | tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix); |
1301 | 17.3k | } |
1302 | 17.3k | break; |
1303 | | |
1304 | 2.71k | case 'f': |
1305 | 2.71k | tp = print_flags (disdata, insn, tp); |
1306 | 2.71k | break; |
1307 | | |
1308 | 15.8k | case 'i': |
1309 | 15.8k | tp = format_dec ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1); |
1310 | 15.8k | break; |
1311 | | |
1312 | 10.7k | case 'P': |
1313 | 10.7k | { |
1314 | 10.7k | const struct cris_spec_reg *sregp |
1315 | 10.7k | = spec_reg_info ((insn >> 12) & 15, disdata->distype); |
1316 | | |
1317 | 10.7k | if (sregp->name == NULL) |
1318 | | /* Should have been caught as a non-match eariler. */ |
1319 | 0 | *tp++ = '?'; |
1320 | 10.7k | else |
1321 | 10.7k | { |
1322 | 10.7k | if (with_reg_prefix) |
1323 | 10.7k | *tp++ = REGISTER_PREFIX_CHAR; |
1324 | 10.7k | strcpy (tp, sregp->name); |
1325 | 10.7k | tp += strlen (tp); |
1326 | 10.7k | } |
1327 | 10.7k | } |
1328 | 10.7k | break; |
1329 | | |
1330 | 0 | default: |
1331 | 0 | strcpy (tp, "???"); |
1332 | 0 | tp += 3; |
1333 | 730k | } |
1334 | 730k | } |
1335 | | |
1336 | 290k | *tp = 0; |
1337 | | |
1338 | 290k | if (prefix_opcodep) |
1339 | 0 | (*info->fprintf_func) (info->stream, " (OOPS unused prefix \"%s: %s\")", |
1340 | 0 | prefix_opcodep->name, prefix_opcodep->args); |
1341 | | |
1342 | 290k | (*info->fprintf_func) (info->stream, "%s", temp); |
1343 | | |
1344 | | /* Get info for matching case-tables, if we don't have any active. |
1345 | | We assume that the last constant seen is used; either in the insn |
1346 | | itself or in a "move.d const,rN, sub.d rN,rM"-like sequence. */ |
1347 | 290k | if (TRACE_CASE && case_offset_counter == 0) |
1348 | 290k | { |
1349 | 290k | if (startswith (opcodep->name, "sub")) |
1350 | 21.5k | case_offset = last_immediate; |
1351 | | |
1352 | | /* It could also be an "add", if there are negative case-values. */ |
1353 | 268k | else if (startswith (opcodep->name, "add")) |
1354 | | /* The first case is the negated operand to the add. */ |
1355 | 32.0k | case_offset = -last_immediate; |
1356 | | |
1357 | | /* A bound insn will tell us the number of cases. */ |
1358 | 236k | else if (startswith (opcodep->name, "bound")) |
1359 | 8.56k | no_of_case_offsets = last_immediate + 1; |
1360 | | |
1361 | | /* A jump or jsr or branch breaks the chain of insns for a |
1362 | | case-table, so assume default first-case again. */ |
1363 | 228k | else if (info->insn_type == dis_jsr |
1364 | 228k | || info->insn_type == dis_branch |
1365 | 228k | || info->insn_type == dis_condbranch) |
1366 | 40.3k | case_offset = 0; |
1367 | 290k | } |
1368 | 290k | } |
1369 | | |
1370 | | |
1371 | | /* Print the CRIS instruction at address memaddr on stream. Returns |
1372 | | length of the instruction, in bytes. Prefix register names with `$' if |
1373 | | WITH_REG_PREFIX. */ |
1374 | | |
1375 | | static int |
1376 | | print_insn_cris_generic (bfd_vma memaddr, |
1377 | | disassemble_info *info, |
1378 | | bool with_reg_prefix) |
1379 | 344k | { |
1380 | 344k | int nbytes; |
1381 | 344k | unsigned int insn; |
1382 | 344k | const struct cris_opcode *matchedp; |
1383 | 344k | int advance = 0; |
1384 | 344k | struct cris_disasm_data *disdata |
1385 | 344k | = (struct cris_disasm_data *) info->private_data; |
1386 | | |
1387 | | /* No instruction will be disassembled as longer than this number of |
1388 | | bytes; stacked prefixes will not be expanded. */ |
1389 | 344k | unsigned char buffer[MAX_BYTES_PER_CRIS_INSN]; |
1390 | 344k | unsigned char *bufp; |
1391 | 344k | int status = 0; |
1392 | 344k | bfd_vma addr; |
1393 | | |
1394 | | /* There will be an "out of range" error after the last instruction. |
1395 | | Reading pairs of bytes in decreasing number, we hope that we will get |
1396 | | at least the amount that we will consume. |
1397 | | |
1398 | | If we can't get any data, or we do not get enough data, we print |
1399 | | the error message. */ |
1400 | | |
1401 | 349k | for (nbytes = MAX_BYTES_PER_CRIS_INSN; nbytes > 0; nbytes -= 2) |
1402 | 349k | { |
1403 | 349k | status = (*info->read_memory_func) (memaddr, buffer, nbytes, info); |
1404 | 349k | if (status == 0) |
1405 | 344k | break; |
1406 | 349k | } |
1407 | | |
1408 | | /* If we did not get all we asked for, then clear the rest. |
1409 | | Hopefully this makes a reproducible result in case of errors. */ |
1410 | 344k | if (nbytes != MAX_BYTES_PER_CRIS_INSN) |
1411 | 2.23k | memset (buffer + nbytes, 0, MAX_BYTES_PER_CRIS_INSN - nbytes); |
1412 | | |
1413 | 344k | addr = memaddr; |
1414 | 344k | bufp = buffer; |
1415 | | |
1416 | | /* Set some defaults for the insn info. */ |
1417 | 344k | info->insn_info_valid = 1; |
1418 | 344k | info->branch_delay_insns = 0; |
1419 | 344k | info->data_size = 0; |
1420 | 344k | info->insn_type = dis_nonbranch; |
1421 | 344k | info->flags = 0; |
1422 | 344k | info->target = 0; |
1423 | 344k | info->target2 = 0; |
1424 | | |
1425 | | /* If we got any data, disassemble it. */ |
1426 | 344k | if (nbytes != 0) |
1427 | 344k | { |
1428 | 344k | matchedp = NULL; |
1429 | | |
1430 | 344k | insn = bufp[0] + bufp[1] * 256; |
1431 | | |
1432 | | /* If we're in a case-table, don't disassemble the offsets. */ |
1433 | 344k | if (TRACE_CASE && case_offset_counter != 0) |
1434 | 0 | { |
1435 | 0 | info->insn_type = dis_noninsn; |
1436 | 0 | advance += 2; |
1437 | | |
1438 | | /* If to print data as offsets, then shortcut here. */ |
1439 | 0 | (*info->fprintf_func) (info->stream, "case %ld%s: -> ", |
1440 | 0 | case_offset + no_of_case_offsets |
1441 | 0 | - case_offset_counter, |
1442 | 0 | case_offset_counter == 1 ? "/default" : |
1443 | 0 | ""); |
1444 | |
|
1445 | 0 | (*info->print_address_func) ((bfd_vma) |
1446 | 0 | ((short) (insn) |
1447 | 0 | + (long) (addr |
1448 | 0 | - (no_of_case_offsets |
1449 | 0 | - case_offset_counter) |
1450 | 0 | * 2)), info); |
1451 | 0 | case_offset_counter--; |
1452 | | |
1453 | | /* The default case start (without a "sub" or "add") must be |
1454 | | zero. */ |
1455 | 0 | if (case_offset_counter == 0) |
1456 | 0 | case_offset = 0; |
1457 | 0 | } |
1458 | 344k | else if (insn == 0) |
1459 | 36.0k | { |
1460 | | /* We're often called to disassemble zeroes. While this is a |
1461 | | valid "bcc .+2" insn, it is also useless enough and enough |
1462 | | of a nuiscance that we will just output "bcc .+2" for it |
1463 | | and signal it as a noninsn. */ |
1464 | 36.0k | (*info->fprintf_func) (info->stream, |
1465 | 36.0k | disdata->distype == cris_dis_v32 |
1466 | 36.0k | ? "bcc ." : "bcc .+2"); |
1467 | 36.0k | info->insn_type = dis_noninsn; |
1468 | 36.0k | advance += 2; |
1469 | 36.0k | } |
1470 | 308k | else |
1471 | 308k | { |
1472 | 308k | const struct cris_opcode *prefix_opcodep = NULL; |
1473 | 308k | unsigned char *prefix_buffer = bufp; |
1474 | 308k | unsigned int prefix_insn = insn; |
1475 | 308k | int prefix_size = 0; |
1476 | | |
1477 | 308k | matchedp = get_opcode_entry (insn, NO_CRIS_PREFIX, disdata); |
1478 | | |
1479 | | /* Check if we're supposed to write out prefixes as address |
1480 | | modes and if this was a prefix. */ |
1481 | 308k | if (matchedp != NULL && PARSE_PREFIX && matchedp->args[0] == 'p') |
1482 | 37.9k | { |
1483 | | /* If it's a prefix, put it into the prefix vars and get the |
1484 | | main insn. */ |
1485 | 37.9k | prefix_size = bytes_to_skip (prefix_insn, matchedp, |
1486 | 37.9k | disdata->distype, NULL); |
1487 | 37.9k | prefix_opcodep = matchedp; |
1488 | | |
1489 | 37.9k | insn = bufp[prefix_size] + bufp[prefix_size + 1] * 256; |
1490 | 37.9k | matchedp = get_opcode_entry (insn, prefix_insn, disdata); |
1491 | | |
1492 | 37.9k | if (matchedp != NULL) |
1493 | 13.5k | { |
1494 | 13.5k | addr += prefix_size; |
1495 | 13.5k | bufp += prefix_size; |
1496 | 13.5k | advance += prefix_size; |
1497 | 13.5k | } |
1498 | 24.3k | else |
1499 | 24.3k | { |
1500 | | /* The "main" insn wasn't valid, at least not when |
1501 | | prefixed. Put back things enough to output the |
1502 | | prefix insn only, as a normal insn. */ |
1503 | 24.3k | matchedp = prefix_opcodep; |
1504 | 24.3k | insn = prefix_insn; |
1505 | 24.3k | prefix_opcodep = NULL; |
1506 | 24.3k | } |
1507 | 37.9k | } |
1508 | | |
1509 | 308k | if (matchedp == NULL) |
1510 | 17.6k | { |
1511 | 17.6k | (*info->fprintf_func) (info->stream, "??0x%x", insn); |
1512 | 17.6k | advance += 2; |
1513 | | |
1514 | 17.6k | info->insn_type = dis_noninsn; |
1515 | 17.6k | } |
1516 | 290k | else |
1517 | 290k | { |
1518 | 290k | advance |
1519 | 290k | += bytes_to_skip (insn, matchedp, disdata->distype, |
1520 | 290k | prefix_opcodep); |
1521 | | |
1522 | | /* The info_type and assorted fields will be set according |
1523 | | to the operands. */ |
1524 | 290k | print_with_operands (matchedp, insn, bufp, addr, info, |
1525 | 290k | prefix_opcodep, prefix_insn, |
1526 | 290k | prefix_buffer, with_reg_prefix); |
1527 | 290k | } |
1528 | 308k | } |
1529 | 344k | } |
1530 | 331 | else |
1531 | 331 | info->insn_type = dis_noninsn; |
1532 | | |
1533 | | /* If we read less than MAX_BYTES_PER_CRIS_INSN, i.e. we got an error |
1534 | | status when reading that much, and the insn decoding indicated a |
1535 | | length exceeding what we read, there is an error. */ |
1536 | 344k | if (status != 0 && (nbytes == 0 || advance > nbytes)) |
1537 | 331 | { |
1538 | 331 | (*info->memory_error_func) (status, memaddr, info); |
1539 | 331 | return -1; |
1540 | 331 | } |
1541 | | |
1542 | | /* Max supported insn size with one folded prefix insn. */ |
1543 | 344k | info->bytes_per_line = MAX_BYTES_PER_CRIS_INSN; |
1544 | | |
1545 | | /* I would like to set this to a fixed value larger than the actual |
1546 | | number of bytes to print in order to avoid spaces between bytes, |
1547 | | but objdump.c (2.9.1) does not like that, so we print 16-bit |
1548 | | chunks, which is the next choice. */ |
1549 | 344k | info->bytes_per_chunk = 2; |
1550 | | |
1551 | | /* Printing bytes in order of increasing addresses makes sense, |
1552 | | especially on a little-endian target. |
1553 | | This is completely the opposite of what you think; setting this to |
1554 | | BFD_ENDIAN_LITTLE will print bytes in order N..0 rather than the 0..N |
1555 | | we want. */ |
1556 | 344k | info->display_endian = BFD_ENDIAN_BIG; |
1557 | | |
1558 | 344k | return advance; |
1559 | 344k | } |
1560 | | |
1561 | | /* Disassemble, prefixing register names with `$'. CRIS v0..v10. */ |
1562 | | |
1563 | | static int |
1564 | | print_insn_cris_with_register_prefix (bfd_vma vma, |
1565 | | disassemble_info *info) |
1566 | 344k | { |
1567 | 344k | if (info->private_data == NULL |
1568 | 344k | && !cris_parse_disassembler_options (info, cris_dis_v0_v10)) |
1569 | 0 | return -1; |
1570 | 344k | return print_insn_cris_generic (vma, info, true); |
1571 | 344k | } |
1572 | | |
1573 | | /* Disassemble, prefixing register names with `$'. CRIS v32. */ |
1574 | | |
1575 | | static int |
1576 | | print_insn_crisv32_with_register_prefix (bfd_vma vma, |
1577 | | disassemble_info *info) |
1578 | 0 | { |
1579 | 0 | if (info->private_data == NULL |
1580 | 0 | && !cris_parse_disassembler_options (info, cris_dis_v32)) |
1581 | 0 | return -1; |
1582 | 0 | return print_insn_cris_generic (vma, info, true); |
1583 | 0 | } |
1584 | | |
1585 | | /* Disassemble, prefixing register names with `$'. |
1586 | | Common v10 and v32 subset. */ |
1587 | | |
1588 | | static int |
1589 | | print_insn_crisv10_v32_with_register_prefix (bfd_vma vma, |
1590 | | disassemble_info *info) |
1591 | 0 | { |
1592 | 0 | if (info->private_data == NULL |
1593 | 0 | && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32)) |
1594 | 0 | return -1; |
1595 | 0 | return print_insn_cris_generic (vma, info, true); |
1596 | 0 | } |
1597 | | |
1598 | | /* Disassemble, no prefixes on register names. CRIS v0..v10. */ |
1599 | | |
1600 | | static int |
1601 | | print_insn_cris_without_register_prefix (bfd_vma vma, |
1602 | | disassemble_info *info) |
1603 | 0 | { |
1604 | 0 | if (info->private_data == NULL |
1605 | 0 | && !cris_parse_disassembler_options (info, cris_dis_v0_v10)) |
1606 | 0 | return -1; |
1607 | 0 | return print_insn_cris_generic (vma, info, false); |
1608 | 0 | } |
1609 | | |
1610 | | /* Disassemble, no prefixes on register names. CRIS v32. */ |
1611 | | |
1612 | | static int |
1613 | | print_insn_crisv32_without_register_prefix (bfd_vma vma, |
1614 | | disassemble_info *info) |
1615 | 0 | { |
1616 | 0 | if (info->private_data == NULL |
1617 | 0 | && !cris_parse_disassembler_options (info, cris_dis_v32)) |
1618 | 0 | return -1; |
1619 | 0 | return print_insn_cris_generic (vma, info, false); |
1620 | 0 | } |
1621 | | |
1622 | | /* Disassemble, no prefixes on register names. |
1623 | | Common v10 and v32 subset. */ |
1624 | | |
1625 | | static int |
1626 | | print_insn_crisv10_v32_without_register_prefix (bfd_vma vma, |
1627 | | disassemble_info *info) |
1628 | 0 | { |
1629 | 0 | if (info->private_data == NULL |
1630 | 0 | && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32)) |
1631 | 0 | return -1; |
1632 | 0 | return print_insn_cris_generic (vma, info, false); |
1633 | 0 | } |
1634 | | |
1635 | | /* Return a disassembler-function that prints registers with a `$' prefix, |
1636 | | or one that prints registers without a prefix. |
1637 | | FIXME: We should improve the solution to avoid the multitude of |
1638 | | functions seen above. */ |
1639 | | |
1640 | | disassembler_ftype |
1641 | | cris_get_disassembler (bfd *abfd) |
1642 | 684 | { |
1643 | | /* If there's no bfd in sight, we return what is valid as input in all |
1644 | | contexts if fed back to the assembler: disassembly *with* register |
1645 | | prefix. Unfortunately this will be totally wrong for v32. */ |
1646 | 684 | if (abfd == NULL) |
1647 | 684 | return print_insn_cris_with_register_prefix; |
1648 | | |
1649 | 0 | if (bfd_get_symbol_leading_char (abfd) == 0) |
1650 | 0 | { |
1651 | 0 | if (bfd_get_mach (abfd) == bfd_mach_cris_v32) |
1652 | 0 | return print_insn_crisv32_with_register_prefix; |
1653 | 0 | if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32) |
1654 | 0 | return print_insn_crisv10_v32_with_register_prefix; |
1655 | | |
1656 | | /* We default to v10. This may be specifically specified in the |
1657 | | bfd mach, but is also the default setting. */ |
1658 | 0 | return print_insn_cris_with_register_prefix; |
1659 | 0 | } |
1660 | | |
1661 | 0 | if (bfd_get_mach (abfd) == bfd_mach_cris_v32) |
1662 | 0 | return print_insn_crisv32_without_register_prefix; |
1663 | 0 | if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32) |
1664 | 0 | return print_insn_crisv10_v32_without_register_prefix; |
1665 | 0 | return print_insn_cris_without_register_prefix; |
1666 | 0 | } |
1667 | | |
1668 | | /* Local variables: |
1669 | | eval: (c-set-style "gnu") |
1670 | | indent-tabs-mode: t |
1671 | | End: */ |