1 /* Disassemble V850 instructions.
2 Copyright (C) 1996 Free Software Foundation, Inc.
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.
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.
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. */
22 #include "opcode/v850.h"
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" };
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 /* start-sanitize-v850e */
35 "ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23",
36 "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
37 /* end-sanitize-v850e */
38 "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23",
39 "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31" };
41 static const char *const v850_cc_names
[] =
42 { "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
43 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" };
46 disassemble (memaddr
, info
, insn
)
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 /* start-sanitize-v850e */
59 /* Special case: 32 bit MOV */
60 if ((insn
& 0xffe0) == 0x0620)
62 /* end-sanitize-v850e */
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
;
77 /* start-sanitize-v850e */
79 target_processor
= PROCESSOR_V850E
;
83 target_processor
= PROCESSOR_V850EQ
;
85 /* end-sanitize-v850e */
88 /* Find the opcode. */
91 if ((op
->mask
& insn
) == op
->opcode
92 && (op
->processors
& target_processor
))
94 const unsigned char * opindex_ptr
;
99 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
100 //fprintf (stderr, "match: mask: %x insn: %x, opcode: %x, name: %s\n", op->mask, insn, op->opcode, op->name );
103 /* Now print the operands.
105 MEMOP is the operand number at which a memory
106 address specification starts, or zero if this
107 instruction has no memory addresses.
109 A memory address is always two arguments.
111 This information allows us to determine when to
112 insert commas into the output stream as well as
113 when to insert disp[reg] expressions onto the
116 for (opindex_ptr
= op
->operands
, opnum
= 1;
118 opindex_ptr
++, opnum
++)
123 bfd_byte buffer
[ 4 ];
125 operand
= &v850_operands
[*opindex_ptr
];
127 if (operand
->extract
)
128 value
= (operand
->extract
) (insn
, 0);
131 if (operand
->bits
== -1)
132 value
= (insn
& operand
->shift
);
134 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
136 if (operand
->flags
& V850_OPERAND_SIGNED
)
137 value
= ((long)(value
<< (32 - operand
->bits
))
138 >> (32 - operand
->bits
));
141 /* The first operand is always output without any
144 For the following arguments:
146 If memop && opnum == memop + 1, then we need '[' since
147 we're about to output the register used in a memory
150 If memop && opnum == memop + 2, then we need ']' since
151 we just finished the register in a memory reference. We
152 also need a ',' before this operand.
154 Else we just need a comma.
156 We may need to output a trailing ']' if the last operand
157 in an instruction is the register for a memory address.
159 The exception (and there's always an exception) is the
160 "jmp" insn which needs square brackets around it's only
161 register argument. */
163 if (memop
&& opnum
== memop
+ 1) info
->fprintf_func (info
->stream
, "[");
164 else if (memop
&& opnum
== memop
+ 2) info
->fprintf_func (info
->stream
, "],");
165 else if (memop
== 1 && opnum
== 1
166 && (operand
->flags
& V850_OPERAND_REG
))
167 info
->fprintf_func (info
->stream
, "[");
168 else if (opnum
> 1) info
->fprintf_func (info
->stream
, ", ");
170 /* extract the flags, ignorng ones which do not effect disassembly output. */
171 flag
= operand
->flags
;
172 flag
&= ~ V850_OPERAND_SIGNED
;
173 flag
&= ~ V850_OPERAND_RELAX
;
178 case V850_OPERAND_REG
: info
->fprintf_func (info
->stream
, "%s", v850_reg_names
[value
]); break;
179 case V850_OPERAND_SRG
: info
->fprintf_func (info
->stream
, "%s", v850_sreg_names
[value
]); break;
180 case V850_OPERAND_CC
: info
->fprintf_func (info
->stream
, "%s", v850_cc_names
[value
]); break;
181 case V850_OPERAND_EP
: info
->fprintf_func (info
->stream
, "ep"); break;
182 default: info
->fprintf_func (info
->stream
, "%d", value
); break;
183 case V850_OPERAND_DISP
:
185 bfd_vma addr
= value
+ memaddr
;
187 /* On the v850 the top 8 bits of an address are used by an overlay manager.
188 Thus it may happen that when we are looking for a symbol to match
189 against an address with some of its top bits set, the search fails to
190 turn up an exact match. In this case we try to find an exact match
191 against a symbol in the lower address space, and if we find one, we
192 use that address. We only do this for JARL instructions however, as
193 we do not want to misinterpret branch instructions. */
194 if (operand
->bits
== 22)
196 if ( ! info
->symbol_at_address_func (addr
, info
)
197 && ((addr
& 0xFF000000) != 0)
198 && info
->symbol_at_address_func (addr
& 0x00FFFFFF, info
))
203 info
->print_address_func (addr
, info
);
207 /* start-sanitize-v850e */
210 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 };
211 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 };
212 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 };
215 unsigned long int mask
= 0;
220 switch (operand
->shift
)
222 case 0xffe00001: regs
= list12_regs
; break;
223 case 0xfff8000f: regs
= list18_h_regs
; break;
224 case 0xfff8001f: regs
= list18_l_regs
; value
&= ~0x10; break; /* Do not include magic bit */
226 fprintf (stderr
, "unknown operand shift: %x\n", operand
->shift
);
230 for (i
= 0; i
< 32; i
++)
232 if (value
& (1 << i
))
236 default: mask
|= (1 << regs
[ i
]); break;
237 case 0: fprintf (stderr
, "unknown pop reg: %d\n", i
); abort();
238 case -1: pc
= true; break;
239 case -2: sr
= true; break;
244 info
->fprintf_func (info
->stream
, "{");
246 if (mask
|| pc
|| sr
)
251 int shown_one
= false;
253 for (bit
= 0; bit
< 32; bit
++)
254 if (mask
& (1 << bit
))
256 unsigned long int first
= bit
;
257 unsigned long int last
;
260 info
->fprintf_func (info
->stream
, ", ");
264 info
->fprintf_func (info
->stream
, v850_reg_names
[first
]);
266 for (bit
++; bit
< 32; bit
++)
267 if ((mask
& (1 << bit
)) == 0)
272 if (last
> first
+ 1)
274 info
->fprintf_func (info
->stream
, " - %s", v850_reg_names
[ last
- 1 ]);
280 info
->fprintf_func (info
->stream
, "%sPC", mask
? ", " : "");
282 info
->fprintf_func (info
->stream
, "%sSR", (mask
|| pc
) ? ", " : "");
285 info
->fprintf_func (info
->stream
, "}");
289 case V850E_IMMEDIATE16
:
290 status
= info
->read_memory_func (memaddr
+ bytes_read
, buffer
, 2, info
);
294 value
= bfd_getl16 (buffer
);
296 /* If this is a DISPOSE instruction with ff set to 0x10, then shift value up by 16. */
297 if ((insn
& 0x001fffc0) == 0x00130780)
300 info
->fprintf_func (info
->stream
, "0x%x", value
);
304 info
->memory_error_func (status
, memaddr
+ bytes_read
, info
);
308 case V850E_IMMEDIATE32
:
309 status
= info
->read_memory_func (memaddr
+ bytes_read
, buffer
, 4, info
);
313 value
= bfd_getl32 (buffer
);
314 info
->fprintf_func (info
->stream
, "0x%lx", value
);
318 info
->memory_error_func (status
, memaddr
+ bytes_read
, info
);
321 /* end-sanitize-v850e */
324 /* Handle jmp correctly. */
325 if (memop
== 1 && opnum
== 1
326 && ((operand
->flags
& V850_OPERAND_REG
) != 0))
327 (*info
->fprintf_func
) (info
->stream
, "]");
330 /* Close any square bracket we left open. */
331 if (memop
&& opnum
== memop
+ 2)
332 (*info
->fprintf_func
) (info
->stream
, "]");
343 info
->fprintf_func (info
->stream
, ".short\t0x%04x", insn
);
345 info
->fprintf_func (info
->stream
, ".long\t0x%08x", insn
);
352 print_insn_v850 (memaddr
, info
)
354 struct disassemble_info
* info
;
357 bfd_byte buffer
[ 4 ];
360 /* First figure out how big the opcode is. */
362 status
= info
->read_memory_func (memaddr
, buffer
, 2, info
);
365 insn
= bfd_getl16 (buffer
);
367 if ( (insn
& 0x0600) == 0x0600
368 && (insn
& 0xffe0) != 0x0620)
370 /* If this is a 4 byte insn, read 4 bytes of stuff. */
371 status
= info
->read_memory_func (memaddr
, buffer
, 4, info
);
374 insn
= bfd_getl32 (buffer
);
380 info
->memory_error_func (status
, memaddr
, info
);
384 /* Make sure we tell our caller how many bytes we consumed. */
385 return disassemble (memaddr
, info
, insn
);