1 /* Disassemble V850 instructions.
2 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007
3 Free Software Foundation, Inc.
5 This file is part of the GNU opcodes library.
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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.
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
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
26 #include "opcode/v850.h"
30 static const char *const v850_reg_names
[] =
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",
34 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" };
36 static const char *const v850_sreg_names
[] =
37 { "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7",
38 "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
39 "ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23",
40 "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
41 "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23",
42 "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31" };
44 static const char *const v850_cc_names
[] =
45 { "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
46 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" };
49 disassemble (bfd_vma memaddr
,
50 struct disassemble_info
* info
,
53 struct v850_opcode
* op
= (struct v850_opcode
*) v850_opcodes
;
54 const struct v850_operand
* operand
;
56 int short_op
= ((insn
& 0x0600) != 0x0600);
60 /* Special case: 32 bit MOV. */
61 if ((insn
& 0xffe0) == 0x0620)
64 bytes_read
= short_op
? 2 : 4;
66 /* If this is a two byte insn, then mask off the high bits. */
74 target_processor
= PROCESSOR_V850
;
78 target_processor
= PROCESSOR_V850E
;
82 target_processor
= PROCESSOR_V850E1
;
86 /* Find the opcode. */
89 if ((op
->mask
& insn
) == op
->opcode
90 && (op
->processors
& target_processor
))
92 const unsigned char *opindex_ptr
;
97 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
100 /* Now print the operands.
102 MEMOP is the operand number at which a memory
103 address specification starts, or zero if this
104 instruction has no memory addresses.
106 A memory address is always two arguments.
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
113 for (opindex_ptr
= op
->operands
, opnum
= 1;
115 opindex_ptr
++, opnum
++)
122 operand
= &v850_operands
[*opindex_ptr
];
124 if (operand
->extract
)
125 value
= (operand
->extract
) (insn
, 0);
128 if (operand
->bits
== -1)
129 value
= (insn
& operand
->shift
);
131 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
133 if (operand
->flags
& V850_OPERAND_SIGNED
)
134 value
= ((long)(value
<< (32 - operand
->bits
))
135 >> (32 - operand
->bits
));
138 /* The first operand is always output without any
141 For the following arguments:
143 If memop && opnum == memop + 1, then we need '[' since
144 we're about to output the register used in a memory
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.
151 Else we just need a comma.
153 We may need to output a trailing ']' if the last operand
154 in an instruction is the register for a memory address.
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. */
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
, "[");
168 info
->fprintf_func (info
->stream
, ", ");
170 /* Extract the flags, ignorng ones which
171 do not effect disassembly output. */
172 flag
= operand
->flags
;
173 flag
&= ~ V850_OPERAND_SIGNED
;
174 flag
&= ~ V850_OPERAND_RELAX
;
179 case V850_OPERAND_REG
:
180 info
->fprintf_func (info
->stream
, "%s", v850_reg_names
[value
]);
182 case V850_OPERAND_SRG
:
183 info
->fprintf_func (info
->stream
, "%s", v850_sreg_names
[value
]);
185 case V850_OPERAND_CC
:
186 info
->fprintf_func (info
->stream
, "%s", v850_cc_names
[value
]);
188 case V850_OPERAND_EP
:
189 info
->fprintf_func (info
->stream
, "ep");
192 info
->fprintf_func (info
->stream
, "%ld", value
);
194 case V850_OPERAND_DISP
:
196 bfd_vma addr
= value
+ memaddr
;
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. */
207 if (operand
->bits
== 22)
209 if ( ! info
->symbol_at_address_func (addr
, info
)
210 && ((addr
& 0xFF000000) != 0)
211 && info
->symbol_at_address_func (addr
& 0x00FFFFFF, info
))
214 info
->print_address_func (addr
, info
);
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 };
225 unsigned long int mask
= 0;
229 switch (operand
->shift
)
231 case 0xffe00001: regs
= list12_regs
; break;
232 case 0xfff8000f: regs
= list18_h_regs
; break;
234 regs
= list18_l_regs
;
235 value
&= ~0x10; /* Do not include magic bit. */
238 /* xgettext:c-format */
239 fprintf (stderr
, _("unknown operand shift: %x\n"),
244 for (i
= 0; i
< 32; i
++)
246 if (value
& (1 << i
))
250 default: mask
|= (1 << regs
[ i
]); break;
251 /* xgettext:c-format */
253 fprintf (stderr
, _("unknown pop reg: %d\n"), i
);
255 case -1: pc
= 1; break;
256 case -2: sr
= 1; break;
261 info
->fprintf_func (info
->stream
, "{");
263 if (mask
|| pc
|| sr
)
270 for (bit
= 0; bit
< 32; bit
++)
271 if (mask
& (1 << bit
))
273 unsigned long int first
= bit
;
274 unsigned long int last
;
277 info
->fprintf_func (info
->stream
, ", ");
281 info
->fprintf_func (info
->stream
,
282 v850_reg_names
[first
]);
284 for (bit
++; bit
< 32; bit
++)
285 if ((mask
& (1 << bit
)) == 0)
290 if (last
> first
+ 1)
291 info
->fprintf_func (info
->stream
, " - %s",
292 v850_reg_names
[last
- 1]);
297 info
->fprintf_func (info
->stream
, "%sPC", mask
? ", " : "");
299 info
->fprintf_func (info
->stream
, "%sSR", (mask
|| pc
) ? ", " : "");
302 info
->fprintf_func (info
->stream
, "}");
306 case V850E_IMMEDIATE16
:
307 status
= info
->read_memory_func (memaddr
+ bytes_read
,
312 value
= bfd_getl16 (buffer
);
314 /* If this is a DISPOSE instruction with ff
315 set to 0x10, then shift value up by 16. */
316 if ((insn
& 0x001fffc0) == 0x00130780)
319 info
->fprintf_func (info
->stream
, "0x%lx", value
);
322 info
->memory_error_func (status
, memaddr
+ bytes_read
,
326 case V850E_IMMEDIATE32
:
327 status
= info
->read_memory_func (memaddr
+ bytes_read
,
332 value
= bfd_getl32 (buffer
);
333 info
->fprintf_func (info
->stream
, "0x%lx", value
);
336 info
->memory_error_func (status
, memaddr
+ bytes_read
,
341 /* Handle jmp correctly. */
342 if (memop
== 1 && opnum
== 1
343 && ((operand
->flags
& V850_OPERAND_REG
) != 0))
344 (*info
->fprintf_func
) (info
->stream
, "]");
347 /* Close any square bracket we left open. */
348 if (memop
&& opnum
== memop
+ 2)
349 (*info
->fprintf_func
) (info
->stream
, "]");
360 info
->fprintf_func (info
->stream
, ".short\t0x%04lx", insn
);
362 info
->fprintf_func (info
->stream
, ".long\t0x%08lx", insn
);
369 print_insn_v850 (bfd_vma memaddr
, struct disassemble_info
* info
)
373 unsigned long insn
= 0;
375 /* First figure out how big the opcode is. */
376 status
= info
->read_memory_func (memaddr
, buffer
, 2, info
);
379 insn
= bfd_getl16 (buffer
);
381 if ( (insn
& 0x0600) == 0x0600
382 && (insn
& 0xffe0) != 0x0620)
384 /* If this is a 4 byte insn, read 4 bytes of stuff. */
385 status
= info
->read_memory_func (memaddr
, buffer
, 4, info
);
388 insn
= bfd_getl32 (buffer
);
394 info
->memory_error_func (status
, memaddr
, info
);
398 /* Make sure we tell our caller how many bytes we consumed. */
399 return disassemble (memaddr
, info
, insn
);