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