OSDN Git Service

* ppc-opc.c: (powerpc_opcodes): Enable icswx for POWER7.
[pf3gnuchains/pf3gnuchains4x.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               bfd_boolean square = FALSE;
287               long value;
288               int flag;
289               char *prefix;
290
291               operand = &v850_operands[*opindex_ptr];
292
293               value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
294
295               /* The first operand is always output without any
296                  special handling.
297
298                  For the following arguments:
299
300                    If memop && opnum == memop + 1, then we need '[' since
301                    we're about to output the register used in a memory
302                    reference.
303
304                    If memop && opnum == memop + 2, then we need ']' since
305                    we just finished the register in a memory reference.  We
306                    also need a ',' before this operand.
307
308                    Else we just need a comma.
309
310                    We may need to output a trailing ']' if the last operand
311                    in an instruction is the register for a memory address.
312
313                    The exception (and there's always an exception) is the
314                    "jmp" insn which needs square brackets around it's only
315                    register argument.  */
316               prefix = "";
317               if (operand->flags & V850_OPERAND_BANG)
318                 {
319                   prefix = "!";
320                 }
321               else if (operand->flags & V850_OPERAND_PERCENT)
322                 {
323                   prefix = "%";
324                 }
325
326               if (opnum == 1 && opnum == memop)
327                 {
328                   info->fprintf_func (info->stream, "%s[", prefix);
329                   square = TRUE;
330                 }
331               else if (opnum > 1
332                        && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
333                        && opnum == memop)
334                 {
335                   info->fprintf_func (info->stream, "%s[", prefix);
336                   square = TRUE;
337                 }
338               else if (opnum > 1)
339                 info->fprintf_func (info->stream, ", %s", prefix);
340
341               /* Extract the flags, ignoring ones which do not effect disassembly output.  */
342               flag = operand->flags & (V850_OPERAND_REG
343                                        | V850_REG_EVEN
344                                        | V850_OPERAND_EP
345                                        | V850_OPERAND_SRG
346                                        | V850E_OPERAND_REG_LIST
347                                        | V850_OPERAND_CC
348                                        | V850_OPERAND_FLOAT_CC);
349
350               switch (flag)
351                 {
352                 case V850_OPERAND_REG:  info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
353                 case (V850_OPERAND_REG|V850_REG_EVEN):  info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
354                 case V850_OPERAND_EP:   info->fprintf_func (info->stream, "ep"); break;
355                 case V850_OPERAND_SRG:  info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
356
357                 case V850E_OPERAND_REG_LIST:
358                   {
359                     static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
360                                                      0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
361                     int *regs;
362                     int i;
363                     unsigned long int mask = 0;
364                     int pc = 0;
365
366
367                     switch (operand->shift)
368                       {
369                       case 0xffe00001: regs = list12_regs; break;
370                       default:
371                         /* xgettext:c-format */
372                         fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
373                         abort ();
374                       }
375
376                     for (i = 0; i < 32; i++)
377                       {
378                         if (value & (1 << i))
379                           {
380                             switch (regs[ i ])
381                               {
382                               default: mask |= (1 << regs[ i ]); break;
383                                 /* xgettext:c-format */
384                               case 0:  fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
385                               case -1: pc = 1; break;
386                               }
387                           }
388                       }
389
390                     info->fprintf_func (info->stream, "{");
391
392                     if (mask || pc)
393                       {
394                         if (mask)
395                           {
396                             unsigned int bit;
397                             int shown_one = 0;
398
399                             for (bit = 0; bit < 32; bit++)
400                               if (mask & (1 << bit))
401                                 {
402                                   unsigned long int first = bit;
403                                   unsigned long int last;
404
405                                   if (shown_one)
406                                     info->fprintf_func (info->stream, ", ");
407                                   else
408                                     shown_one = 1;
409
410                                   info->fprintf_func (info->stream, v850_reg_names[first]);
411
412                                   for (bit++; bit < 32; bit++)
413                                     if ((mask & (1 << bit)) == 0)
414                                       break;
415
416                                   last = bit;
417
418                                   if (last > first + 1)
419                                     {
420                                       info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
421                                     }
422                                 }
423                           }
424
425                         if (pc)
426                           info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
427                       }
428
429                     info->fprintf_func (info->stream, "}");
430                   }
431                   break;
432
433                 case V850_OPERAND_CC:   info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
434                 case V850_OPERAND_FLOAT_CC:   info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
435
436                 default:
437                   print_value (operand->flags, memaddr, info, value);
438                   break;
439                 }
440
441               if (square)
442                 (*info->fprintf_func) (info->stream, "]");
443             }
444
445           /* All done. */
446           break;
447         }
448     next_opcode:
449       op++;
450     }
451
452   return match;
453 }
454
455 int
456 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
457 {
458   int status, status2, match;
459   bfd_byte buffer[8];
460   int length = 0, code_length = 0;
461   unsigned long insn = 0, insn2 = 0;
462   int target_processor;
463
464   switch (info->mach)
465     {
466     case 0:
467     default:
468       target_processor = PROCESSOR_V850;
469       break;
470
471     case bfd_mach_v850e:
472       target_processor = PROCESSOR_V850E;
473       break;
474
475     case bfd_mach_v850e1:
476       target_processor = PROCESSOR_V850E;
477       break;
478
479     case bfd_mach_v850e2:
480       target_processor = PROCESSOR_V850E2;
481       break;
482
483     case bfd_mach_v850e2v3:
484       target_processor = PROCESSOR_V850E2V3;
485       break;
486     }
487
488   status = info->read_memory_func (memaddr, buffer, 2, info);
489
490   if (status)
491     {
492       info->memory_error_func (status, memaddr, info);
493       return -1;
494     }
495
496   insn = bfd_getl16 (buffer);
497
498   status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
499
500   if (!status2)
501     {
502       insn2 = bfd_getl16 (buffer);
503       /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
504     }
505
506   /* Special case.  */
507   if (length == 0
508       && (target_processor == PROCESSOR_V850E2
509           || target_processor == PROCESSOR_V850E2V3))
510     {
511       if ((insn & 0xffff) == 0x02e0             /* jr 32bit */
512           && !status2 && (insn2 & 0x1) == 0)
513         {
514           length = 2;
515           code_length = 6;
516         }
517       else if ((insn & 0xffe0) == 0x02e0        /* jarl 32bit */
518                && !status2 && (insn2 & 0x1) == 0)
519         {
520           length = 2;
521           code_length = 6;
522         }
523       else if ((insn & 0xffe0) == 0x06e0        /* jmp 32bit */
524                && !status2 && (insn2 & 0x1) == 0)
525         {
526           length = 2;
527           code_length = 6;
528         }
529     }
530
531   if (length == 0
532       && target_processor == PROCESSOR_V850E2V3)
533     {
534       if (((insn & 0xffe0) == 0x0780            /* ld.b 23bit */
535            && !status2 && (insn2 & 0x000f) == 0x0005)
536           || ((insn & 0xffe0) == 0x07a0         /* ld.bu 23bit */
537               && !status2 && (insn2 & 0x000f) == 0x0005)
538           || ((insn & 0xffe0) == 0x0780         /* ld.h 23bit */
539               && !status2 && (insn2 & 0x000f) == 0x0007)
540           || ((insn & 0xffe0) == 0x07a0         /* ld.hu 23bit */
541               && !status2 && (insn2 & 0x000f) == 0x0007)
542           || ((insn & 0xffe0) == 0x0780         /* ld.w 23bit */
543               && !status2 && (insn2 & 0x000f) == 0x0009))
544         {
545           length = 4;
546           code_length = 6;
547         }
548       else if (((insn & 0xffe0) == 0x0780       /* st.b 23bit */
549                && !status2 && (insn2 & 0x000f) == 0x000d)
550               || ((insn & 0xffe0) == 0x07a0     /* st.h 23bit */
551                   && !status2 && (insn2 & 0x000f) == 0x000d)
552               || ((insn & 0xffe0) == 0x0780     /* st.w 23bit */
553                   && !status2 && (insn2 & 0x000f) == 0x000f))
554         {
555           length = 4;
556           code_length = 6;
557         }
558     }
559
560   if (length == 0
561       && target_processor != PROCESSOR_V850)
562     {
563       if ((insn & 0xffe0) == 0x0620)            /* 32 bit MOV */
564         {
565           length = 2;
566           code_length = 6;
567         }
568       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16<<16 */
569                && !status2 && (insn2 & 0x001f) == 0x0013)
570         {
571           length = 4;
572           code_length = 6;
573         }
574       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm16 */
575                && !status2 && (insn2 & 0x001f) == 0x000b)
576         {
577           length = 4;
578           code_length = 6;
579         }
580       else if ((insn & 0xffc0) == 0x0780        /* prepare {list}, imm5, imm32 */
581                && !status2 && (insn2 & 0x001f) == 0x001b)
582         {
583           length = 4;
584           code_length = 8;
585         }
586     }
587
588   if (length == 4
589       || (length == 0
590           && (insn & 0x0600) == 0x0600))
591     {
592       /* This is a 4 byte insn.  */
593       status = info->read_memory_func (memaddr, buffer, 4, info);
594       if (!status)
595         {
596           insn = bfd_getl32 (buffer);
597
598           if (!length)
599             length = code_length = 4;
600         }
601     }
602
603   if (code_length > length)
604     {
605       status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
606       if (status)
607         length = 0;
608     }
609
610   if (length == 0 && !status)
611     length = code_length = 2;
612
613   if (length == 2)
614     insn &= 0xffff;
615
616   match = disassemble (memaddr, info, length, insn);
617
618   if (!match)
619     {
620       int l = 0;
621
622       status = info->read_memory_func (memaddr, buffer, code_length, info);
623
624       while (l < code_length)
625         {
626           if (code_length - l == 2)
627             {
628               insn = bfd_getl16 (buffer + l) & 0xffff;
629               info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
630               l += 2;
631             }
632           else
633             {
634               insn = bfd_getl32 (buffer + l);
635               info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
636               l += 4;
637             }
638         }
639     }
640
641   return code_length;
642 }