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