Fixed disassembler to use processor type when decoding instructions.
[binutils-gdb.git] / opcodes / v850-dis.c
1 /* Disassemble V850 instructions.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18
19 #include <stdio.h>
20
21 #include "ansidecl.h"
22 #include "opcode/v850.h"
23 #include "dis-asm.h"
24
25 static const char *const v850_reg_names[] =
26 { "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
27 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
28 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
29 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" };
30
31 static const char *const v850_sreg_names[] =
32 { "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7",
33 "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
34 "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23",
35 "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31" };
36
37 static const char *const v850_cc_names[] =
38 { "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
39 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" };
40
41 static int
42 disassemble (memaddr, info, insn)
43 bfd_vma memaddr;
44 struct disassemble_info *info;
45 unsigned long insn;
46 {
47 struct v850_opcode * op = (struct v850_opcode *)v850_opcodes;
48 const struct v850_operand * operand;
49 int match = 0;
50 int short_op = ((insn & 0x0600) != 0x0600);
51 int bytes_read;
52 int target_processor;
53
54 /* start-sanitize-v850e */
55 /* Special case: 32 bit MOV */
56 if ((insn & 0xffe0) == 0x0620)
57 short_op = true;
58 /* end-sanitize-v850e */
59
60 bytes_read = short_op ? 2 : 4;
61
62 /* If this is a two byte insn, then mask off the high bits. */
63 if (short_op)
64 insn &= 0xffff;
65
66 switch (info->mach)
67 {
68 case 0:
69 default:
70 target_processor = PROCESSOR_V850;
71 break;
72
73 /* start-sanitize-v850e */
74 case bfd_mach_v850e:
75 target_processor = PROCESSOR_V850E;
76 break;
77
78 case bfd_mach_v850eq:
79 target_processor = PROCESSOR_V850EQ;
80 break;
81 /* end-sanitize-v850e */
82 }
83
84 /* Find the opcode. */
85 while (op->name)
86 {
87 if ((op->mask & insn) == op->opcode
88 && (op->processors & target_processor))
89 {
90 const unsigned char * opindex_ptr;
91 unsigned int opnum;
92 unsigned int memop;
93
94 match = 1;
95 (*info->fprintf_func) (info->stream, "%s\t", op->name);
96 //fprintf (stderr, "match: mask: %x insn: %x, opcode: %x, name: %s\n", op->mask, insn, op->opcode, op->name );
97
98 memop = op->memop;
99 /* Now print the operands.
100
101 MEMOP is the operand number at which a memory
102 address specification starts, or zero if this
103 instruction has no memory addresses.
104
105 A memory address is always two arguments.
106
107 This information allows us to determine when to
108 insert commas into the output stream as well as
109 when to insert disp[reg] expressions onto the
110 output stream. */
111
112 for (opindex_ptr = op->operands, opnum = 1;
113 *opindex_ptr != 0;
114 opindex_ptr++, opnum++)
115 {
116 long value;
117 int flag;
118 int status;
119 bfd_byte buffer[ 4 ];
120
121 operand = &v850_operands[*opindex_ptr];
122
123 if (operand->extract)
124 value = (operand->extract) (insn, 0);
125 else
126 {
127 if (operand->bits == -1)
128 value = (insn & operand->shift);
129 else
130 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
131
132 if (operand->flags & V850_OPERAND_SIGNED)
133 value = ((long)(value << (32 - operand->bits))
134 >> (32 - operand->bits));
135 }
136
137 /* The first operand is always output without any
138 special handling.
139
140 For the following arguments:
141
142 If memop && opnum == memop + 1, then we need '[' since
143 we're about to output the register used in a memory
144 reference.
145
146 If memop && opnum == memop + 2, then we need ']' since
147 we just finished the register in a memory reference. We
148 also need a ',' before this operand.
149
150 Else we just need a comma.
151
152 We may need to output a trailing ']' if the last operand
153 in an instruction is the register for a memory address.
154
155 The exception (and there's always an exception) is the
156 "jmp" insn which needs square brackets around it's only
157 register argument. */
158
159 if (memop && opnum == memop + 1) info->fprintf_func (info->stream, "[");
160 else if (memop && opnum == memop + 2) info->fprintf_func (info->stream, "],");
161 else if (memop == 1 && opnum == 1
162 && (operand->flags & V850_OPERAND_REG))
163 info->fprintf_func (info->stream, "[");
164 else if (opnum > 1) info->fprintf_func (info->stream, ", ");
165
166 /* extract the flags, ignorng ones which do not effect disassembly output. */
167 flag = operand->flags;
168 flag &= ~ V850_OPERAND_SIGNED;
169 flag &= ~ V850_OPERAND_RELAX;
170 flag &= - flag;
171
172 switch (flag)
173 {
174 case V850_OPERAND_REG: info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
175 case V850_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
176 case V850_OPERAND_CC: info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
177 case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break;
178 case V850_OPERAND_DISP: info->print_address_func (value + memaddr, info); break;
179 default: info->fprintf_func (info->stream, "%d", value); break;
180 /* start-sanitize-v850e */
181 case V850E_PUSH_POP:
182 {
183 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
184 static int list18_h_regs[32] = { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
185 static int list18_l_regs[32] = { 3, 2, 1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8 };
186 int * regs;
187 int i;
188 unsigned long int mask = 0;
189 int pc = false;
190 int sr = false;
191
192
193 switch (operand->shift)
194 {
195 case 0xffe00001: regs = list12_regs; break;
196 case 0xfff8000f: regs = list18_h_regs; break;
197 case 0xfff8001f: regs = list18_l_regs; value &= ~0x10; break; /* Do not include magic bit */
198 default:
199 fprintf (stderr, "unknown operand shift: %x\n", operand->shift );
200 abort();
201 }
202
203 for (i = 0; i < 32; i++)
204 {
205 if (value & (1 << i))
206 {
207 switch (regs[ i ])
208 {
209 default: mask |= (1 << regs[ i ]); break;
210 case 0: fprintf (stderr, "unknown pop reg: %d\n", i ); abort();
211 case -1: pc = true; break;
212 case -2: sr = true; break;
213 }
214 }
215 }
216
217 info->fprintf_func (info->stream, "{");
218
219 if (mask || pc || sr)
220 {
221 if (mask)
222 {
223 unsigned int bit;
224 int shown_one = false;
225
226 for (bit = 0; bit < 32; bit++)
227 if (mask & (1 << bit))
228 {
229 unsigned long int first = bit;
230 unsigned long int last;
231
232 if (shown_one)
233 info->fprintf_func (info->stream, ", ");
234 else
235 shown_one = true;
236
237 info->fprintf_func (info->stream, v850_reg_names[first]);
238
239 for (bit++; bit < 32; bit++)
240 if ((mask & (1 << bit)) == 0)
241 break;
242
243 last = bit;
244
245 if (last > first + 1)
246 {
247 info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
248 }
249 }
250 }
251
252 if (pc)
253 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
254 if (sr)
255 info->fprintf_func (info->stream, "%sSR", (mask || pc) ? ", " : "");
256 }
257
258 info->fprintf_func (info->stream, "}");
259 }
260 break;
261
262 case V850E_IMMEDIATE16:
263 status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
264 if (status == 0)
265 {
266 bytes_read += 2;
267 value = bfd_getl16 (buffer);
268
269 /* If this is a DISPOSE instruction with ff set to 0x10, then shift value up by 16. */
270 if ((insn & 0x001fffc0) == 0x00130780)
271 value <<= 16;
272
273 info->fprintf_func (info->stream, "0x%x", value);
274 }
275 else
276 {
277 info->memory_error_func (status, memaddr + bytes_read, info);
278 }
279 break;
280
281 case V850E_IMMEDIATE32:
282 status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
283 if (status == 0)
284 {
285 bytes_read += 4;
286 value = bfd_getl32 (buffer);
287 info->fprintf_func (info->stream, "0x%lx", value);
288 }
289 else
290 {
291 info->memory_error_func (status, memaddr + bytes_read, info);
292 }
293 break;
294 /* end-sanitize-v850e */
295 }
296
297 /* Handle jmp correctly. */
298 if (memop == 1 && opnum == 1
299 && ((operand->flags & V850_OPERAND_REG) != 0))
300 (*info->fprintf_func) (info->stream, "]");
301 }
302
303 /* Close any square bracket we left open. */
304 if (memop && opnum == memop + 2)
305 (*info->fprintf_func) (info->stream, "]");
306
307 /* All done. */
308 break;
309 }
310 op++;
311 }
312
313 if (!match)
314 {
315 if (short_op)
316 info->fprintf_func (info->stream, ".short\t0x%04x", insn);
317 else
318 info->fprintf_func (info->stream, ".long\t0x%08x", insn);
319 }
320
321 return bytes_read;
322 }
323
324 int
325 print_insn_v850 (memaddr, info)
326 bfd_vma memaddr;
327 struct disassemble_info * info;
328 {
329 int status;
330 bfd_byte buffer[ 4 ];
331 unsigned long insn;
332
333 /* First figure out how big the opcode is. */
334
335 status = info->read_memory_func (memaddr, buffer, 2, info);
336 if (status == 0)
337 {
338 insn = bfd_getl16 (buffer);
339
340 if ( (insn & 0x0600) == 0x0600
341 && (insn & 0xffe0) != 0x0620)
342 {
343 /* If this is a 4 byte insn, read 4 bytes of stuff. */
344 status = info->read_memory_func (memaddr, buffer, 4, info);
345
346 if (status == 0)
347 insn = bfd_getl32 (buffer);
348 }
349 }
350
351 if (status != 0)
352 {
353 info->memory_error_func (status, memaddr, info);
354 return -1;
355 }
356
357 /* Make sure we tell our caller how many bytes we consumed. */
358 return disassemble (memaddr, info, insn);
359 }
360
361