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