OSDN Git Service

2010-09-27 Tejas Belagod <tejas.belagod@arm.com>
[pf3gnuchains/sourceware.git] / opcodes / v850-dis.c
1 /* Disassemble V850 instructions.
2    Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010
3    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 <stdio.h>
24
25 #include "sysdep.h"
26 #include "opcode/v850.h"
27 #include "dis-asm.h"
28 #include "opintl.h"
29
30 static const char *const v850_reg_names[] =
31 {
32   "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
33   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
34   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
35   "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
36 };
37
38 static const char *const v850_sreg_names[] =
39 {
40   "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
41   "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
42   "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
43   "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
44   "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
45   "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
46   "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
47   "fewr", "dbwr", "bsel"
48 };
49
50 static const char *const v850_cc_names[] =
51 {
52   "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
53   "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
54 };
55
56 static const char *const v850_float_cc_names[] =
57 {
58   "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
59   "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
60 };
61
62
63 static void
64 print_value (int flags, bfd_vma memaddr, struct disassemble_info *info, long value)
65 {
66   if (flags & V850_PCREL)
67     {
68       bfd_vma addr = value + memaddr;
69       info->print_address_func (addr, info);
70     }
71   else if (flags & V850_OPERAND_DISP)
72     {
73       if (flags & V850_OPERAND_SIGNED)
74         {
75           info->fprintf_func (info->stream, "%ld", value);
76         }
77       else
78         {
79           info->fprintf_func (info->stream, "%lu", value);
80         }
81     }
82   else if (flags & V850E_IMMEDIATE32)
83     {
84       info->fprintf_func (info->stream, "0x%lx", value);
85     }
86   else
87     {
88       if (flags & V850_OPERAND_SIGNED)
89         {
90           info->fprintf_func (info->stream, "%ld", value);
91         }
92       else
93         {
94           info->fprintf_func (info->stream, "%lu", value);
95         }
96     }
97 }
98
99 static long
100 get_operand_value (const struct v850_operand *operand,
101                    unsigned long insn,
102                    int bytes_read,
103                    bfd_vma memaddr,
104                    struct disassemble_info * info,
105                    bfd_boolean noerror,
106                    int *invalid)
107 {
108   long value;
109   bfd_byte buffer[4];
110
111   if ((operand->flags & V850E_IMMEDIATE16)
112       || (operand->flags & V850E_IMMEDIATE16HI))
113     {
114       int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
115
116       if (status == 0)
117         {
118           value = bfd_getl16 (buffer);
119
120           if (operand->flags & V850E_IMMEDIATE16HI)
121             value <<= 16;
122
123           return value;
124         }
125
126       if (!noerror)
127         info->memory_error_func (status, memaddr + bytes_read, info);
128
129       return 0;
130     }
131
132   if (operand->flags & V850E_IMMEDIATE23)
133     {
134       int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
135
136       if (status == 0)
137         {
138           value = bfd_getl32 (buffer);
139
140           value = (operand->extract) (value, invalid);
141
142           return value;
143         }
144
145       if (!noerror)
146         info->memory_error_func (status, memaddr + bytes_read, info);
147
148       return 0;
149     }
150
151   if (operand->flags & V850E_IMMEDIATE32)
152     {
153       int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
154
155       if (status == 0)
156         {
157           bytes_read += 4;
158           value = bfd_getl32 (buffer);
159
160           return value;
161         }
162
163       if (!noerror)
164         info->memory_error_func (status, memaddr + bytes_read, info);
165
166       return 0;
167     }
168
169   if (operand->extract)
170     value = (operand->extract) (insn, invalid);
171   else
172     {
173       if (operand->bits == -1)
174         value = (insn & operand->shift);
175       else
176         value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
177
178       if (operand->flags & V850_OPERAND_SIGNED)
179         value = ((long)(value << (sizeof (long)*8 - operand->bits))
180                  >> (sizeof (long)*8 - operand->bits));
181     }
182
183   return value;
184 }
185
186
187 static int
188 disassemble (bfd_vma memaddr, struct disassemble_info *info, int bytes_read, unsigned long insn)
189 {
190   struct v850_opcode *op = (struct v850_opcode *)v850_opcodes;
191   const struct v850_operand *operand;
192   int match = 0;
193   int target_processor;
194
195   switch (info->mach)
196     {
197     case 0:
198     default:
199       target_processor = PROCESSOR_V850;
200       break;
201
202     case bfd_mach_v850e:
203       target_processor = PROCESSOR_V850E;
204       break;
205
206     case bfd_mach_v850e1:
207       target_processor = PROCESSOR_V850E;
208       break;
209
210     case bfd_mach_v850e2:
211       target_processor = PROCESSOR_V850E2;
212       break;
213
214     case bfd_mach_v850e2v3:
215       target_processor = PROCESSOR_V850E2V3;
216       break;
217     }
218
219   /* If this is a two byte insn, then mask off the high bits.  */
220   if (bytes_read == 2)
221     insn &= 0xffff;
222
223   /* Find the opcode.  */
224   while (op->name)
225     {
226       if ((op->mask & insn) == op->opcode
227           && (op->processors & target_processor)
228           && !(op->processors & PROCESSOR_OPTION_ALIAS))
229         {
230           /* Code check start.  */
231           const unsigned char *opindex_ptr;
232           unsigned int opnum;
233           unsigned int memop;
234
235           for (opindex_ptr = op->operands, opnum = 1;
236                *opindex_ptr != 0;
237                opindex_ptr++, opnum++)
238             {
239               int invalid = 0;
240               long value;
241
242               operand = &v850_operands[*opindex_ptr];
243
244               value = get_operand_value (operand, insn, bytes_read, memaddr, info, 1, &invalid);
245
246               if (invalid)
247                 goto next_opcode;
248
249               if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
250                 goto next_opcode;
251
252               if ((operand->flags & V850_NOT_SA) && value == 0xd)
253                 goto next_opcode;
254
255               if ((operand->flags & V850_NOT_IMM0) && value == 0)
256                 goto next_opcode;
257             }
258
259           /* Code check end.  */
260
261           match = 1;
262           (*info->fprintf_func) (info->stream, "%s\t", op->name);
263 #if 0
264           fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
265                    insn, op->mask, op->opcode, op->name );
266 #endif
267
268           memop = op->memop;
269           /* Now print the operands.
270
271              MEMOP is the operand number at which a memory
272              address specification starts, or zero if this
273              instruction has no memory addresses.
274
275              A memory address is always two arguments.
276
277              This information allows us to determine when to
278              insert commas into the output stream as well as
279              when to insert disp[reg] expressions onto the
280              output stream.  */
281
282           for (opindex_ptr = op->operands, opnum = 1;
283                *opindex_ptr != 0;
284                opindex_ptr++, opnum++)
285             {
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                 info->fprintf_func (info->stream, "%s[", prefix);
327               else if (opnum > 1
328                        && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
329                        && opnum == memop)
330                 info->fprintf_func (info->stream, "%s[", prefix);
331               else if (opnum > 1)
332                 info->fprintf_func (info->stream, ", %s", prefix);
333
334               /* Extract the flags, ignoring ones which do not effect disassembly output.  */
335               flag = operand->flags & (V850_OPERAND_REG
336                                        | V850_REG_EVEN
337                                        | V850_OPERAND_EP
338                                        | V850_OPERAND_SRG
339                                        | V850E_OPERAND_REG_LIST
340                                        | V850_OPERAND_CC
341                                        | V850_OPERAND_FLOAT_CC);
342
343               switch (flag)
344                 {
345                 case V850_OPERAND_REG:  info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
346                 case (V850_OPERAND_REG|V850_REG_EVEN):  info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
347                 case V850_OPERAND_EP:   info->fprintf_func (info->stream, "ep"); break;
348                 case V850_OPERAND_SRG:  info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
349
350                 case V850E_OPERAND_REG_LIST:
351                   {
352                     static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
353                                                      0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
354                     int *regs;
355                     int i;
356                     unsigned long int mask = 0;
357                     int pc = 0;
358
359
360                     switch (operand->shift)
361                       {
362                       case 0xffe00001: regs = list12_regs; break;
363                       default:
364                         /* xgettext:c-format */
365                         fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
366                         abort ();
367                       }
368
369                     for (i = 0; i < 32; i++)
370                       {
371                         if (value & (1 << i))
372                           {
373                             switch (regs[ i ])
374                               {
375                               default: mask |= (1 << regs[ i ]); break;
376                                 /* xgettext:c-format */
377                               case 0:  fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
378                               case -1: pc = 1; break;
379                               }
380                           }
381                       }
382
383                     info->fprintf_func (info->stream, "{");
384
385                     if (mask || pc)
386                       {
387                         if (mask)
388                           {
389                             unsigned int bit;
390                             int shown_one = 0;
391
392                             for (bit = 0; bit < 32; bit++)
393                               if (mask & (1 << bit))
394                                 {
395                                   unsigned long int first = bit;
396                                   unsigned long int last;
397
398                                   if (shown_one)
399                                     info->fprintf_func (info->stream, ", ");
400                                   else
401                                     shown_one = 1;
402
403                                   info->fprintf_func (info->stream, v850_reg_names[first]);
404
405                                   for (bit++; bit < 32; bit++)
406                                     if ((mask & (1 << bit)) == 0)
407                                       break;
408
409                                   last = bit;
410
411                                   if (last > first + 1)
412                                     {
413                                       info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
414                                     }
415                                 }
416                           }
417
418                         if (pc)
419                           info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
420                       }
421
422                     info->fprintf_func (info->stream, "}");
423                   }
424                   break;
425
426                 case V850_OPERAND_CC:   info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
427                 case V850_OPERAND_FLOAT_CC:   info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
428
429                 default:
430                   print_value (operand->flags, memaddr, info, value);
431                   break;
432                 }
433
434               if (opnum == 2 && opnum == memop)
435                 (*info->fprintf_func) (info->stream, "]");
436             }
437
438           /* All done. */
439           break;
440         }
441     next_opcode:
442       op++;
443     }
444
445   return match;
446 }
447
448 int
449 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
450 {
451   int status, status2, match;
452   bfd_byte buffer[8];
453   int length = 0, code_length = 0;
454   unsigned long insn = 0, insn2 = 0;
455   int target_processor;
456
457   switch (info->mach)
458     {
459     case 0:
460     default:
461       target_processor = PROCESSOR_V850;
462       break;
463
464     case bfd_mach_v850e:
465       target_processor = PROCESSOR_V850E;
466       break;
467
468     case bfd_mach_v850e1:
469       target_processor = PROCESSOR_V850E;
470       break;
471
472     case bfd_mach_v850e2:
473       target_processor = PROCESSOR_V850E2;
474       break;
475
476     case bfd_mach_v850e2v3:
477       target_processor = PROCESSOR_V850E2V3;
478       break;
479     }
480
481   status = info->read_memory_func (memaddr, buffer, 2, info);
482
483   if (status)
484     {
485       info->memory_error_func (status, memaddr, info);
486       return -1;
487     }
488
489   insn = bfd_getl16 (buffer);
490
491   status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
492
493   if (!status2)
494     {
495       insn2 = bfd_getl16 (buffer);
496       /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
497     }
498
499   /* Special case.  */
500   if (length == 0
501       && (target_processor == PROCESSOR_V850E2
502           || target_processor == PROCESSOR_V850E2V3))
503     {
504       if ((insn & 0xffff) == 0x02e0             /* jr 32bit */
505           && !status2 && (insn2 & 0x1) == 0)
506         {
507           length = 2;
508           code_length = 6;
509         }
510       else if ((insn & 0xffe0) == 0x02e0        /* jarl 32bit */
511                && !status2 && (insn2 & 0x1) == 0)
512         {
513           length = 2;
514           code_length = 6;
515         }
516       else if ((insn & 0xffe0) == 0x06e0        /* jmp 32bit */
517                && !status2 && (insn2 & 0x1) == 0)
518         {
519           length = 2;
520           code_length = 6;
521         }
522     }
523
524   if (length == 0
525       && target_processor == PROCESSOR_V850E2V3)
526     {
527       if (((insn & 0xffe0) == 0x0780            /* ld.b 23bit */
528            && !status2 && (insn2 & 0x000f) == 0x0005)
529           || ((insn & 0xffe0) == 0x07a0         /* ld.bu 23bit */
530               && !status2 && (insn2 & 0x000f) == 0x0005)
531           || ((insn & 0xffe0) == 0x0780         /* ld.h 23bit */
532               && !status2 && (insn2 & 0x000f) == 0x0007)
533           || ((insn & 0xffe0) == 0x07a0         /* ld.hu 23bit */
534               && !status2 && (insn2 & 0x000f) == 0x0007)
535           || ((insn & 0xffe0) == 0x0780         /* ld.w 23bit */
536               && !status2 && (insn2 & 0x000f) == 0x0009))
537         {
538           length = 4;
539           code_length = 6;
540         }
541       else if (((insn & 0xffe0) == 0x0780       /* st.b 23bit */
542                && !status2 && (insn2 & 0x000f) == 0x000d)
543               || ((insn & 0xffe0) == 0x07a0     /* st.h 23bit */
544                   && !status2 && (insn2 & 0x000f) == 0x000d)
545               || ((insn & 0xffe0) == 0x0780     /* st.w 23bit */
546                   && !status2 && (insn2 & 0x000f) == 0x000f))
547         {
548           length = 4;
549           code_length = 6;
550         }
551     }
552
553   if (length == 0
554       && target_processor != PROCESSOR_V850)
555     {
556       if ((insn & 0xffe0) == 0x0620)            /* 32 bit MOV */
557         {
558           length = 2;
559           code_length = 6;
560         }
561       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16<<16 */
562                && !status2 && (insn2 & 0x001f) == 0x0013)
563         {
564           length = 4;
565           code_length = 6;
566         }
567       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16 */
568                && !status2 && (insn2 & 0x001f) == 0x000b)
569         {
570           length = 4;
571           code_length = 6;
572         }
573       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm32 */
574                && !status2 && (insn2 & 0x001f) == 0x001b)
575         {
576           length = 4;
577           code_length = 8;
578         }
579     }
580
581   if (length == 4
582       || (length == 0
583           && (insn & 0x0600) == 0x0600))
584     {
585       /* This is a 4 byte insn.  */
586       status = info->read_memory_func (memaddr, buffer, 4, info);
587       if (!status)
588         {
589           insn = bfd_getl32 (buffer);
590
591           if (!length)
592             length = code_length = 4;
593         }
594     }
595
596   if (code_length > length)
597     {
598       status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
599       if (status)
600         length = 0;
601     }
602
603   if (length == 0 && !status)
604     length = code_length = 2;
605
606   if (length == 2)
607     insn &= 0xffff;
608
609   match = disassemble (memaddr, info, length, insn);
610
611   if (!match)
612     {
613       int l = 0;
614
615       status = info->read_memory_func (memaddr, buffer, code_length, info);
616
617       while (l < code_length)
618         {
619           if (code_length - l == 2)
620             {
621               insn = bfd_getl16 (buffer + l) & 0xffff;
622               info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
623               l += 2;
624             }
625           else
626             {
627               insn = bfd_getl32 (buffer + l);
628               info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
629               l += 4;
630             }
631         }
632     }
633
634   return code_length;
635 }