Snap. Gets through igen's checks.
[deliverable/binutils-gdb.git] / opcodes / v850-dis.c
CommitLineData
529418dd
JL
1/* Disassemble V850 instructions.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 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
502535cf
JL
25static 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",
404d6e4f 29 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" };
502535cf
JL
30
31static 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
37static const char *const v850_cc_names[] =
38{ "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
a5f2a4e5 39 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" };
502535cf 40
d87a1542
NC
41static int
42disassemble (memaddr, info, insn)
529418dd
JL
43 bfd_vma memaddr;
44 struct disassemble_info *info;
d87a1542 45 unsigned long insn;
529418dd 46{
d87a1542
NC
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;
404d6e4f
NC
52 int target_processor;
53
54/* start-sanitize-v850e */
d87a1542
NC
55 /* Special case: 32 bit MOV */
56 if ((insn & 0xffe0) == 0x0620)
57 short_op = true;
404d6e4f
NC
58/* end-sanitize-v850e */
59
d87a1542
NC
60 bytes_read = short_op ? 2 : 4;
61
529418dd 62 /* If this is a two byte insn, then mask off the high bits. */
d87a1542 63 if (short_op)
529418dd
JL
64 insn &= 0xffff;
65
404d6e4f
NC
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
529418dd
JL
84 /* Find the opcode. */
85 while (op->name)
86 {
404d6e4f
NC
87 if ((op->mask & insn) == op->opcode
88 && (op->processors & target_processor))
529418dd 89 {
d87a1542
NC
90 const unsigned char * opindex_ptr;
91 unsigned int opnum;
92 unsigned int memop;
502535cf 93
529418dd
JL
94 match = 1;
95 (*info->fprintf_func) (info->stream, "%s\t", op->name);
d87a1542 96//fprintf (stderr, "match: mask: %x insn: %x, opcode: %x, name: %s\n", op->mask, insn, op->opcode, op->name );
502535cf 97
d87a1542
NC
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.
502535cf 106
d87a1542
NC
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
502535cf 121 operand = &v850_operands[*opindex_ptr];
1f302a3b 122
502535cf
JL
123 if (operand->extract)
124 value = (operand->extract) (insn, 0);
125 else
1f302a3b
NC
126 {
127 if (operand->bits == -1)
128 value = (insn & operand->shift);
129 else
130 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
502535cf 131
1f302a3b
NC
132 if (operand->flags & V850_OPERAND_SIGNED)
133 value = ((long)(value << (32 - operand->bits))
134 >> (32 - operand->bits));
135 }
d87a1542
NC
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;
d87a1542
NC
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 };
d87a1542
NC
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 };
d0fd63cb
NC
186 int * regs;
187 int i;
188 unsigned long int mask = 0;
189 int pc = false;
190 int sr = false;
191
d87a1542
NC
192
193 switch (operand->shift)
194 {
195 case 0xffe00001: regs = list12_regs; break;
d87a1542
NC
196 case 0xfff8000f: regs = list18_h_regs; break;
197 case 0xfff8001f: regs = list18_l_regs; value &= ~0x10; break; /* Do not include magic bit */
d87a1542
NC
198 default:
199 fprintf (stderr, "unknown operand shift: %x\n", operand->shift );
200 abort();
201 }
202
d87a1542
NC
203 for (i = 0; i < 32; i++)
204 {
205 if (value & (1 << i))
206 {
d87a1542
NC
207 switch (regs[ i ])
208 {
d0fd63cb 209 default: mask |= (1 << regs[ i ]); break;
d87a1542 210 case 0: fprintf (stderr, "unknown pop reg: %d\n", i ); abort();
d0fd63cb
NC
211 case -1: pc = true; break;
212 case -2: sr = true; break;
d87a1542
NC
213 }
214 }
215 }
d0fd63cb
NC
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
d87a1542
NC
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, "]");
502535cf
JL
301 }
302
d87a1542
NC
303 /* Close any square bracket we left open. */
304 if (memop && opnum == memop + 2)
305 (*info->fprintf_func) (info->stream, "]");
306
502535cf 307 /* All done. */
529418dd
JL
308 break;
309 }
310 op++;
311 }
312
313 if (!match)
314 {
d87a1542
NC
315 if (short_op)
316 info->fprintf_func (info->stream, ".short\t0x%04x", insn);
529418dd 317 else
d87a1542 318 info->fprintf_func (info->stream, ".long\t0x%08x", insn);
529418dd 319 }
d87a1542
NC
320
321 return bytes_read;
529418dd 322}
d87a1542
NC
323
324int
325print_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
This page took 0.067018 seconds and 4 git commands to generate.