]> Git Repo - binutils.git/blob - opcodes/v850-dis.c
PR exp/13206:
[binutils.git] / opcodes / v850-dis.c
1 /* Disassemble V850 instructions.
2    Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010,
3    2012  Free Software Foundation, Inc.
4
5    This file is part of the GNU opcodes library.
6
7    This library is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11
12    It is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21
22
23 #include "sysdep.h"
24 #include <stdio.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 void
63 print_value (int flags, bfd_vma memaddr, struct disassemble_info *info, long value)
64 {
65   if (flags & V850_PCREL)
66     {
67       bfd_vma addr = value + memaddr;
68       info->print_address_func (addr, info);
69     }
70   else if (flags & V850_OPERAND_DISP)
71     {
72       if (flags & V850_OPERAND_SIGNED)
73         {
74           info->fprintf_func (info->stream, "%ld", value);
75         }
76       else
77         {
78           info->fprintf_func (info->stream, "%lu", value);
79         }
80     }
81   else if (flags & V850E_IMMEDIATE32)
82     {
83       info->fprintf_func (info->stream, "0x%lx", value);
84     }
85   else
86     {
87       if (flags & V850_OPERAND_SIGNED)
88         {
89           info->fprintf_func (info->stream, "%ld", value);
90         }
91       else
92         {
93           info->fprintf_func (info->stream, "%lu", value);
94         }
95     }
96 }
97
98 static long
99 get_operand_value (const struct v850_operand *operand,
100                    unsigned long insn,
101                    int bytes_read,
102                    bfd_vma memaddr,
103                    struct disassemble_info * info,
104                    bfd_boolean noerror,
105                    int *invalid)
106 {
107   long value;
108   bfd_byte buffer[4];
109
110   if ((operand->flags & V850E_IMMEDIATE16)
111       || (operand->flags & V850E_IMMEDIATE16HI))
112     {
113       int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
114
115       if (status == 0)
116         {
117           value = bfd_getl16 (buffer);
118
119           if (operand->flags & V850E_IMMEDIATE16HI)
120             value <<= 16;
121
122           return value;
123         }
124
125       if (!noerror)
126         info->memory_error_func (status, memaddr + bytes_read, info);
127
128       return 0;
129     }
130
131   if (operand->flags & V850E_IMMEDIATE23)
132     {
133       int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
134
135       if (status == 0)
136         {
137           value = bfd_getl32 (buffer);
138
139           value = (operand->extract) (value, invalid);
140
141           return value;
142         }
143
144       if (!noerror)
145         info->memory_error_func (status, memaddr + bytes_read, info);
146
147       return 0;
148     }
149
150   if (operand->flags & V850E_IMMEDIATE32)
151     {
152       int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
153
154       if (status == 0)
155         {
156           bytes_read += 4;
157           value = bfd_getl32 (buffer);
158
159           return value;
160         }
161
162       if (!noerror)
163         info->memory_error_func (status, memaddr + bytes_read, info);
164
165       return 0;
166     }
167
168   if (operand->extract)
169     value = (operand->extract) (insn, invalid);
170   else
171     {
172       if (operand->bits == -1)
173         value = (insn & operand->shift);
174       else
175         value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
176
177       if (operand->flags & V850_OPERAND_SIGNED)
178         value = ((long)(value << (sizeof (long)*8 - operand->bits))
179                  >> (sizeof (long)*8 - operand->bits));
180     }
181
182   return value;
183 }
184
185
186 static int
187 disassemble (bfd_vma memaddr, struct disassemble_info *info, int bytes_read, unsigned long insn)
188 {
189   struct v850_opcode *op = (struct v850_opcode *)v850_opcodes;
190   const struct v850_operand *operand;
191   int match = 0;
192   int target_processor;
193
194   switch (info->mach)
195     {
196     case 0:
197     default:
198       target_processor = PROCESSOR_V850;
199       break;
200
201     case bfd_mach_v850e:
202       target_processor = PROCESSOR_V850E;
203       break;
204
205     case bfd_mach_v850e1:
206       target_processor = PROCESSOR_V850E;
207       break;
208
209     case bfd_mach_v850e2:
210       target_processor = PROCESSOR_V850E2;
211       break;
212
213     case bfd_mach_v850e2v3:
214       target_processor = PROCESSOR_V850E2V3;
215       break;
216     }
217
218   /* If this is a two byte insn, then mask off the high bits.  */
219   if (bytes_read == 2)
220     insn &= 0xffff;
221
222   /* Find the opcode.  */
223   while (op->name)
224     {
225       if ((op->mask & insn) == op->opcode
226           && (op->processors & target_processor)
227           && !(op->processors & PROCESSOR_OPTION_ALIAS))
228         {
229           /* Code check start.  */
230           const unsigned char *opindex_ptr;
231           unsigned int opnum;
232           unsigned int memop;
233
234           for (opindex_ptr = op->operands, opnum = 1;
235                *opindex_ptr != 0;
236                opindex_ptr++, opnum++)
237             {
238               int invalid = 0;
239               long value;
240
241               operand = &v850_operands[*opindex_ptr];
242
243               value = get_operand_value (operand, insn, bytes_read, memaddr, info, 1, &invalid);
244
245               if (invalid)
246                 goto next_opcode;
247
248               if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
249                 goto next_opcode;
250
251               if ((operand->flags & V850_NOT_SA) && value == 0xd)
252                 goto next_opcode;
253
254               if ((operand->flags & V850_NOT_IMM0) && value == 0)
255                 goto next_opcode;
256             }
257
258           /* Code check end.  */
259
260           match = 1;
261           (*info->fprintf_func) (info->stream, "%s\t", op->name);
262 #if 0
263           fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
264                    insn, op->mask, op->opcode, op->name );
265 #endif
266
267           memop = op->memop;
268           /* Now print the operands.
269
270              MEMOP is the operand number at which a memory
271              address specification starts, or zero if this
272              instruction has no memory addresses.
273
274              A memory address is always two arguments.
275
276              This information allows us to determine when to
277              insert commas into the output stream as well as
278              when to insert disp[reg] expressions onto the
279              output stream.  */
280
281           for (opindex_ptr = op->operands, opnum = 1;
282                *opindex_ptr != 0;
283                opindex_ptr++, opnum++)
284             {
285               bfd_boolean square = FALSE;
286               long value;
287               int flag;
288               char *prefix;
289
290               operand = &v850_operands[*opindex_ptr];
291
292               value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
293
294               /* The first operand is always output without any
295                  special handling.
296
297                  For the following arguments:
298
299                    If memop && opnum == memop + 1, then we need '[' since
300                    we're about to output the register used in a memory
301                    reference.
302
303                    If memop && opnum == memop + 2, then we need ']' since
304                    we just finished the register in a memory reference.  We
305                    also need a ',' before this operand.
306
307                    Else we just need a comma.
308
309                    We may need to output a trailing ']' if the last operand
310                    in an instruction is the register for a memory address.
311
312                    The exception (and there's always an exception) is the
313                    "jmp" insn which needs square brackets around it's only
314                    register argument.  */
315               prefix = "";
316               if (operand->flags & V850_OPERAND_BANG)
317                 {
318                   prefix = "!";
319                 }
320               else if (operand->flags & V850_OPERAND_PERCENT)
321                 {
322                   prefix = "%";
323                 }
324
325               if (opnum == 1 && opnum == memop)
326                 {
327                   info->fprintf_func (info->stream, "%s[", prefix);
328                   square = TRUE;
329                 }
330               else if (opnum > 1
331                        && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
332                        && opnum == memop)
333                 {
334                   info->fprintf_func (info->stream, "%s[", prefix);
335                   square = TRUE;
336                 }
337               else if (opnum > 1)
338                 info->fprintf_func (info->stream, ", %s", prefix);
339
340               /* Extract the flags, ignoring ones which do not effect disassembly output.  */
341               flag = operand->flags & (V850_OPERAND_REG
342                                        | V850_REG_EVEN
343                                        | V850_OPERAND_EP
344                                        | V850_OPERAND_SRG
345                                        | V850E_OPERAND_REG_LIST
346                                        | V850_OPERAND_CC
347                                        | V850_OPERAND_FLOAT_CC);
348
349               switch (flag)
350                 {
351                 case V850_OPERAND_REG:  info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
352                 case (V850_OPERAND_REG|V850_REG_EVEN):  info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
353                 case V850_OPERAND_EP:   info->fprintf_func (info->stream, "ep"); break;
354                 case V850_OPERAND_SRG:  info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
355
356                 case V850E_OPERAND_REG_LIST:
357                   {
358                     static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
359                                                      0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
360                     int *regs;
361                     int i;
362                     unsigned long int mask = 0;
363                     int pc = 0;
364
365
366                     switch (operand->shift)
367                       {
368                       case 0xffe00001: regs = list12_regs; break;
369                       default:
370                         /* xgettext:c-format */
371                         fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
372                         abort ();
373                       }
374
375                     for (i = 0; i < 32; i++)
376                       {
377                         if (value & (1 << i))
378                           {
379                             switch (regs[ i ])
380                               {
381                               default: mask |= (1 << regs[ i ]); break;
382                                 /* xgettext:c-format */
383                               case 0:  fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
384                               case -1: pc = 1; break;
385                               }
386                           }
387                       }
388
389                     info->fprintf_func (info->stream, "{");
390
391                     if (mask || pc)
392                       {
393                         if (mask)
394                           {
395                             unsigned int bit;
396                             int shown_one = 0;
397
398                             for (bit = 0; bit < 32; bit++)
399                               if (mask & (1 << bit))
400                                 {
401                                   unsigned long int first = bit;
402                                   unsigned long int last;
403
404                                   if (shown_one)
405                                     info->fprintf_func (info->stream, ", ");
406                                   else
407                                     shown_one = 1;
408
409                                   info->fprintf_func (info->stream, v850_reg_names[first]);
410
411                                   for (bit++; bit < 32; bit++)
412                                     if ((mask & (1 << bit)) == 0)
413                                       break;
414
415                                   last = bit;
416
417                                   if (last > first + 1)
418                                     {
419                                       info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
420                                     }
421                                 }
422                           }
423
424                         if (pc)
425                           info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
426                       }
427
428                     info->fprintf_func (info->stream, "}");
429                   }
430                   break;
431
432                 case V850_OPERAND_CC:   info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
433                 case V850_OPERAND_FLOAT_CC:   info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
434
435                 default:
436                   print_value (operand->flags, memaddr, info, value);
437                   break;
438                 }
439
440               if (square)
441                 (*info->fprintf_func) (info->stream, "]");
442             }
443
444           /* All done. */
445           break;
446         }
447     next_opcode:
448       op++;
449     }
450
451   return match;
452 }
453
454 int
455 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
456 {
457   int status, status2, match;
458   bfd_byte buffer[8];
459   int length = 0, code_length = 0;
460   unsigned long insn = 0, insn2 = 0;
461   int target_processor;
462
463   switch (info->mach)
464     {
465     case 0:
466     default:
467       target_processor = PROCESSOR_V850;
468       break;
469
470     case bfd_mach_v850e:
471       target_processor = PROCESSOR_V850E;
472       break;
473
474     case bfd_mach_v850e1:
475       target_processor = PROCESSOR_V850E;
476       break;
477
478     case bfd_mach_v850e2:
479       target_processor = PROCESSOR_V850E2;
480       break;
481
482     case bfd_mach_v850e2v3:
483       target_processor = PROCESSOR_V850E2V3;
484       break;
485     }
486
487   status = info->read_memory_func (memaddr, buffer, 2, info);
488
489   if (status)
490     {
491       info->memory_error_func (status, memaddr, info);
492       return -1;
493     }
494
495   insn = bfd_getl16 (buffer);
496
497   status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
498
499   if (!status2)
500     {
501       insn2 = bfd_getl16 (buffer);
502       /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
503     }
504
505   /* Special case.  */
506   if (length == 0
507       && (target_processor == PROCESSOR_V850E2
508           || target_processor == PROCESSOR_V850E2V3))
509     {
510       if ((insn & 0xffff) == 0x02e0             /* jr 32bit */
511           && !status2 && (insn2 & 0x1) == 0)
512         {
513           length = 2;
514           code_length = 6;
515         }
516       else if ((insn & 0xffe0) == 0x02e0        /* jarl 32bit */
517                && !status2 && (insn2 & 0x1) == 0)
518         {
519           length = 2;
520           code_length = 6;
521         }
522       else if ((insn & 0xffe0) == 0x06e0        /* jmp 32bit */
523                && !status2 && (insn2 & 0x1) == 0)
524         {
525           length = 2;
526           code_length = 6;
527         }
528     }
529
530   if (length == 0
531       && target_processor == PROCESSOR_V850E2V3)
532     {
533       if (((insn & 0xffe0) == 0x0780            /* ld.b 23bit */
534            && !status2 && (insn2 & 0x000f) == 0x0005)
535           || ((insn & 0xffe0) == 0x07a0         /* ld.bu 23bit */
536               && !status2 && (insn2 & 0x000f) == 0x0005)
537           || ((insn & 0xffe0) == 0x0780         /* ld.h 23bit */
538               && !status2 && (insn2 & 0x000f) == 0x0007)
539           || ((insn & 0xffe0) == 0x07a0         /* ld.hu 23bit */
540               && !status2 && (insn2 & 0x000f) == 0x0007)
541           || ((insn & 0xffe0) == 0x0780         /* ld.w 23bit */
542               && !status2 && (insn2 & 0x000f) == 0x0009))
543         {
544           length = 4;
545           code_length = 6;
546         }
547       else if (((insn & 0xffe0) == 0x0780       /* st.b 23bit */
548                && !status2 && (insn2 & 0x000f) == 0x000d)
549               || ((insn & 0xffe0) == 0x07a0     /* st.h 23bit */
550                   && !status2 && (insn2 & 0x000f) == 0x000d)
551               || ((insn & 0xffe0) == 0x0780     /* st.w 23bit */
552                   && !status2 && (insn2 & 0x000f) == 0x000f))
553         {
554           length = 4;
555           code_length = 6;
556         }
557     }
558
559   if (length == 0
560       && target_processor != PROCESSOR_V850)
561     {
562       if ((insn & 0xffe0) == 0x0620)            /* 32 bit MOV */
563         {
564           length = 2;
565           code_length = 6;
566         }
567       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16<<16 */
568                && !status2 && (insn2 & 0x001f) == 0x0013)
569         {
570           length = 4;
571           code_length = 6;
572         }
573       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16 */
574                && !status2 && (insn2 & 0x001f) == 0x000b)
575         {
576           length = 4;
577           code_length = 6;
578         }
579       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm32 */
580                && !status2 && (insn2 & 0x001f) == 0x001b)
581         {
582           length = 4;
583           code_length = 8;
584         }
585     }
586
587   if (length == 4
588       || (length == 0
589           && (insn & 0x0600) == 0x0600))
590     {
591       /* This is a 4 byte insn.  */
592       status = info->read_memory_func (memaddr, buffer, 4, info);
593       if (!status)
594         {
595           insn = bfd_getl32 (buffer);
596
597           if (!length)
598             length = code_length = 4;
599         }
600     }
601
602   if (code_length > length)
603     {
604       status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
605       if (status)
606         length = 0;
607     }
608
609   if (length == 0 && !status)
610     length = code_length = 2;
611
612   if (length == 2)
613     insn &= 0xffff;
614
615   match = disassemble (memaddr, info, length, insn);
616
617   if (!match)
618     {
619       int l = 0;
620
621       status = info->read_memory_func (memaddr, buffer, code_length, info);
622
623       while (l < code_length)
624         {
625           if (code_length - l == 2)
626             {
627               insn = bfd_getl16 (buffer + l) & 0xffff;
628               info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
629               l += 2;
630             }
631           else
632             {
633               insn = bfd_getl32 (buffer + l);
634               info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
635               l += 4;
636             }
637         }
638     }
639
640   return code_length;
641 }
This page took 0.061329 seconds and 4 git commands to generate.