[AArch64][PATCH 13/14] Support FP16 Adv.SIMD Shift By Immediate instructions.
[external/binutils.git] / opcodes / v850-dis.c
1 /* Disassemble V850 instructions.
2    Copyright (C) 1996-2015 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 "dis-asm.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                         fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift);
454                         abort ();
455                       }
456
457                     for (i = 0; i < 32; i++)
458                       {
459                         if (value & (1 << i))
460                           {
461                             switch (regs[ i ])
462                               {
463                               default: mask |= (1 << regs[ i ]); break;
464                                 /* xgettext:c-format */
465                               case 0:  fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
466                               case -1: pc = 1; break;
467                               }
468                           }
469                       }
470
471                     info->fprintf_func (info->stream, "{");
472
473                     if (mask || pc)
474                       {
475                         if (mask)
476                           {
477                             unsigned int bit;
478                             int shown_one = 0;
479
480                             for (bit = 0; bit < 32; bit++)
481                               if (mask & (1 << bit))
482                                 {
483                                   unsigned long int first = bit;
484                                   unsigned long int last;
485
486                                   if (shown_one)
487                                     info->fprintf_func (info->stream, ", ");
488                                   else
489                                     shown_one = 1;
490
491                                   info->fprintf_func (info->stream, "%s", v850_reg_names[first]);
492
493                                   for (bit++; bit < 32; bit++)
494                                     if ((mask & (1 << bit)) == 0)
495                                       break;
496
497                                   last = bit;
498
499                                   if (last > first + 1)
500                                     {
501                                       info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
502                                     }
503                                 }
504                           }
505
506                         if (pc)
507                           info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
508                       }
509
510                     info->fprintf_func (info->stream, "}");
511                   }
512                   break;
513
514                 case V850_OPERAND_CC:
515                   info->fprintf_func (info->stream, "%s", v850_cc_names[value]);
516                   break;
517
518                 case V850_OPERAND_FLOAT_CC:
519                   info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]);
520                   break;
521
522                 case V850_OPERAND_CACHEOP:
523                   {
524                     int idx;
525
526                     for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
527                       {
528                         if (value == v850_cacheop_codes[idx])
529                           {
530                             info->fprintf_func (info->stream, "%s",
531                                                 v850_cacheop_names[idx]);
532                             goto MATCH_CACHEOP_CODE;
533                           }
534                       }
535                     info->fprintf_func (info->stream, "%d", (int) value);
536                   }
537                 MATCH_CACHEOP_CODE:
538                   break;
539
540                 case V850_OPERAND_PREFOP:
541                   {
542                     int idx;
543
544                     for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
545                       {
546                         if (value == v850_prefop_codes[idx])
547                           {
548                             info->fprintf_func (info->stream, "%s",
549                               v850_prefop_names[idx]);
550                             goto MATCH_PREFOP_CODE;
551                           }
552                       }
553                     info->fprintf_func (info->stream, "%d", (int) value);
554                   }
555                 MATCH_PREFOP_CODE:
556                   break;
557
558                 case V850_OPERAND_VREG:
559                   info->fprintf_func (info->stream, "%s", v850_vreg_names[value]);
560                   break;
561
562                 default:
563                   print_value (operand->flags, memaddr, info, value);
564                   break;
565                 }
566
567               if (square)
568                 (*info->fprintf_func) (info->stream, "]");
569             }
570
571           /* All done. */
572           break;
573         }
574     next_opcode:
575       op++;
576     }
577
578   return match;
579 }
580
581 int
582 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
583 {
584   int status, status2, match;
585   bfd_byte buffer[8];
586   int length = 0, code_length = 0;
587   unsigned long insn = 0, insn2 = 0;
588   int target_processor;
589
590   switch (info->mach)
591     {
592     case 0:
593     default:
594       target_processor = PROCESSOR_V850;
595       break;
596
597     case bfd_mach_v850e:
598       target_processor = PROCESSOR_V850E;
599       break;
600
601     case bfd_mach_v850e1:
602       target_processor = PROCESSOR_V850E;
603       break;
604
605     case bfd_mach_v850e2:
606       target_processor = PROCESSOR_V850E2;
607       break;
608
609     case bfd_mach_v850e2v3:
610       target_processor = PROCESSOR_V850E2V3;
611       break;
612
613     case bfd_mach_v850e3v5:
614       target_processor = PROCESSOR_V850E3V5;
615       break;
616     }
617
618   status = info->read_memory_func (memaddr, buffer, 2, info);
619
620   if (status)
621     {
622       info->memory_error_func (status, memaddr, info);
623       return -1;
624     }
625
626   insn = bfd_getl16 (buffer);
627
628   status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
629
630   if (!status2)
631     {
632       insn2 = bfd_getl16 (buffer);
633       /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
634     }
635
636   /* Special case.  */
637   if (length == 0
638       && ((target_processor & PROCESSOR_V850E2_UP) != 0))
639     {
640       if ((insn & 0xffff) == 0x02e0             /* jr 32bit */
641           && !status2 && (insn2 & 0x1) == 0)
642         {
643           length = 2;
644           code_length = 6;
645         }
646       else if ((insn & 0xffe0) == 0x02e0        /* jarl 32bit */
647                && !status2 && (insn2 & 0x1) == 0)
648         {
649           length = 2;
650           code_length = 6;
651         }
652       else if ((insn & 0xffe0) == 0x06e0        /* jmp 32bit */
653                && !status2 && (insn2 & 0x1) == 0)
654         {
655           length = 2;
656           code_length = 6;
657         }
658     }
659
660   if (length == 0
661       && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
662     {
663       if (   ((insn & 0xffe0) == 0x07a0         /* ld.dw 23bit (v850e3v5) */
664               && !status2 && (insn2 & 0x000f) == 0x0009)
665           || ((insn & 0xffe0) == 0x07a0         /* st.dw 23bit (v850e3v5) */
666               && !status2 && (insn2 & 0x000f) == 0x000f))
667         {
668           length = 4;
669           code_length = 6;
670         }
671     }
672
673   if (length == 0
674       && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
675     {
676       if (((insn & 0xffe0) == 0x0780            /* ld.b 23bit */
677            && !status2 && (insn2 & 0x000f) == 0x0005)
678           || ((insn & 0xffe0) == 0x07a0         /* ld.bu 23bit */
679               && !status2 && (insn2 & 0x000f) == 0x0005)
680           || ((insn & 0xffe0) == 0x0780         /* ld.h 23bit */
681               && !status2 && (insn2 & 0x000f) == 0x0007)
682           || ((insn & 0xffe0) == 0x07a0         /* ld.hu 23bit */
683               && !status2 && (insn2 & 0x000f) == 0x0007)
684           || ((insn & 0xffe0) == 0x0780         /* ld.w 23bit */
685               && !status2 && (insn2 & 0x000f) == 0x0009))
686         {
687           length = 4;
688           code_length = 6;
689         }
690       else if (((insn & 0xffe0) == 0x0780       /* st.b 23bit */
691                && !status2 && (insn2 & 0x000f) == 0x000d)
692               || ((insn & 0xffe0) == 0x07a0     /* st.h 23bit */
693                   && !status2 && (insn2 & 0x000f) == 0x000d)
694               || ((insn & 0xffe0) == 0x0780     /* st.w 23bit */
695                   && !status2 && (insn2 & 0x000f) == 0x000f))
696         {
697           length = 4;
698           code_length = 6;
699         }
700     }
701
702   if (length == 0
703       && target_processor != PROCESSOR_V850)
704     {
705       if ((insn & 0xffe0) == 0x0620)            /* 32 bit MOV */
706         {
707           length = 2;
708           code_length = 6;
709         }
710       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16<<16 */
711                && !status2 && (insn2 & 0x001f) == 0x0013)
712         {
713           length = 4;
714           code_length = 6;
715         }
716       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16 */
717                && !status2 && (insn2 & 0x001f) == 0x000b)
718         {
719           length = 4;
720           code_length = 6;
721         }
722       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm32 */
723                && !status2 && (insn2 & 0x001f) == 0x001b)
724         {
725           length = 4;
726           code_length = 8;
727         }
728     }
729
730   if (length == 4
731       || (length == 0
732           && (insn & 0x0600) == 0x0600))
733     {
734       /* This is a 4 byte insn.  */
735       status = info->read_memory_func (memaddr, buffer, 4, info);
736       if (!status)
737         {
738           insn = bfd_getl32 (buffer);
739
740           if (!length)
741             length = code_length = 4;
742         }
743     }
744
745   if (code_length > length)
746     {
747       status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
748       if (status)
749         length = 0;
750     }
751
752   if (length == 0 && !status)
753     length = code_length = 2;
754
755   if (length == 2)
756     insn &= 0xffff;
757
758   /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
759   if (length == 0)
760     return -1;
761
762   match = disassemble (memaddr, info, length, insn);
763
764   if (!match)
765     {
766       int l = 0;
767
768       status = info->read_memory_func (memaddr, buffer, code_length, info);
769
770       while (l < code_length)
771         {
772           if (code_length - l == 2)
773             {
774               insn = bfd_getl16 (buffer + l) & 0xffff;
775               info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
776               l += 2;
777             }
778           else
779             {
780               insn = bfd_getl32 (buffer + l);
781               info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
782               l += 4;
783             }
784         }
785     }
786
787   return code_length;
788 }