gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / v850-dis.c
CommitLineData
252b5132 1/* Disassemble V850 instructions.
b3adc24a 2 Copyright (C) 1996-2020 Free Software Foundation, Inc.
252b5132 3
9b201bb5
NC
4 This file is part of the GNU opcodes library.
5
6 This library is free software; you can redistribute it and/or modify
8ad30312 7 it under the terms of the GNU General Public License as published by
9b201bb5
NC
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
252b5132 10
9b201bb5
NC
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
252b5132 15
8ad30312
NC
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
47b0e7ad
NC
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
252b5132
RH
20
21
0d8dfecf 22#include "sysdep.h"
df7b86aa 23#include <stdio.h>
78c8d46c 24#include <string.h>
47b0e7ad 25#include "opcode/v850.h"
88c1242d 26#include "disassemble.h"
252b5132 27#include "opintl.h"
5103274f 28#include "libiberty.h"
78c8d46c 29
7903e530 30static const int v850_cacheop_codes[] =
78c8d46c
NC
31{
32 0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06,
33 0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1
34};
35
7903e530 36static const int v850_prefop_codes[] =
78c8d46c
NC
37{ 0x00, 0x04, -1};
38
1cd986c5 39static void
78c8d46c
NC
40print_value (int flags,
41 bfd_vma memaddr,
42 struct disassemble_info *info,
43 long value)
1cd986c5
NC
44{
45 if (flags & V850_PCREL)
46 {
47 bfd_vma addr = value + memaddr;
41702d50
NC
48
49 if (flags & V850_INVERSE_PCREL)
50 addr = memaddr - value;
1cd986c5
NC
51 info->print_address_func (addr, info);
52 }
53 else if (flags & V850_OPERAND_DISP)
54 {
55 if (flags & V850_OPERAND_SIGNED)
56 {
57 info->fprintf_func (info->stream, "%ld", value);
58 }
59 else
60 {
61 info->fprintf_func (info->stream, "%lu", value);
62 }
63 }
78c8d46c
NC
64 else if ((flags & V850E_IMMEDIATE32)
65 || (flags & V850E_IMMEDIATE16HI))
1cd986c5
NC
66 {
67 info->fprintf_func (info->stream, "0x%lx", value);
68 }
69 else
70 {
71 if (flags & V850_OPERAND_SIGNED)
72 {
73 info->fprintf_func (info->stream, "%ld", value);
74 }
75 else
76 {
77 info->fprintf_func (info->stream, "%lu", value);
78 }
79 }
80}
47b0e7ad 81
1cd986c5
NC
82static long
83get_operand_value (const struct v850_operand *operand,
84 unsigned long insn,
85 int bytes_read,
86 bfd_vma memaddr,
87 struct disassemble_info * info,
88 bfd_boolean noerror,
89 int *invalid)
90{
2a81ccbb 91 unsigned long value;
1cd986c5
NC
92 bfd_byte buffer[4];
93
94 if ((operand->flags & V850E_IMMEDIATE16)
95 || (operand->flags & V850E_IMMEDIATE16HI))
96 {
97 int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
98
99 if (status == 0)
100 {
101 value = bfd_getl16 (buffer);
102
103 if (operand->flags & V850E_IMMEDIATE16HI)
104 value <<= 16;
dd42f060 105 else if (value & 0x8000)
b6518b38 106 value |= (-1UL << 16);
1cd986c5
NC
107
108 return value;
109 }
110
111 if (!noerror)
112 info->memory_error_func (status, memaddr + bytes_read, info);
113
114 return 0;
115 }
116
117 if (operand->flags & V850E_IMMEDIATE23)
118 {
119 int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
120
121 if (status == 0)
122 {
123 value = bfd_getl32 (buffer);
124
125 value = (operand->extract) (value, invalid);
126
127 return value;
128 }
129
130 if (!noerror)
131 info->memory_error_func (status, memaddr + bytes_read, info);
132
133 return 0;
134 }
135
136 if (operand->flags & V850E_IMMEDIATE32)
137 {
138 int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
139
140 if (status == 0)
141 {
142 bytes_read += 4;
143 value = bfd_getl32 (buffer);
144
145 return value;
146 }
147
148 if (!noerror)
149 info->memory_error_func (status, memaddr + bytes_read, info);
150
151 return 0;
152 }
153
154 if (operand->extract)
155 value = (operand->extract) (insn, invalid);
156 else
157 {
158 if (operand->bits == -1)
159 value = (insn & operand->shift);
160 else
2a81ccbb 161 value = (insn >> operand->shift) & ((1ul << operand->bits) - 1);
1cd986c5
NC
162
163 if (operand->flags & V850_OPERAND_SIGNED)
2a81ccbb
AM
164 {
165 unsigned long sign = 1ul << (operand->bits - 1);
166 value = (value ^ sign) - sign;
167 }
1cd986c5
NC
168 }
169
170 return value;
171}
172
5103274f
NC
173static const char *
174get_v850_sreg_name (unsigned int reg)
175{
176 static const char *const v850_sreg_names[] =
177 {
178 "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
179 "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
180 "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
181 "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
182 "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
183 "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
184 "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
185 "fewr", "dbwr", "bsel"
186 };
187
188 if (reg < ARRAY_SIZE (v850_sreg_names))
189 return v850_sreg_names[reg];
190 return _("<invalid s-reg number>");
191}
192
193static const char *
194get_v850_reg_name (unsigned int reg)
195{
196 static const char *const v850_reg_names[] =
197 {
198 "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
199 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
200 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
201 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
202 };
203
204 if (reg < ARRAY_SIZE (v850_reg_names))
205 return v850_reg_names[reg];
206 return _("<invalid reg number>");
207}
208
209static const char *
210get_v850_vreg_name (unsigned int reg)
211{
212 static const char *const v850_vreg_names[] =
213 {
214 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9",
215 "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18",
216 "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27",
217 "vr28", "vr29", "vr30", "vr31"
218 };
219
220 if (reg < ARRAY_SIZE (v850_vreg_names))
221 return v850_vreg_names[reg];
222 return _("<invalid v-reg number>");
223}
224
225static const char *
226get_v850_cc_name (unsigned int reg)
227{
228 static const char *const v850_cc_names[] =
229 {
230 "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
231 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
232 };
233
234 if (reg < ARRAY_SIZE (v850_cc_names))
235 return v850_cc_names[reg];
236 return _("<invalid CC-reg number>");
237}
238
239static const char *
240get_v850_float_cc_name (unsigned int reg)
241{
242 static const char *const v850_float_cc_names[] =
243 {
244 "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
245 "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
246 };
247
248 if (reg < ARRAY_SIZE (v850_float_cc_names))
249 return v850_float_cc_names[reg];
250 return _("<invalid float-CC-reg number>");
251}
252
253static const char *
254get_v850_cacheop_name (unsigned int reg)
255{
256 static const char *const v850_cacheop_names[] =
257 {
258 "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd",
259 "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd"
260 };
261
262 if (reg < ARRAY_SIZE (v850_cacheop_names))
263 return v850_cacheop_names[reg];
264 return _("<invalid cacheop number>");
265}
266
267static const char *
268get_v850_prefop_name (unsigned int reg)
269{
270 static const char *const v850_prefop_names[] =
271 { "prefi", "prefd" };
272
273 if (reg < ARRAY_SIZE (v850_prefop_names))
274 return v850_prefop_names[reg];
275 return _("<invalid prefop number>");
276}
1cd986c5
NC
277
278static int
78c8d46c
NC
279disassemble (bfd_vma memaddr,
280 struct disassemble_info *info,
281 int bytes_read,
282 unsigned long insn)
1cd986c5 283{
78c8d46c 284 struct v850_opcode *op = (struct v850_opcode *) v850_opcodes;
1cd986c5
NC
285 const struct v850_operand *operand;
286 int match = 0;
287 int target_processor;
252b5132
RH
288
289 switch (info->mach)
290 {
291 case 0:
292 default:
293 target_processor = PROCESSOR_V850;
294 break;
295
296 case bfd_mach_v850e:
297 target_processor = PROCESSOR_V850E;
298 break;
8ad30312
NC
299
300 case bfd_mach_v850e1:
1cd986c5
NC
301 target_processor = PROCESSOR_V850E;
302 break;
303
304 case bfd_mach_v850e2:
305 target_processor = PROCESSOR_V850E2;
306 break;
307
308 case bfd_mach_v850e2v3:
309 target_processor = PROCESSOR_V850E2V3;
8ad30312 310 break;
78c8d46c
NC
311
312 case bfd_mach_v850e3v5:
313 target_processor = PROCESSOR_V850E3V5;
314 break;
252b5132 315 }
47b0e7ad 316
1cd986c5
NC
317 /* If this is a two byte insn, then mask off the high bits. */
318 if (bytes_read == 2)
319 insn &= 0xffff;
320
252b5132
RH
321 /* Find the opcode. */
322 while (op->name)
323 {
324 if ((op->mask & insn) == op->opcode
1cd986c5
NC
325 && (op->processors & target_processor)
326 && !(op->processors & PROCESSOR_OPTION_ALIAS))
252b5132 327 {
1cd986c5 328 /* Code check start. */
b34976b6
AM
329 const unsigned char *opindex_ptr;
330 unsigned int opnum;
331 unsigned int memop;
252b5132 332
1cd986c5
NC
333 for (opindex_ptr = op->operands, opnum = 1;
334 *opindex_ptr != 0;
335 opindex_ptr++, opnum++)
336 {
337 int invalid = 0;
338 long value;
339
340 operand = &v850_operands[*opindex_ptr];
341
78c8d46c
NC
342 value = get_operand_value (operand, insn, bytes_read, memaddr,
343 info, 1, &invalid);
1cd986c5
NC
344
345 if (invalid)
346 goto next_opcode;
347
348 if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
349 goto next_opcode;
350
351 if ((operand->flags & V850_NOT_SA) && value == 0xd)
352 goto next_opcode;
353
354 if ((operand->flags & V850_NOT_IMM0) && value == 0)
355 goto next_opcode;
356 }
357
358 /* Code check end. */
359
252b5132
RH
360 match = 1;
361 (*info->fprintf_func) (info->stream, "%s\t", op->name);
1cd986c5
NC
362#if 0
363 fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
364 insn, op->mask, op->opcode, op->name );
365#endif
252b5132
RH
366
367 memop = op->memop;
368 /* Now print the operands.
369
370 MEMOP is the operand number at which a memory
371 address specification starts, or zero if this
372 instruction has no memory addresses.
373
374 A memory address is always two arguments.
375
376 This information allows us to determine when to
377 insert commas into the output stream as well as
378 when to insert disp[reg] expressions onto the
379 output stream. */
47b0e7ad 380
252b5132
RH
381 for (opindex_ptr = op->operands, opnum = 1;
382 *opindex_ptr != 0;
383 opindex_ptr++, opnum++)
384 {
7d063384 385 bfd_boolean square = FALSE;
b34976b6
AM
386 long value;
387 int flag;
1cd986c5 388 char *prefix;
47b0e7ad 389
252b5132 390 operand = &v850_operands[*opindex_ptr];
47b0e7ad 391
78c8d46c
NC
392 value = get_operand_value (operand, insn, bytes_read, memaddr,
393 info, 0, 0);
252b5132
RH
394
395 /* The first operand is always output without any
396 special handling.
397
398 For the following arguments:
399
400 If memop && opnum == memop + 1, then we need '[' since
401 we're about to output the register used in a memory
402 reference.
403
404 If memop && opnum == memop + 2, then we need ']' since
405 we just finished the register in a memory reference. We
406 also need a ',' before this operand.
407
408 Else we just need a comma.
409
410 We may need to output a trailing ']' if the last operand
47b0e7ad 411 in an instruction is the register for a memory address.
252b5132 412
04ee5257 413 The exception (and there's always an exception) are the
252b5132 414 "jmp" insn which needs square brackets around it's only
04ee5257
NC
415 register argument, and the clr1/not1/set1/tst1 insns
416 which [...] around their second register argument. */
417
1cd986c5
NC
418 prefix = "";
419 if (operand->flags & V850_OPERAND_BANG)
420 {
421 prefix = "!";
422 }
423 else if (operand->flags & V850_OPERAND_PERCENT)
424 {
425 prefix = "%";
426 }
252b5132 427
1cd986c5 428 if (opnum == 1 && opnum == memop)
7d063384
NC
429 {
430 info->fprintf_func (info->stream, "%s[", prefix);
431 square = TRUE;
432 }
78c8d46c
NC
433 else if ( (strcmp ("stc.w", op->name) == 0
434 || strcmp ("cache", op->name) == 0
435 || strcmp ("pref", op->name) == 0)
436 && opnum == 2 && opnum == memop)
437 {
438 info->fprintf_func (info->stream, ", [");
439 square = TRUE;
440 }
441 else if ( (strcmp (op->name, "pushsp") == 0
442 || strcmp (op->name, "popsp") == 0
443 || strcmp (op->name, "dbpush" ) == 0)
444 && opnum == 2)
445 {
446 info->fprintf_func (info->stream, "-");
447 }
1cd986c5 448 else if (opnum > 1
78c8d46c
NC
449 && (v850_operands[*(opindex_ptr - 1)].flags
450 & V850_OPERAND_DISP) != 0
1cd986c5 451 && opnum == memop)
7d063384
NC
452 {
453 info->fprintf_func (info->stream, "%s[", prefix);
454 square = TRUE;
455 }
04ee5257
NC
456 else if (opnum == 2
457 && ( op->opcode == 0x00e407e0 /* clr1 */
458 || op->opcode == 0x00e207e0 /* not1 */
459 || op->opcode == 0x00e007e0 /* set1 */
460 || op->opcode == 0x00e607e0 /* tst1 */
461 ))
462 {
463 info->fprintf_func (info->stream, ", %s[", prefix);
464 square = TRUE;
7903e530 465 }
1cd986c5
NC
466 else if (opnum > 1)
467 info->fprintf_func (info->stream, ", %s", prefix);
468
78c8d46c
NC
469 /* Extract the flags, ignoring ones which do not
470 effect disassembly output. */
1cd986c5
NC
471 flag = operand->flags & (V850_OPERAND_REG
472 | V850_REG_EVEN
473 | V850_OPERAND_EP
474 | V850_OPERAND_SRG
475 | V850E_OPERAND_REG_LIST
476 | V850_OPERAND_CC
78c8d46c
NC
477 | V850_OPERAND_VREG
478 | V850_OPERAND_CACHEOP
479 | V850_OPERAND_PREFOP
1cd986c5 480 | V850_OPERAND_FLOAT_CC);
47b0e7ad 481
252b5132
RH
482 switch (flag)
483 {
78c8d46c 484 case V850_OPERAND_REG:
5103274f 485 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value));
78c8d46c
NC
486 break;
487 case (V850_OPERAND_REG|V850_REG_EVEN):
5103274f 488 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2));
78c8d46c
NC
489 break;
490 case V850_OPERAND_EP:
491 info->fprintf_func (info->stream, "ep");
492 break;
493 case V850_OPERAND_SRG:
5103274f 494 info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value));
78c8d46c 495 break;
1cd986c5 496 case V850E_OPERAND_REG_LIST:
252b5132 497 {
1cd986c5
NC
498 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
499 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
b34976b6
AM
500 int *regs;
501 int i;
6c2ca6c2 502 unsigned int mask = 0;
b34976b6 503 int pc = 0;
1cd986c5 504
252b5132
RH
505 switch (operand->shift)
506 {
507 case 0xffe00001: regs = list12_regs; break;
252b5132
RH
508 default:
509 /* xgettext:c-format */
a6743a54
AM
510 opcodes_error_handler (_("unknown operand shift: %x"),
511 operand->shift);
47b0e7ad 512 abort ();
252b5132
RH
513 }
514
515 for (i = 0; i < 32; i++)
516 {
6c2ca6c2 517 if (value & (1u << i))
252b5132
RH
518 {
519 switch (regs[ i ])
520 {
a6743a54 521 default:
6c2ca6c2 522 mask |= (1u << regs[ i ]);
a6743a54
AM
523 break;
524 case 0:
252b5132 525 /* xgettext:c-format */
a6743a54
AM
526 opcodes_error_handler (_("unknown reg: %d"), i);
527 abort ();
528 break;
529 case -1:
530 pc = 1;
531 break;
252b5132
RH
532 }
533 }
534 }
535
536 info->fprintf_func (info->stream, "{");
47b0e7ad 537
1cd986c5 538 if (mask || pc)
252b5132
RH
539 {
540 if (mask)
541 {
542 unsigned int bit;
b34976b6 543 int shown_one = 0;
47b0e7ad 544
252b5132 545 for (bit = 0; bit < 32; bit++)
6c2ca6c2 546 if (mask & (1u << bit))
252b5132 547 {
6c2ca6c2
AM
548 unsigned int first = bit;
549 unsigned int last;
252b5132
RH
550
551 if (shown_one)
552 info->fprintf_func (info->stream, ", ");
553 else
b34976b6 554 shown_one = 1;
47b0e7ad 555
5103274f 556 info->fprintf_func (info->stream, "%s", get_v850_reg_name (first));
47b0e7ad 557
252b5132 558 for (bit++; bit < 32; bit++)
6c2ca6c2 559 if ((mask & (1u << bit)) == 0)
252b5132
RH
560 break;
561
562 last = bit;
563
564 if (last > first + 1)
1cd986c5 565 {
5103274f 566 info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1));
1cd986c5 567 }
252b5132
RH
568 }
569 }
47b0e7ad 570
252b5132
RH
571 if (pc)
572 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
252b5132 573 }
47b0e7ad 574
252b5132
RH
575 info->fprintf_func (info->stream, "}");
576 }
252b5132 577 break;
47b0e7ad 578
78c8d46c 579 case V850_OPERAND_CC:
5103274f 580 info->fprintf_func (info->stream, "%s", get_v850_cc_name (value));
78c8d46c
NC
581 break;
582
583 case V850_OPERAND_FLOAT_CC:
5103274f 584 info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value));
78c8d46c
NC
585 break;
586
587 case V850_OPERAND_CACHEOP:
588 {
589 int idx;
590
591 for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
592 {
593 if (value == v850_cacheop_codes[idx])
594 {
595 info->fprintf_func (info->stream, "%s",
5103274f 596 get_v850_cacheop_name (idx));
78c8d46c
NC
597 goto MATCH_CACHEOP_CODE;
598 }
599 }
600 info->fprintf_func (info->stream, "%d", (int) value);
601 }
602 MATCH_CACHEOP_CODE:
603 break;
604
605 case V850_OPERAND_PREFOP:
606 {
607 int idx;
608
609 for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
610 {
611 if (value == v850_prefop_codes[idx])
612 {
613 info->fprintf_func (info->stream, "%s",
5103274f 614 get_v850_prefop_name (idx));
78c8d46c
NC
615 goto MATCH_PREFOP_CODE;
616 }
617 }
618 info->fprintf_func (info->stream, "%d", (int) value);
619 }
620 MATCH_PREFOP_CODE:
621 break;
622
623 case V850_OPERAND_VREG:
5103274f 624 info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value));
78c8d46c 625 break;
1cd986c5
NC
626
627 default:
628 print_value (operand->flags, memaddr, info, value);
252b5132 629 break;
47b0e7ad 630 }
252b5132 631
7d063384 632 if (square)
252b5132
RH
633 (*info->fprintf_func) (info->stream, "]");
634 }
635
252b5132
RH
636 /* All done. */
637 break;
638 }
1cd986c5 639 next_opcode:
252b5132
RH
640 op++;
641 }
642
1cd986c5 643 return match;
252b5132
RH
644}
645
47b0e7ad
NC
646int
647print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
252b5132 648{
1cd986c5
NC
649 int status, status2, match;
650 bfd_byte buffer[8];
651 int length = 0, code_length = 0;
652 unsigned long insn = 0, insn2 = 0;
653 int target_processor;
654
655 switch (info->mach)
656 {
657 case 0:
658 default:
659 target_processor = PROCESSOR_V850;
660 break;
661
662 case bfd_mach_v850e:
663 target_processor = PROCESSOR_V850E;
664 break;
665
666 case bfd_mach_v850e1:
667 target_processor = PROCESSOR_V850E;
668 break;
669
670 case bfd_mach_v850e2:
671 target_processor = PROCESSOR_V850E2;
672 break;
673
674 case bfd_mach_v850e2v3:
675 target_processor = PROCESSOR_V850E2V3;
676 break;
78c8d46c
NC
677
678 case bfd_mach_v850e3v5:
679 target_processor = PROCESSOR_V850E3V5;
680 break;
1cd986c5 681 }
252b5132 682
252b5132 683 status = info->read_memory_func (memaddr, buffer, 2, info);
1cd986c5
NC
684
685 if (status)
686 {
687 info->memory_error_func (status, memaddr, info);
688 return -1;
689 }
690
691 insn = bfd_getl16 (buffer);
692
693 status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
694
695 if (!status2)
252b5132 696 {
1cd986c5
NC
697 insn2 = bfd_getl16 (buffer);
698 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
699 }
47b0e7ad 700
1cd986c5
NC
701 /* Special case. */
702 if (length == 0
78c8d46c 703 && ((target_processor & PROCESSOR_V850E2_UP) != 0))
1cd986c5
NC
704 {
705 if ((insn & 0xffff) == 0x02e0 /* jr 32bit */
706 && !status2 && (insn2 & 0x1) == 0)
707 {
708 length = 2;
709 code_length = 6;
710 }
711 else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */
712 && !status2 && (insn2 & 0x1) == 0)
713 {
714 length = 2;
715 code_length = 6;
716 }
717 else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */
718 && !status2 && (insn2 & 0x1) == 0)
252b5132 719 {
1cd986c5
NC
720 length = 2;
721 code_length = 6;
722 }
723 }
252b5132 724
1cd986c5 725 if (length == 0
78c8d46c
NC
726 && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
727 {
728 if ( ((insn & 0xffe0) == 0x07a0 /* ld.dw 23bit (v850e3v5) */
729 && !status2 && (insn2 & 0x000f) == 0x0009)
730 || ((insn & 0xffe0) == 0x07a0 /* st.dw 23bit (v850e3v5) */
731 && !status2 && (insn2 & 0x000f) == 0x000f))
732 {
733 length = 4;
734 code_length = 6;
735 }
736 }
737
738 if (length == 0
739 && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
1cd986c5
NC
740 {
741 if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */
742 && !status2 && (insn2 & 0x000f) == 0x0005)
743 || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */
744 && !status2 && (insn2 & 0x000f) == 0x0005)
745 || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */
746 && !status2 && (insn2 & 0x000f) == 0x0007)
747 || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */
748 && !status2 && (insn2 & 0x000f) == 0x0007)
749 || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */
750 && !status2 && (insn2 & 0x000f) == 0x0009))
751 {
752 length = 4;
753 code_length = 6;
754 }
755 else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */
756 && !status2 && (insn2 & 0x000f) == 0x000d)
757 || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */
758 && !status2 && (insn2 & 0x000f) == 0x000d)
759 || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */
760 && !status2 && (insn2 & 0x000f) == 0x000f))
761 {
762 length = 4;
763 code_length = 6;
252b5132
RH
764 }
765 }
47b0e7ad 766
1cd986c5
NC
767 if (length == 0
768 && target_processor != PROCESSOR_V850)
252b5132 769 {
1cd986c5
NC
770 if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */
771 {
772 length = 2;
773 code_length = 6;
774 }
775 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */
776 && !status2 && (insn2 & 0x001f) == 0x0013)
777 {
778 length = 4;
779 code_length = 6;
780 }
781 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */
782 && !status2 && (insn2 & 0x001f) == 0x000b)
783 {
784 length = 4;
785 code_length = 6;
786 }
787 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */
788 && !status2 && (insn2 & 0x001f) == 0x001b)
789 {
790 length = 4;
791 code_length = 8;
792 }
793 }
794
795 if (length == 4
796 || (length == 0
797 && (insn & 0x0600) == 0x0600))
798 {
799 /* This is a 4 byte insn. */
800 status = info->read_memory_func (memaddr, buffer, 4, info);
801 if (!status)
802 {
803 insn = bfd_getl32 (buffer);
804
805 if (!length)
806 length = code_length = 4;
807 }
808 }
809
810 if (code_length > length)
811 {
812 status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
813 if (status)
814 length = 0;
815 }
816
817 if (length == 0 && !status)
818 length = code_length = 2;
819
820 if (length == 2)
821 insn &= 0xffff;
822
78c8d46c
NC
823 /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
824 if (length == 0)
825 return -1;
826
1cd986c5
NC
827 match = disassemble (memaddr, info, length, insn);
828
829 if (!match)
830 {
831 int l = 0;
832
833 status = info->read_memory_func (memaddr, buffer, code_length, info);
834
835 while (l < code_length)
836 {
837 if (code_length - l == 2)
838 {
839 insn = bfd_getl16 (buffer + l) & 0xffff;
840 info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
841 l += 2;
842 }
843 else
844 {
845 insn = bfd_getl32 (buffer + l);
846 info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
847 l += 4;
848 }
849 }
252b5132
RH
850 }
851
1cd986c5 852 return code_length;
252b5132 853}
This page took 1.023555 seconds and 4 git commands to generate.