Imported Upstream version 7.5.1
[platform/upstream/gdb.git] / opcodes / i860-dis.c
1 /* Disassembler for the i860.
2    Copyright 2000, 2003, 2005, 2007, 2012 Free Software Foundation, Inc.
3
4    Contributed by Jason Eckhardt <jle@cygnus.com>.
5
6    This file is part of the GNU opcodes library.
7
8    This library is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3, or (at your option)
11    any later version.
12
13    It is distributed in the hope that it will be useful, but WITHOUT
14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16    License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
22
23 #include "sysdep.h"
24 #include "dis-asm.h"
25 #include "opcode/i860.h"
26
27 /* Later we should probably choose the prefix based on which OS flavor.  */
28 #define I860_REG_PREFIX "%"
29
30 /* Integer register names (encoded as 0..31 in the instruction).  */
31 static const char *const grnames[] = 
32  {"r0",  "r1",  "sp",  "fp",  "r4",  "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", "r30", "r31"};
36
37 /* FP register names (encoded as 0..31 in the instruction).  */
38 static const char *const frnames[] = 
39  {"f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
40   "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
41   "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
42   "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"};
43
44 /* Control/status register names (encoded as 0..11 in the instruction).
45    Registers bear, ccr, p0, p1, p2 and p3 are XP only.  */
46 static const char *const crnames[] = 
47  {"fir", "psr", "dirbase", "db", "fsr", "epsr", "bear", "ccr",
48   "p0", "p1", "p2", "p3", "--", "--", "--", "--" };
49
50
51
52 /* True if opcode is xor, xorh, and, andh, or, orh, andnot, andnoth.  */
53 #define BITWISE_OP(op)  ((op) == 0x30 || (op) == 0x31           \
54                          || (op) == 0x34 || (op) == 0x35        \
55                          || (op) == 0x38 || (op) == 0x39        \
56                          || (op) == 0x3c || (op) == 0x3d        \
57                          || (op) == 0x33 || (op) == 0x37        \
58                          || (op) == 0x3b || (op) == 0x3f)
59
60
61 /* Sign extend N-bit number.  */
62 static int
63 sign_ext (unsigned int x, int n)
64 {
65   int t;
66   t = x >> (n - 1);
67   t = ((-t) << n) | x;
68   return t;
69 }
70
71
72 /* Print a PC-relative branch offset.  VAL is the sign extended value
73    from the branch instruction.  */
74 static void
75 print_br_address (disassemble_info *info, bfd_vma memaddr, long val)
76 {
77
78   long adj = (long)memaddr + 4 + (val << 2);
79
80   (*info->fprintf_func) (info->stream, "0x%08lx", adj);
81             
82   /* Attempt to obtain a symbol for the target address.  */
83         
84   if (info->print_address_func && adj != 0)
85     {
86       (*info->fprintf_func) (info->stream, "\t// ");
87       (*info->print_address_func) (adj, info);
88     }
89 }
90
91
92 /* Print one instruction.  */
93 int
94 print_insn_i860 (bfd_vma memaddr, disassemble_info *info)
95 {
96   bfd_byte buff[4];
97   unsigned int insn, i;
98   int status;
99   const struct i860_opcode *opcode = 0;
100
101   status = (*info->read_memory_func) (memaddr, buff, sizeof (buff), info);
102   if (status != 0)
103     {
104       (*info->memory_error_func) (status, memaddr, info);
105       return -1;
106     }
107
108   /* Note that i860 instructions are always accessed as little endian
109      data, regardless of the endian mode of the i860.  */
110   insn = bfd_getl32 (buff);
111
112   status = 0;
113   i = 0;
114   while (i860_opcodes[i].name != NULL)
115     {
116       opcode = &i860_opcodes[i];
117       if ((insn & opcode->match) == opcode->match
118           && (insn & opcode->lose) == 0)
119         {
120           status = 1;
121           break;
122         }
123       ++i;
124     }
125
126   if (status == 0)
127     {
128       /* Instruction not in opcode table.  */
129       (*info->fprintf_func) (info->stream, ".long %#08x", insn);
130     }
131   else
132     {
133       const char *s;
134       int val;
135
136       /* If this a flop (or a shrd) and its dual bit is set,
137          prefix with 'd.'.  */  
138       if (((insn & 0xfc000000) == 0x48000000
139            || (insn & 0xfc000000) == 0xb0000000)
140           && (insn & 0x200))
141         (*info->fprintf_func) (info->stream, "d.%s\t", opcode->name);
142       else
143         (*info->fprintf_func) (info->stream, "%s\t", opcode->name);
144
145       for (s = opcode->args; *s; s++)
146         {
147           switch (*s)
148             {
149             /* Integer register (src1).  */
150             case '1':
151               (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX,
152                                      grnames[(insn >> 11) & 0x1f]);
153               break;
154
155             /* Integer register (src2).  */
156             case '2':
157               (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX,
158                                      grnames[(insn >> 21) & 0x1f]);
159               break;
160
161             /* Integer destination register.  */
162             case 'd':
163               (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX,
164                                      grnames[(insn >> 16) & 0x1f]);
165               break;
166
167             /* Floating-point register (src1).  */
168             case 'e':
169               (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX,
170                                      frnames[(insn >> 11) & 0x1f]);
171               break;
172
173             /* Floating-point register (src2).  */
174             case 'f':
175               (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX,
176                                      frnames[(insn >> 21) & 0x1f]);
177               break;
178
179             /* Floating-point destination register.  */
180             case 'g':
181               (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX,
182                                      frnames[(insn >> 16) & 0x1f]);
183               break;
184
185             /* Control register.  */
186             case 'c':
187               (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX,
188                                      crnames[(insn >> 21) & 0xf]);
189               break;
190
191             /* 16-bit immediate (sign extend, except for bitwise ops).  */
192             case 'i':
193               if (BITWISE_OP ((insn & 0xfc000000) >> 26))
194                 (*info->fprintf_func) (info->stream, "0x%04x",
195                                        (unsigned int) (insn & 0xffff));
196               else
197                 (*info->fprintf_func) (info->stream, "%d",
198                                        sign_ext ((insn & 0xffff), 16));
199               break;
200
201             /* 16-bit immediate, aligned (2^0, ld.b).  */
202             case 'I':
203               (*info->fprintf_func) (info->stream, "%d",
204                                      sign_ext ((insn & 0xffff), 16));
205               break;
206
207             /* 16-bit immediate, aligned (2^1, ld.s).  */
208             case 'J':
209               (*info->fprintf_func) (info->stream, "%d",
210                                      sign_ext ((insn & 0xfffe), 16));
211               break;
212
213             /* 16-bit immediate, aligned (2^2, ld.l, {p}fld.l, fst.l).  */
214             case 'K':
215               (*info->fprintf_func) (info->stream, "%d",
216                                      sign_ext ((insn & 0xfffc), 16));
217               break;
218
219             /* 16-bit immediate, aligned (2^3, {p}fld.d, fst.d).  */
220             case 'L':
221               (*info->fprintf_func) (info->stream, "%d",
222                                      sign_ext ((insn & 0xfff8), 16));
223               break;
224
225             /* 16-bit immediate, aligned (2^4, {p}fld.q, fst.q).  */
226             case 'M':
227               (*info->fprintf_func) (info->stream, "%d",
228                                      sign_ext ((insn & 0xfff0), 16));
229               break;
230
231             /* 5-bit immediate (zero extend).  */
232             case '5':
233               (*info->fprintf_func) (info->stream, "%d",
234                                      ((insn >> 11) & 0x1f));
235               break;
236
237             /* Split 16 bit immediate (20..16:10..0).  */
238             case 's':
239               val = ((insn >> 5) & 0xf800) | (insn & 0x07ff);
240               (*info->fprintf_func) (info->stream, "%d",
241                                      sign_ext (val, 16));
242               break;
243
244             /* Split 16 bit immediate, aligned. (2^0, st.b).  */
245             case 'S':
246               val = ((insn >> 5) & 0xf800) | (insn & 0x07ff);
247               (*info->fprintf_func) (info->stream, "%d",
248                                      sign_ext (val, 16));
249               break;
250
251             /* Split 16 bit immediate, aligned. (2^1, st.s).  */
252             case 'T':
253               val = ((insn >> 5) & 0xf800) | (insn & 0x07fe);
254               (*info->fprintf_func) (info->stream, "%d",
255                                      sign_ext (val, 16));
256               break;
257
258             /* Split 16 bit immediate, aligned. (2^2, st.l).  */
259             case 'U':
260               val = ((insn >> 5) & 0xf800) | (insn & 0x07fc);
261               (*info->fprintf_func) (info->stream, "%d",
262                                      sign_ext (val, 16));
263               break;
264
265             /* 26-bit PC relative immediate (lbroff).  */
266             case 'l':
267               val = sign_ext ((insn & 0x03ffffff), 26);
268               print_br_address (info, memaddr, val);
269               break;
270
271             /* 16-bit PC relative immediate (sbroff).  */
272             case 'r':
273               val = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
274               print_br_address (info, memaddr, val);
275               break;
276
277             default:
278               (*info->fprintf_func) (info->stream, "%c", *s);
279               break;
280             }
281         }
282     }
283
284   return sizeof (insn);
285 }
286