1 /* Disassemble V850 instructions.
2 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005
3 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18 MA 02110-1301, USA. */
24 #include "opcode/v850.h"
28 static const char *const v850_reg_names
[] =
29 { "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
30 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
31 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
32 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" };
34 static const char *const v850_sreg_names
[] =
35 { "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7",
36 "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
37 "ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23",
38 "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
39 "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23",
40 "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31" };
42 static const char *const v850_cc_names
[] =
43 { "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
44 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" };
47 disassemble (bfd_vma memaddr
,
48 struct disassemble_info
* info
,
51 struct v850_opcode
* op
= (struct v850_opcode
*) v850_opcodes
;
52 const struct v850_operand
* operand
;
54 int short_op
= ((insn
& 0x0600) != 0x0600);
58 /* Special case: 32 bit MOV. */
59 if ((insn
& 0xffe0) == 0x0620)
62 bytes_read
= short_op
? 2 : 4;
64 /* If this is a two byte insn, then mask off the high bits. */
72 target_processor
= PROCESSOR_V850
;
76 target_processor
= PROCESSOR_V850E
;
80 target_processor
= PROCESSOR_V850E1
;
84 /* Find the opcode. */
87 if ((op
->mask
& insn
) == op
->opcode
88 && (op
->processors
& target_processor
))
90 const unsigned char *opindex_ptr
;
95 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
98 /* Now print the operands.
100 MEMOP is the operand number at which a memory
101 address specification starts, or zero if this
102 instruction has no memory addresses.
104 A memory address is always two arguments.
106 This information allows us to determine when to
107 insert commas into the output stream as well as
108 when to insert disp[reg] expressions onto the
111 for (opindex_ptr
= op
->operands
, opnum
= 1;
113 opindex_ptr
++, opnum
++)
120 operand
= &v850_operands
[*opindex_ptr
];
122 if (operand
->extract
)
123 value
= (operand
->extract
) (insn
, 0);
126 if (operand
->bits
== -1)
127 value
= (insn
& operand
->shift
);
129 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
131 if (operand
->flags
& V850_OPERAND_SIGNED
)
132 value
= ((long)(value
<< (32 - operand
->bits
))
133 >> (32 - operand
->bits
));
136 /* The first operand is always output without any
139 For the following arguments:
141 If memop && opnum == memop + 1, then we need '[' since
142 we're about to output the register used in a memory
145 If memop && opnum == memop + 2, then we need ']' since
146 we just finished the register in a memory reference. We
147 also need a ',' before this operand.
149 Else we just need a comma.
151 We may need to output a trailing ']' if the last operand
152 in an instruction is the register for a memory address.
154 The exception (and there's always an exception) is the
155 "jmp" insn which needs square brackets around it's only
156 register argument. */
158 if (memop
&& opnum
== memop
+ 1)
159 info
->fprintf_func (info
->stream
, "[");
160 else if (memop
&& opnum
== memop
+ 2)
161 info
->fprintf_func (info
->stream
, "],");
162 else if (memop
== 1 && opnum
== 1
163 && (operand
->flags
& V850_OPERAND_REG
))
164 info
->fprintf_func (info
->stream
, "[");
166 info
->fprintf_func (info
->stream
, ", ");
168 /* Extract the flags, ignorng ones which
169 do not effect disassembly output. */
170 flag
= operand
->flags
;
171 flag
&= ~ V850_OPERAND_SIGNED
;
172 flag
&= ~ V850_OPERAND_RELAX
;
177 case V850_OPERAND_REG
:
178 info
->fprintf_func (info
->stream
, "%s", v850_reg_names
[value
]);
180 case V850_OPERAND_SRG
:
181 info
->fprintf_func (info
->stream
, "%s", v850_sreg_names
[value
]);
183 case V850_OPERAND_CC
:
184 info
->fprintf_func (info
->stream
, "%s", v850_cc_names
[value
]);
186 case V850_OPERAND_EP
:
187 info
->fprintf_func (info
->stream
, "ep");
190 info
->fprintf_func (info
->stream
, "%ld", value
);
192 case V850_OPERAND_DISP
:
194 bfd_vma addr
= value
+ memaddr
;
196 /* On the v850 the top 8 bits of an address are used by an
197 overlay manager. Thus it may happen that when we are
198 looking for a symbol to match against an address with
199 some of its top bits set, the search fails to turn up an
200 exact match. In this case we try to find an exact match
201 against a symbol in the lower address space, and if we
202 find one, we use that address. We only do this for
203 JARL instructions however, as we do not want to
204 misinterpret branch instructions. */
205 if (operand
->bits
== 22)
207 if ( ! info
->symbol_at_address_func (addr
, info
)
208 && ((addr
& 0xFF000000) != 0)
209 && info
->symbol_at_address_func (addr
& 0x00FFFFFF, info
))
212 info
->print_address_func (addr
, info
);
218 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 };
219 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 };
220 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 };
223 unsigned long int mask
= 0;
227 switch (operand
->shift
)
229 case 0xffe00001: regs
= list12_regs
; break;
230 case 0xfff8000f: regs
= list18_h_regs
; break;
232 regs
= list18_l_regs
;
233 value
&= ~0x10; /* Do not include magic bit. */
236 /* xgettext:c-format */
237 fprintf (stderr
, _("unknown operand shift: %x\n"),
242 for (i
= 0; i
< 32; i
++)
244 if (value
& (1 << i
))
248 default: mask
|= (1 << regs
[ i
]); break;
249 /* xgettext:c-format */
251 fprintf (stderr
, _("unknown pop reg: %d\n"), i
);
253 case -1: pc
= 1; break;
254 case -2: sr
= 1; break;
259 info
->fprintf_func (info
->stream
, "{");
261 if (mask
|| pc
|| sr
)
268 for (bit
= 0; bit
< 32; bit
++)
269 if (mask
& (1 << bit
))
271 unsigned long int first
= bit
;
272 unsigned long int last
;
275 info
->fprintf_func (info
->stream
, ", ");
279 info
->fprintf_func (info
->stream
,
280 v850_reg_names
[first
]);
282 for (bit
++; bit
< 32; bit
++)
283 if ((mask
& (1 << bit
)) == 0)
288 if (last
> first
+ 1)
289 info
->fprintf_func (info
->stream
, " - %s",
290 v850_reg_names
[last
- 1]);
295 info
->fprintf_func (info
->stream
, "%sPC", mask
? ", " : "");
297 info
->fprintf_func (info
->stream
, "%sSR", (mask
|| pc
) ? ", " : "");
300 info
->fprintf_func (info
->stream
, "}");
304 case V850E_IMMEDIATE16
:
305 status
= info
->read_memory_func (memaddr
+ bytes_read
,
310 value
= bfd_getl16 (buffer
);
312 /* If this is a DISPOSE instruction with ff
313 set to 0x10, then shift value up by 16. */
314 if ((insn
& 0x001fffc0) == 0x00130780)
317 info
->fprintf_func (info
->stream
, "0x%lx", value
);
320 info
->memory_error_func (status
, memaddr
+ bytes_read
,
324 case V850E_IMMEDIATE32
:
325 status
= info
->read_memory_func (memaddr
+ bytes_read
,
330 value
= bfd_getl32 (buffer
);
331 info
->fprintf_func (info
->stream
, "0x%lx", value
);
334 info
->memory_error_func (status
, memaddr
+ bytes_read
,
339 /* Handle jmp correctly. */
340 if (memop
== 1 && opnum
== 1
341 && ((operand
->flags
& V850_OPERAND_REG
) != 0))
342 (*info
->fprintf_func
) (info
->stream
, "]");
345 /* Close any square bracket we left open. */
346 if (memop
&& opnum
== memop
+ 2)
347 (*info
->fprintf_func
) (info
->stream
, "]");
358 info
->fprintf_func (info
->stream
, ".short\t0x%04lx", insn
);
360 info
->fprintf_func (info
->stream
, ".long\t0x%08lx", insn
);
367 print_insn_v850 (bfd_vma memaddr
, struct disassemble_info
* info
)
371 unsigned long insn
= 0;
373 /* First figure out how big the opcode is. */
374 status
= info
->read_memory_func (memaddr
, buffer
, 2, info
);
377 insn
= bfd_getl16 (buffer
);
379 if ( (insn
& 0x0600) == 0x0600
380 && (insn
& 0xffe0) != 0x0620)
382 /* If this is a 4 byte insn, read 4 bytes of stuff. */
383 status
= info
->read_memory_func (memaddr
, buffer
, 4, info
);
386 insn
= bfd_getl32 (buffer
);
392 info
->memory_error_func (status
, memaddr
, info
);
396 /* Make sure we tell our caller how many bytes we consumed. */
397 return disassemble (memaddr
, info
, insn
);
This page took 0.037188 seconds and 4 git commands to generate.