]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/v850-dis.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / opcodes / v850-dis.c
1 /* Disassemble V850 instructions.
2 Copyright (C) 1996-2020 Free Software Foundation, Inc.
3
4 This file is part of the GNU opcodes library.
5
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
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.
15
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
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21
22 #include "sysdep.h"
23 #include <stdio.h>
24 #include <string.h>
25 #include "opcode/v850.h"
26 #include "disassemble.h"
27 #include "opintl.h"
28 #include "libiberty.h"
29
30 static const int v850_cacheop_codes[] =
31 {
32 0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06,
33 0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1
34 };
35
36 static const int v850_prefop_codes[] =
37 { 0x00, 0x04, -1};
38
39 static void
40 print_value (int flags,
41 bfd_vma memaddr,
42 struct disassemble_info *info,
43 long value)
44 {
45 if (flags & V850_PCREL)
46 {
47 bfd_vma addr = value + memaddr;
48
49 if (flags & V850_INVERSE_PCREL)
50 addr = memaddr - value;
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 }
64 else if ((flags & V850E_IMMEDIATE32)
65 || (flags & V850E_IMMEDIATE16HI))
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 }
81
82 static long
83 get_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 unsigned 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;
105 else if (value & 0x8000)
106 value |= (-1UL << 16);
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) & ((1ul << operand->bits) - 1);
162
163 if (operand->flags & V850_OPERAND_SIGNED)
164 {
165 unsigned long sign = 1ul << (operand->bits - 1);
166 value = (value ^ sign) - sign;
167 }
168 }
169
170 return value;
171 }
172
173 static const char *
174 get_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
193 static const char *
194 get_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
209 static const char *
210 get_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
225 static const char *
226 get_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
239 static const char *
240 get_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
253 static const char *
254 get_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
267 static const char *
268 get_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 }
277
278 static int
279 disassemble (bfd_vma memaddr,
280 struct disassemble_info *info,
281 int bytes_read,
282 unsigned long insn)
283 {
284 struct v850_opcode *op = (struct v850_opcode *) v850_opcodes;
285 const struct v850_operand *operand;
286 int match = 0;
287 int target_processor;
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;
299
300 case bfd_mach_v850e1:
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;
310 break;
311
312 case bfd_mach_v850e3v5:
313 target_processor = PROCESSOR_V850E3V5;
314 break;
315 }
316
317 /* If this is a two byte insn, then mask off the high bits. */
318 if (bytes_read == 2)
319 insn &= 0xffff;
320
321 /* Find the opcode. */
322 while (op->name)
323 {
324 if ((op->mask & insn) == op->opcode
325 && (op->processors & target_processor)
326 && !(op->processors & PROCESSOR_OPTION_ALIAS))
327 {
328 /* Code check start. */
329 const unsigned char *opindex_ptr;
330 unsigned int opnum;
331 unsigned int memop;
332
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
342 value = get_operand_value (operand, insn, bytes_read, memaddr,
343 info, 1, &invalid);
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
360 match = 1;
361 (*info->fprintf_func) (info->stream, "%s\t", op->name);
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
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. */
380
381 for (opindex_ptr = op->operands, opnum = 1;
382 *opindex_ptr != 0;
383 opindex_ptr++, opnum++)
384 {
385 bfd_boolean square = FALSE;
386 long value;
387 int flag;
388 char *prefix;
389
390 operand = &v850_operands[*opindex_ptr];
391
392 value = get_operand_value (operand, insn, bytes_read, memaddr,
393 info, 0, 0);
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
411 in an instruction is the register for a memory address.
412
413 The exception (and there's always an exception) are the
414 "jmp" insn which needs square brackets around it's only
415 register argument, and the clr1/not1/set1/tst1 insns
416 which [...] around their second register argument. */
417
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 }
427
428 if (opnum == 1 && opnum == memop)
429 {
430 info->fprintf_func (info->stream, "%s[", prefix);
431 square = TRUE;
432 }
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 }
448 else if (opnum > 1
449 && (v850_operands[*(opindex_ptr - 1)].flags
450 & V850_OPERAND_DISP) != 0
451 && opnum == memop)
452 {
453 info->fprintf_func (info->stream, "%s[", prefix);
454 square = TRUE;
455 }
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;
465 }
466 else if (opnum > 1)
467 info->fprintf_func (info->stream, ", %s", prefix);
468
469 /* Extract the flags, ignoring ones which do not
470 effect disassembly output. */
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
477 | V850_OPERAND_VREG
478 | V850_OPERAND_CACHEOP
479 | V850_OPERAND_PREFOP
480 | V850_OPERAND_FLOAT_CC);
481
482 switch (flag)
483 {
484 case V850_OPERAND_REG:
485 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value));
486 break;
487 case (V850_OPERAND_REG|V850_REG_EVEN):
488 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2));
489 break;
490 case V850_OPERAND_EP:
491 info->fprintf_func (info->stream, "ep");
492 break;
493 case V850_OPERAND_SRG:
494 info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value));
495 break;
496 case V850E_OPERAND_REG_LIST:
497 {
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 };
500 int *regs;
501 int i;
502 unsigned int mask = 0;
503 int pc = 0;
504
505 switch (operand->shift)
506 {
507 case 0xffe00001: regs = list12_regs; break;
508 default:
509 /* xgettext:c-format */
510 opcodes_error_handler (_("unknown operand shift: %x"),
511 operand->shift);
512 abort ();
513 }
514
515 for (i = 0; i < 32; i++)
516 {
517 if (value & (1u << i))
518 {
519 switch (regs[ i ])
520 {
521 default:
522 mask |= (1u << regs[ i ]);
523 break;
524 case 0:
525 /* xgettext:c-format */
526 opcodes_error_handler (_("unknown reg: %d"), i);
527 abort ();
528 break;
529 case -1:
530 pc = 1;
531 break;
532 }
533 }
534 }
535
536 info->fprintf_func (info->stream, "{");
537
538 if (mask || pc)
539 {
540 if (mask)
541 {
542 unsigned int bit;
543 int shown_one = 0;
544
545 for (bit = 0; bit < 32; bit++)
546 if (mask & (1u << bit))
547 {
548 unsigned int first = bit;
549 unsigned int last;
550
551 if (shown_one)
552 info->fprintf_func (info->stream, ", ");
553 else
554 shown_one = 1;
555
556 info->fprintf_func (info->stream, "%s", get_v850_reg_name (first));
557
558 for (bit++; bit < 32; bit++)
559 if ((mask & (1u << bit)) == 0)
560 break;
561
562 last = bit;
563
564 if (last > first + 1)
565 {
566 info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1));
567 }
568 }
569 }
570
571 if (pc)
572 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
573 }
574
575 info->fprintf_func (info->stream, "}");
576 }
577 break;
578
579 case V850_OPERAND_CC:
580 info->fprintf_func (info->stream, "%s", get_v850_cc_name (value));
581 break;
582
583 case V850_OPERAND_FLOAT_CC:
584 info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value));
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",
596 get_v850_cacheop_name (idx));
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",
614 get_v850_prefop_name (idx));
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:
624 info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value));
625 break;
626
627 default:
628 print_value (operand->flags, memaddr, info, value);
629 break;
630 }
631
632 if (square)
633 (*info->fprintf_func) (info->stream, "]");
634 }
635
636 /* All done. */
637 break;
638 }
639 next_opcode:
640 op++;
641 }
642
643 return match;
644 }
645
646 int
647 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
648 {
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;
677
678 case bfd_mach_v850e3v5:
679 target_processor = PROCESSOR_V850E3V5;
680 break;
681 }
682
683 status = info->read_memory_func (memaddr, buffer, 2, info);
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)
696 {
697 insn2 = bfd_getl16 (buffer);
698 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
699 }
700
701 /* Special case. */
702 if (length == 0
703 && ((target_processor & PROCESSOR_V850E2_UP) != 0))
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)
719 {
720 length = 2;
721 code_length = 6;
722 }
723 }
724
725 if (length == 0
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))
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;
764 }
765 }
766
767 if (length == 0
768 && target_processor != PROCESSOR_V850)
769 {
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
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
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 }
850 }
851
852 return code_length;
853 }