v850-dis.c revision 1.1.1.8 1 1.1 christos /* Disassemble V850 instructions.
2 1.1.1.8 christos Copyright (C) 1996-2020 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of the GNU opcodes library.
5 1.1 christos
6 1.1 christos This library is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3, or (at your option)
9 1.1 christos any later version.
10 1.1 christos
11 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
12 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 1.1 christos License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; if not, write to the Free Software
18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 1.1 christos MA 02110-1301, USA. */
20 1.1 christos
21 1.1 christos
22 1.1 christos #include "sysdep.h"
23 1.1.1.2 christos #include <stdio.h>
24 1.1.1.2 christos #include <string.h>
25 1.1 christos #include "opcode/v850.h"
26 1.1.1.7 christos #include "disassemble.h"
27 1.1 christos #include "opintl.h"
28 1.1.1.8 christos #include "libiberty.h"
29 1.1.1.2 christos
30 1.1.1.3 christos static const int v850_cacheop_codes[] =
31 1.1.1.2 christos {
32 1.1.1.2 christos 0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06,
33 1.1.1.2 christos 0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1
34 1.1.1.2 christos };
35 1.1.1.2 christos
36 1.1.1.3 christos static const int v850_prefop_codes[] =
37 1.1.1.2 christos { 0x00, 0x04, -1};
38 1.1.1.2 christos
39 1.1 christos static void
40 1.1.1.2 christos print_value (int flags,
41 1.1.1.2 christos bfd_vma memaddr,
42 1.1.1.2 christos struct disassemble_info *info,
43 1.1.1.2 christos long value)
44 1.1 christos {
45 1.1 christos if (flags & V850_PCREL)
46 1.1 christos {
47 1.1 christos bfd_vma addr = value + memaddr;
48 1.1.1.3 christos
49 1.1.1.3 christos if (flags & V850_INVERSE_PCREL)
50 1.1.1.3 christos addr = memaddr - value;
51 1.1 christos info->print_address_func (addr, info);
52 1.1 christos }
53 1.1 christos else if (flags & V850_OPERAND_DISP)
54 1.1 christos {
55 1.1 christos if (flags & V850_OPERAND_SIGNED)
56 1.1 christos {
57 1.1 christos info->fprintf_func (info->stream, "%ld", value);
58 1.1 christos }
59 1.1 christos else
60 1.1 christos {
61 1.1 christos info->fprintf_func (info->stream, "%lu", value);
62 1.1 christos }
63 1.1 christos }
64 1.1.1.2 christos else if ((flags & V850E_IMMEDIATE32)
65 1.1.1.2 christos || (flags & V850E_IMMEDIATE16HI))
66 1.1 christos {
67 1.1 christos info->fprintf_func (info->stream, "0x%lx", value);
68 1.1 christos }
69 1.1 christos else
70 1.1 christos {
71 1.1 christos if (flags & V850_OPERAND_SIGNED)
72 1.1 christos {
73 1.1 christos info->fprintf_func (info->stream, "%ld", value);
74 1.1 christos }
75 1.1 christos else
76 1.1 christos {
77 1.1 christos info->fprintf_func (info->stream, "%lu", value);
78 1.1 christos }
79 1.1 christos }
80 1.1 christos }
81 1.1 christos
82 1.1 christos static long
83 1.1 christos get_operand_value (const struct v850_operand *operand,
84 1.1 christos unsigned long insn,
85 1.1 christos int bytes_read,
86 1.1 christos bfd_vma memaddr,
87 1.1 christos struct disassemble_info * info,
88 1.1 christos bfd_boolean noerror,
89 1.1 christos int *invalid)
90 1.1 christos {
91 1.1.1.8 christos unsigned long value;
92 1.1 christos bfd_byte buffer[4];
93 1.1 christos
94 1.1 christos if ((operand->flags & V850E_IMMEDIATE16)
95 1.1 christos || (operand->flags & V850E_IMMEDIATE16HI))
96 1.1 christos {
97 1.1 christos int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
98 1.1 christos
99 1.1 christos if (status == 0)
100 1.1 christos {
101 1.1 christos value = bfd_getl16 (buffer);
102 1.1 christos
103 1.1 christos if (operand->flags & V850E_IMMEDIATE16HI)
104 1.1 christos value <<= 16;
105 1.1.1.2 christos else if (value & 0x8000)
106 1.1.1.5 christos value |= (-1UL << 16);
107 1.1 christos
108 1.1 christos return value;
109 1.1 christos }
110 1.1 christos
111 1.1 christos if (!noerror)
112 1.1 christos info->memory_error_func (status, memaddr + bytes_read, info);
113 1.1 christos
114 1.1 christos return 0;
115 1.1 christos }
116 1.1 christos
117 1.1 christos if (operand->flags & V850E_IMMEDIATE23)
118 1.1 christos {
119 1.1 christos int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
120 1.1 christos
121 1.1 christos if (status == 0)
122 1.1 christos {
123 1.1 christos value = bfd_getl32 (buffer);
124 1.1 christos
125 1.1 christos value = (operand->extract) (value, invalid);
126 1.1 christos
127 1.1 christos return value;
128 1.1 christos }
129 1.1 christos
130 1.1 christos if (!noerror)
131 1.1 christos info->memory_error_func (status, memaddr + bytes_read, info);
132 1.1 christos
133 1.1 christos return 0;
134 1.1 christos }
135 1.1 christos
136 1.1 christos if (operand->flags & V850E_IMMEDIATE32)
137 1.1 christos {
138 1.1 christos int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
139 1.1 christos
140 1.1 christos if (status == 0)
141 1.1 christos {
142 1.1 christos bytes_read += 4;
143 1.1 christos value = bfd_getl32 (buffer);
144 1.1 christos
145 1.1 christos return value;
146 1.1 christos }
147 1.1 christos
148 1.1 christos if (!noerror)
149 1.1 christos info->memory_error_func (status, memaddr + bytes_read, info);
150 1.1 christos
151 1.1 christos return 0;
152 1.1 christos }
153 1.1 christos
154 1.1 christos if (operand->extract)
155 1.1 christos value = (operand->extract) (insn, invalid);
156 1.1 christos else
157 1.1 christos {
158 1.1 christos if (operand->bits == -1)
159 1.1 christos value = (insn & operand->shift);
160 1.1 christos else
161 1.1.1.8 christos value = (insn >> operand->shift) & ((1ul << operand->bits) - 1);
162 1.1 christos
163 1.1 christos if (operand->flags & V850_OPERAND_SIGNED)
164 1.1.1.8 christos {
165 1.1.1.8 christos unsigned long sign = 1ul << (operand->bits - 1);
166 1.1.1.8 christos value = (value ^ sign) - sign;
167 1.1.1.8 christos }
168 1.1 christos }
169 1.1 christos
170 1.1 christos return value;
171 1.1 christos }
172 1.1 christos
173 1.1.1.8 christos static const char *
174 1.1.1.8 christos get_v850_sreg_name (unsigned int reg)
175 1.1.1.8 christos {
176 1.1.1.8 christos static const char *const v850_sreg_names[] =
177 1.1.1.8 christos {
178 1.1.1.8 christos "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
179 1.1.1.8 christos "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
180 1.1.1.8 christos "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
181 1.1.1.8 christos "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
182 1.1.1.8 christos "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
183 1.1.1.8 christos "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
184 1.1.1.8 christos "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
185 1.1.1.8 christos "fewr", "dbwr", "bsel"
186 1.1.1.8 christos };
187 1.1.1.8 christos
188 1.1.1.8 christos if (reg < ARRAY_SIZE (v850_sreg_names))
189 1.1.1.8 christos return v850_sreg_names[reg];
190 1.1.1.8 christos return _("<invalid s-reg number>");
191 1.1.1.8 christos }
192 1.1.1.8 christos
193 1.1.1.8 christos static const char *
194 1.1.1.8 christos get_v850_reg_name (unsigned int reg)
195 1.1.1.8 christos {
196 1.1.1.8 christos static const char *const v850_reg_names[] =
197 1.1.1.8 christos {
198 1.1.1.8 christos "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
199 1.1.1.8 christos "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
200 1.1.1.8 christos "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
201 1.1.1.8 christos "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
202 1.1.1.8 christos };
203 1.1.1.8 christos
204 1.1.1.8 christos if (reg < ARRAY_SIZE (v850_reg_names))
205 1.1.1.8 christos return v850_reg_names[reg];
206 1.1.1.8 christos return _("<invalid reg number>");
207 1.1.1.8 christos }
208 1.1.1.8 christos
209 1.1.1.8 christos static const char *
210 1.1.1.8 christos get_v850_vreg_name (unsigned int reg)
211 1.1.1.8 christos {
212 1.1.1.8 christos static const char *const v850_vreg_names[] =
213 1.1.1.8 christos {
214 1.1.1.8 christos "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9",
215 1.1.1.8 christos "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18",
216 1.1.1.8 christos "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27",
217 1.1.1.8 christos "vr28", "vr29", "vr30", "vr31"
218 1.1.1.8 christos };
219 1.1.1.8 christos
220 1.1.1.8 christos if (reg < ARRAY_SIZE (v850_vreg_names))
221 1.1.1.8 christos return v850_vreg_names[reg];
222 1.1.1.8 christos return _("<invalid v-reg number>");
223 1.1.1.8 christos }
224 1.1.1.8 christos
225 1.1.1.8 christos static const char *
226 1.1.1.8 christos get_v850_cc_name (unsigned int reg)
227 1.1.1.8 christos {
228 1.1.1.8 christos static const char *const v850_cc_names[] =
229 1.1.1.8 christos {
230 1.1.1.8 christos "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
231 1.1.1.8 christos "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
232 1.1.1.8 christos };
233 1.1.1.8 christos
234 1.1.1.8 christos if (reg < ARRAY_SIZE (v850_cc_names))
235 1.1.1.8 christos return v850_cc_names[reg];
236 1.1.1.8 christos return _("<invalid CC-reg number>");
237 1.1.1.8 christos }
238 1.1.1.8 christos
239 1.1.1.8 christos static const char *
240 1.1.1.8 christos get_v850_float_cc_name (unsigned int reg)
241 1.1.1.8 christos {
242 1.1.1.8 christos static const char *const v850_float_cc_names[] =
243 1.1.1.8 christos {
244 1.1.1.8 christos "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
245 1.1.1.8 christos "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
246 1.1.1.8 christos };
247 1.1.1.8 christos
248 1.1.1.8 christos if (reg < ARRAY_SIZE (v850_float_cc_names))
249 1.1.1.8 christos return v850_float_cc_names[reg];
250 1.1.1.8 christos return _("<invalid float-CC-reg number>");
251 1.1.1.8 christos }
252 1.1.1.8 christos
253 1.1.1.8 christos static const char *
254 1.1.1.8 christos get_v850_cacheop_name (unsigned int reg)
255 1.1.1.8 christos {
256 1.1.1.8 christos static const char *const v850_cacheop_names[] =
257 1.1.1.8 christos {
258 1.1.1.8 christos "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd",
259 1.1.1.8 christos "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd"
260 1.1.1.8 christos };
261 1.1.1.8 christos
262 1.1.1.8 christos if (reg < ARRAY_SIZE (v850_cacheop_names))
263 1.1.1.8 christos return v850_cacheop_names[reg];
264 1.1.1.8 christos return _("<invalid cacheop number>");
265 1.1.1.8 christos }
266 1.1.1.8 christos
267 1.1.1.8 christos static const char *
268 1.1.1.8 christos get_v850_prefop_name (unsigned int reg)
269 1.1.1.8 christos {
270 1.1.1.8 christos static const char *const v850_prefop_names[] =
271 1.1.1.8 christos { "prefi", "prefd" };
272 1.1.1.8 christos
273 1.1.1.8 christos if (reg < ARRAY_SIZE (v850_prefop_names))
274 1.1.1.8 christos return v850_prefop_names[reg];
275 1.1.1.8 christos return _("<invalid prefop number>");
276 1.1.1.8 christos }
277 1.1 christos
278 1.1 christos static int
279 1.1.1.2 christos disassemble (bfd_vma memaddr,
280 1.1.1.2 christos struct disassemble_info *info,
281 1.1.1.2 christos int bytes_read,
282 1.1.1.2 christos unsigned long insn)
283 1.1 christos {
284 1.1.1.2 christos struct v850_opcode *op = (struct v850_opcode *) v850_opcodes;
285 1.1 christos const struct v850_operand *operand;
286 1.1 christos int match = 0;
287 1.1 christos int target_processor;
288 1.1 christos
289 1.1 christos switch (info->mach)
290 1.1 christos {
291 1.1 christos case 0:
292 1.1 christos default:
293 1.1 christos target_processor = PROCESSOR_V850;
294 1.1 christos break;
295 1.1 christos
296 1.1 christos case bfd_mach_v850e:
297 1.1 christos target_processor = PROCESSOR_V850E;
298 1.1 christos break;
299 1.1 christos
300 1.1 christos case bfd_mach_v850e1:
301 1.1 christos target_processor = PROCESSOR_V850E;
302 1.1 christos break;
303 1.1 christos
304 1.1 christos case bfd_mach_v850e2:
305 1.1 christos target_processor = PROCESSOR_V850E2;
306 1.1 christos break;
307 1.1 christos
308 1.1 christos case bfd_mach_v850e2v3:
309 1.1 christos target_processor = PROCESSOR_V850E2V3;
310 1.1 christos break;
311 1.1.1.2 christos
312 1.1.1.2 christos case bfd_mach_v850e3v5:
313 1.1.1.2 christos target_processor = PROCESSOR_V850E3V5;
314 1.1.1.2 christos break;
315 1.1 christos }
316 1.1 christos
317 1.1 christos /* If this is a two byte insn, then mask off the high bits. */
318 1.1 christos if (bytes_read == 2)
319 1.1 christos insn &= 0xffff;
320 1.1 christos
321 1.1 christos /* Find the opcode. */
322 1.1 christos while (op->name)
323 1.1 christos {
324 1.1 christos if ((op->mask & insn) == op->opcode
325 1.1 christos && (op->processors & target_processor)
326 1.1 christos && !(op->processors & PROCESSOR_OPTION_ALIAS))
327 1.1 christos {
328 1.1 christos /* Code check start. */
329 1.1 christos const unsigned char *opindex_ptr;
330 1.1 christos unsigned int opnum;
331 1.1 christos unsigned int memop;
332 1.1 christos
333 1.1 christos for (opindex_ptr = op->operands, opnum = 1;
334 1.1 christos *opindex_ptr != 0;
335 1.1 christos opindex_ptr++, opnum++)
336 1.1 christos {
337 1.1 christos int invalid = 0;
338 1.1 christos long value;
339 1.1 christos
340 1.1 christos operand = &v850_operands[*opindex_ptr];
341 1.1 christos
342 1.1.1.2 christos value = get_operand_value (operand, insn, bytes_read, memaddr,
343 1.1.1.2 christos info, 1, &invalid);
344 1.1 christos
345 1.1 christos if (invalid)
346 1.1 christos goto next_opcode;
347 1.1 christos
348 1.1 christos if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
349 1.1 christos goto next_opcode;
350 1.1 christos
351 1.1 christos if ((operand->flags & V850_NOT_SA) && value == 0xd)
352 1.1 christos goto next_opcode;
353 1.1 christos
354 1.1 christos if ((operand->flags & V850_NOT_IMM0) && value == 0)
355 1.1 christos goto next_opcode;
356 1.1 christos }
357 1.1 christos
358 1.1 christos /* Code check end. */
359 1.1 christos
360 1.1 christos match = 1;
361 1.1 christos (*info->fprintf_func) (info->stream, "%s\t", op->name);
362 1.1 christos #if 0
363 1.1 christos fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
364 1.1 christos insn, op->mask, op->opcode, op->name );
365 1.1 christos #endif
366 1.1 christos
367 1.1 christos memop = op->memop;
368 1.1 christos /* Now print the operands.
369 1.1 christos
370 1.1 christos MEMOP is the operand number at which a memory
371 1.1 christos address specification starts, or zero if this
372 1.1 christos instruction has no memory addresses.
373 1.1 christos
374 1.1 christos A memory address is always two arguments.
375 1.1 christos
376 1.1 christos This information allows us to determine when to
377 1.1 christos insert commas into the output stream as well as
378 1.1 christos when to insert disp[reg] expressions onto the
379 1.1 christos output stream. */
380 1.1 christos
381 1.1 christos for (opindex_ptr = op->operands, opnum = 1;
382 1.1 christos *opindex_ptr != 0;
383 1.1 christos opindex_ptr++, opnum++)
384 1.1 christos {
385 1.1.1.2 christos bfd_boolean square = FALSE;
386 1.1 christos long value;
387 1.1 christos int flag;
388 1.1 christos char *prefix;
389 1.1 christos
390 1.1 christos operand = &v850_operands[*opindex_ptr];
391 1.1 christos
392 1.1.1.2 christos value = get_operand_value (operand, insn, bytes_read, memaddr,
393 1.1.1.2 christos info, 0, 0);
394 1.1 christos
395 1.1 christos /* The first operand is always output without any
396 1.1 christos special handling.
397 1.1 christos
398 1.1 christos For the following arguments:
399 1.1 christos
400 1.1 christos If memop && opnum == memop + 1, then we need '[' since
401 1.1 christos we're about to output the register used in a memory
402 1.1 christos reference.
403 1.1 christos
404 1.1 christos If memop && opnum == memop + 2, then we need ']' since
405 1.1 christos we just finished the register in a memory reference. We
406 1.1 christos also need a ',' before this operand.
407 1.1 christos
408 1.1 christos Else we just need a comma.
409 1.1 christos
410 1.1 christos We may need to output a trailing ']' if the last operand
411 1.1 christos in an instruction is the register for a memory address.
412 1.1 christos
413 1.1.1.2 christos The exception (and there's always an exception) are the
414 1.1 christos "jmp" insn which needs square brackets around it's only
415 1.1.1.2 christos register argument, and the clr1/not1/set1/tst1 insns
416 1.1.1.2 christos which [...] around their second register argument. */
417 1.1.1.2 christos
418 1.1 christos prefix = "";
419 1.1 christos if (operand->flags & V850_OPERAND_BANG)
420 1.1 christos {
421 1.1 christos prefix = "!";
422 1.1 christos }
423 1.1 christos else if (operand->flags & V850_OPERAND_PERCENT)
424 1.1 christos {
425 1.1 christos prefix = "%";
426 1.1 christos }
427 1.1 christos
428 1.1 christos if (opnum == 1 && opnum == memop)
429 1.1.1.2 christos {
430 1.1.1.2 christos info->fprintf_func (info->stream, "%s[", prefix);
431 1.1.1.2 christos square = TRUE;
432 1.1.1.2 christos }
433 1.1.1.2 christos else if ( (strcmp ("stc.w", op->name) == 0
434 1.1.1.2 christos || strcmp ("cache", op->name) == 0
435 1.1.1.2 christos || strcmp ("pref", op->name) == 0)
436 1.1.1.2 christos && opnum == 2 && opnum == memop)
437 1.1.1.2 christos {
438 1.1.1.2 christos info->fprintf_func (info->stream, ", [");
439 1.1.1.2 christos square = TRUE;
440 1.1.1.2 christos }
441 1.1.1.2 christos else if ( (strcmp (op->name, "pushsp") == 0
442 1.1.1.2 christos || strcmp (op->name, "popsp") == 0
443 1.1.1.2 christos || strcmp (op->name, "dbpush" ) == 0)
444 1.1.1.2 christos && opnum == 2)
445 1.1.1.2 christos {
446 1.1.1.2 christos info->fprintf_func (info->stream, "-");
447 1.1.1.2 christos }
448 1.1 christos else if (opnum > 1
449 1.1.1.2 christos && (v850_operands[*(opindex_ptr - 1)].flags
450 1.1.1.2 christos & V850_OPERAND_DISP) != 0
451 1.1 christos && opnum == memop)
452 1.1.1.2 christos {
453 1.1.1.2 christos info->fprintf_func (info->stream, "%s[", prefix);
454 1.1.1.2 christos square = TRUE;
455 1.1.1.2 christos }
456 1.1.1.2 christos else if (opnum == 2
457 1.1.1.2 christos && ( op->opcode == 0x00e407e0 /* clr1 */
458 1.1.1.2 christos || op->opcode == 0x00e207e0 /* not1 */
459 1.1.1.2 christos || op->opcode == 0x00e007e0 /* set1 */
460 1.1.1.2 christos || op->opcode == 0x00e607e0 /* tst1 */
461 1.1.1.2 christos ))
462 1.1.1.2 christos {
463 1.1.1.2 christos info->fprintf_func (info->stream, ", %s[", prefix);
464 1.1.1.2 christos square = TRUE;
465 1.1.1.3 christos }
466 1.1 christos else if (opnum > 1)
467 1.1 christos info->fprintf_func (info->stream, ", %s", prefix);
468 1.1 christos
469 1.1.1.2 christos /* Extract the flags, ignoring ones which do not
470 1.1.1.2 christos effect disassembly output. */
471 1.1 christos flag = operand->flags & (V850_OPERAND_REG
472 1.1 christos | V850_REG_EVEN
473 1.1 christos | V850_OPERAND_EP
474 1.1 christos | V850_OPERAND_SRG
475 1.1 christos | V850E_OPERAND_REG_LIST
476 1.1 christos | V850_OPERAND_CC
477 1.1.1.2 christos | V850_OPERAND_VREG
478 1.1.1.2 christos | V850_OPERAND_CACHEOP
479 1.1.1.2 christos | V850_OPERAND_PREFOP
480 1.1 christos | V850_OPERAND_FLOAT_CC);
481 1.1 christos
482 1.1 christos switch (flag)
483 1.1 christos {
484 1.1.1.2 christos case V850_OPERAND_REG:
485 1.1.1.8 christos info->fprintf_func (info->stream, "%s", get_v850_reg_name (value));
486 1.1.1.2 christos break;
487 1.1.1.2 christos case (V850_OPERAND_REG|V850_REG_EVEN):
488 1.1.1.8 christos info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2));
489 1.1.1.2 christos break;
490 1.1.1.2 christos case V850_OPERAND_EP:
491 1.1.1.2 christos info->fprintf_func (info->stream, "ep");
492 1.1.1.2 christos break;
493 1.1.1.2 christos case V850_OPERAND_SRG:
494 1.1.1.8 christos info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value));
495 1.1.1.2 christos break;
496 1.1 christos case V850E_OPERAND_REG_LIST:
497 1.1 christos {
498 1.1 christos static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
499 1.1 christos 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
500 1.1 christos int *regs;
501 1.1 christos int i;
502 1.1.1.8 christos unsigned int mask = 0;
503 1.1 christos int pc = 0;
504 1.1 christos
505 1.1 christos switch (operand->shift)
506 1.1 christos {
507 1.1 christos case 0xffe00001: regs = list12_regs; break;
508 1.1 christos default:
509 1.1 christos /* xgettext:c-format */
510 1.1.1.7 christos opcodes_error_handler (_("unknown operand shift: %x"),
511 1.1.1.7 christos operand->shift);
512 1.1 christos abort ();
513 1.1 christos }
514 1.1 christos
515 1.1 christos for (i = 0; i < 32; i++)
516 1.1 christos {
517 1.1.1.8 christos if (value & (1u << i))
518 1.1 christos {
519 1.1 christos switch (regs[ i ])
520 1.1 christos {
521 1.1.1.7 christos default:
522 1.1.1.8 christos mask |= (1u << regs[ i ]);
523 1.1.1.7 christos break;
524 1.1.1.7 christos case 0:
525 1.1 christos /* xgettext:c-format */
526 1.1.1.7 christos opcodes_error_handler (_("unknown reg: %d"), i);
527 1.1.1.7 christos abort ();
528 1.1.1.7 christos break;
529 1.1.1.7 christos case -1:
530 1.1.1.7 christos pc = 1;
531 1.1.1.7 christos break;
532 1.1 christos }
533 1.1 christos }
534 1.1 christos }
535 1.1 christos
536 1.1 christos info->fprintf_func (info->stream, "{");
537 1.1 christos
538 1.1 christos if (mask || pc)
539 1.1 christos {
540 1.1 christos if (mask)
541 1.1 christos {
542 1.1 christos unsigned int bit;
543 1.1 christos int shown_one = 0;
544 1.1 christos
545 1.1 christos for (bit = 0; bit < 32; bit++)
546 1.1.1.8 christos if (mask & (1u << bit))
547 1.1 christos {
548 1.1.1.8 christos unsigned int first = bit;
549 1.1.1.8 christos unsigned int last;
550 1.1 christos
551 1.1 christos if (shown_one)
552 1.1 christos info->fprintf_func (info->stream, ", ");
553 1.1 christos else
554 1.1 christos shown_one = 1;
555 1.1 christos
556 1.1.1.8 christos info->fprintf_func (info->stream, "%s", get_v850_reg_name (first));
557 1.1 christos
558 1.1 christos for (bit++; bit < 32; bit++)
559 1.1.1.8 christos if ((mask & (1u << bit)) == 0)
560 1.1 christos break;
561 1.1 christos
562 1.1 christos last = bit;
563 1.1 christos
564 1.1 christos if (last > first + 1)
565 1.1 christos {
566 1.1.1.8 christos info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1));
567 1.1 christos }
568 1.1 christos }
569 1.1 christos }
570 1.1 christos
571 1.1 christos if (pc)
572 1.1 christos info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
573 1.1 christos }
574 1.1 christos
575 1.1 christos info->fprintf_func (info->stream, "}");
576 1.1 christos }
577 1.1 christos break;
578 1.1 christos
579 1.1.1.2 christos case V850_OPERAND_CC:
580 1.1.1.8 christos info->fprintf_func (info->stream, "%s", get_v850_cc_name (value));
581 1.1.1.2 christos break;
582 1.1.1.2 christos
583 1.1.1.2 christos case V850_OPERAND_FLOAT_CC:
584 1.1.1.8 christos info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value));
585 1.1.1.2 christos break;
586 1.1.1.2 christos
587 1.1.1.2 christos case V850_OPERAND_CACHEOP:
588 1.1.1.2 christos {
589 1.1.1.2 christos int idx;
590 1.1.1.2 christos
591 1.1.1.2 christos for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
592 1.1.1.2 christos {
593 1.1.1.2 christos if (value == v850_cacheop_codes[idx])
594 1.1.1.2 christos {
595 1.1.1.2 christos info->fprintf_func (info->stream, "%s",
596 1.1.1.8 christos get_v850_cacheop_name (idx));
597 1.1.1.2 christos goto MATCH_CACHEOP_CODE;
598 1.1.1.2 christos }
599 1.1.1.2 christos }
600 1.1.1.2 christos info->fprintf_func (info->stream, "%d", (int) value);
601 1.1.1.2 christos }
602 1.1.1.2 christos MATCH_CACHEOP_CODE:
603 1.1.1.2 christos break;
604 1.1.1.2 christos
605 1.1.1.2 christos case V850_OPERAND_PREFOP:
606 1.1.1.2 christos {
607 1.1.1.2 christos int idx;
608 1.1.1.2 christos
609 1.1.1.2 christos for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
610 1.1.1.2 christos {
611 1.1.1.2 christos if (value == v850_prefop_codes[idx])
612 1.1.1.2 christos {
613 1.1.1.2 christos info->fprintf_func (info->stream, "%s",
614 1.1.1.8 christos get_v850_prefop_name (idx));
615 1.1.1.2 christos goto MATCH_PREFOP_CODE;
616 1.1.1.2 christos }
617 1.1.1.2 christos }
618 1.1.1.2 christos info->fprintf_func (info->stream, "%d", (int) value);
619 1.1.1.2 christos }
620 1.1.1.2 christos MATCH_PREFOP_CODE:
621 1.1.1.2 christos break;
622 1.1.1.2 christos
623 1.1.1.2 christos case V850_OPERAND_VREG:
624 1.1.1.8 christos info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value));
625 1.1.1.2 christos break;
626 1.1 christos
627 1.1 christos default:
628 1.1 christos print_value (operand->flags, memaddr, info, value);
629 1.1 christos break;
630 1.1 christos }
631 1.1 christos
632 1.1.1.2 christos if (square)
633 1.1 christos (*info->fprintf_func) (info->stream, "]");
634 1.1 christos }
635 1.1 christos
636 1.1 christos /* All done. */
637 1.1 christos break;
638 1.1 christos }
639 1.1 christos next_opcode:
640 1.1 christos op++;
641 1.1 christos }
642 1.1 christos
643 1.1 christos return match;
644 1.1 christos }
645 1.1 christos
646 1.1 christos int
647 1.1 christos print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
648 1.1 christos {
649 1.1 christos int status, status2, match;
650 1.1 christos bfd_byte buffer[8];
651 1.1 christos int length = 0, code_length = 0;
652 1.1 christos unsigned long insn = 0, insn2 = 0;
653 1.1 christos int target_processor;
654 1.1 christos
655 1.1 christos switch (info->mach)
656 1.1 christos {
657 1.1 christos case 0:
658 1.1 christos default:
659 1.1 christos target_processor = PROCESSOR_V850;
660 1.1 christos break;
661 1.1 christos
662 1.1 christos case bfd_mach_v850e:
663 1.1 christos target_processor = PROCESSOR_V850E;
664 1.1 christos break;
665 1.1 christos
666 1.1 christos case bfd_mach_v850e1:
667 1.1 christos target_processor = PROCESSOR_V850E;
668 1.1 christos break;
669 1.1 christos
670 1.1 christos case bfd_mach_v850e2:
671 1.1 christos target_processor = PROCESSOR_V850E2;
672 1.1 christos break;
673 1.1 christos
674 1.1 christos case bfd_mach_v850e2v3:
675 1.1 christos target_processor = PROCESSOR_V850E2V3;
676 1.1 christos break;
677 1.1.1.2 christos
678 1.1.1.2 christos case bfd_mach_v850e3v5:
679 1.1.1.2 christos target_processor = PROCESSOR_V850E3V5;
680 1.1.1.2 christos break;
681 1.1 christos }
682 1.1 christos
683 1.1 christos status = info->read_memory_func (memaddr, buffer, 2, info);
684 1.1 christos
685 1.1 christos if (status)
686 1.1 christos {
687 1.1 christos info->memory_error_func (status, memaddr, info);
688 1.1 christos return -1;
689 1.1 christos }
690 1.1 christos
691 1.1 christos insn = bfd_getl16 (buffer);
692 1.1 christos
693 1.1 christos status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
694 1.1 christos
695 1.1 christos if (!status2)
696 1.1 christos {
697 1.1 christos insn2 = bfd_getl16 (buffer);
698 1.1 christos /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
699 1.1 christos }
700 1.1 christos
701 1.1 christos /* Special case. */
702 1.1 christos if (length == 0
703 1.1.1.2 christos && ((target_processor & PROCESSOR_V850E2_UP) != 0))
704 1.1 christos {
705 1.1 christos if ((insn & 0xffff) == 0x02e0 /* jr 32bit */
706 1.1 christos && !status2 && (insn2 & 0x1) == 0)
707 1.1 christos {
708 1.1 christos length = 2;
709 1.1 christos code_length = 6;
710 1.1 christos }
711 1.1 christos else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */
712 1.1 christos && !status2 && (insn2 & 0x1) == 0)
713 1.1 christos {
714 1.1 christos length = 2;
715 1.1 christos code_length = 6;
716 1.1 christos }
717 1.1 christos else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */
718 1.1 christos && !status2 && (insn2 & 0x1) == 0)
719 1.1 christos {
720 1.1 christos length = 2;
721 1.1 christos code_length = 6;
722 1.1 christos }
723 1.1 christos }
724 1.1 christos
725 1.1 christos if (length == 0
726 1.1.1.2 christos && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
727 1.1.1.2 christos {
728 1.1.1.2 christos if ( ((insn & 0xffe0) == 0x07a0 /* ld.dw 23bit (v850e3v5) */
729 1.1.1.2 christos && !status2 && (insn2 & 0x000f) == 0x0009)
730 1.1.1.2 christos || ((insn & 0xffe0) == 0x07a0 /* st.dw 23bit (v850e3v5) */
731 1.1.1.2 christos && !status2 && (insn2 & 0x000f) == 0x000f))
732 1.1.1.2 christos {
733 1.1.1.2 christos length = 4;
734 1.1.1.2 christos code_length = 6;
735 1.1.1.2 christos }
736 1.1.1.2 christos }
737 1.1.1.2 christos
738 1.1.1.2 christos if (length == 0
739 1.1.1.2 christos && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
740 1.1 christos {
741 1.1 christos if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */
742 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0005)
743 1.1 christos || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */
744 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0005)
745 1.1 christos || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */
746 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0007)
747 1.1 christos || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */
748 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0007)
749 1.1 christos || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */
750 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0009))
751 1.1 christos {
752 1.1 christos length = 4;
753 1.1 christos code_length = 6;
754 1.1 christos }
755 1.1 christos else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */
756 1.1 christos && !status2 && (insn2 & 0x000f) == 0x000d)
757 1.1 christos || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */
758 1.1 christos && !status2 && (insn2 & 0x000f) == 0x000d)
759 1.1 christos || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */
760 1.1 christos && !status2 && (insn2 & 0x000f) == 0x000f))
761 1.1 christos {
762 1.1 christos length = 4;
763 1.1 christos code_length = 6;
764 1.1 christos }
765 1.1 christos }
766 1.1 christos
767 1.1 christos if (length == 0
768 1.1 christos && target_processor != PROCESSOR_V850)
769 1.1 christos {
770 1.1 christos if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */
771 1.1 christos {
772 1.1 christos length = 2;
773 1.1 christos code_length = 6;
774 1.1 christos }
775 1.1 christos else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */
776 1.1 christos && !status2 && (insn2 & 0x001f) == 0x0013)
777 1.1 christos {
778 1.1 christos length = 4;
779 1.1 christos code_length = 6;
780 1.1 christos }
781 1.1 christos else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */
782 1.1 christos && !status2 && (insn2 & 0x001f) == 0x000b)
783 1.1 christos {
784 1.1 christos length = 4;
785 1.1 christos code_length = 6;
786 1.1 christos }
787 1.1 christos else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */
788 1.1 christos && !status2 && (insn2 & 0x001f) == 0x001b)
789 1.1 christos {
790 1.1 christos length = 4;
791 1.1 christos code_length = 8;
792 1.1 christos }
793 1.1 christos }
794 1.1 christos
795 1.1 christos if (length == 4
796 1.1 christos || (length == 0
797 1.1 christos && (insn & 0x0600) == 0x0600))
798 1.1 christos {
799 1.1 christos /* This is a 4 byte insn. */
800 1.1 christos status = info->read_memory_func (memaddr, buffer, 4, info);
801 1.1 christos if (!status)
802 1.1 christos {
803 1.1 christos insn = bfd_getl32 (buffer);
804 1.1 christos
805 1.1 christos if (!length)
806 1.1 christos length = code_length = 4;
807 1.1 christos }
808 1.1 christos }
809 1.1 christos
810 1.1 christos if (code_length > length)
811 1.1 christos {
812 1.1 christos status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
813 1.1 christos if (status)
814 1.1 christos length = 0;
815 1.1 christos }
816 1.1 christos
817 1.1 christos if (length == 0 && !status)
818 1.1 christos length = code_length = 2;
819 1.1 christos
820 1.1 christos if (length == 2)
821 1.1 christos insn &= 0xffff;
822 1.1 christos
823 1.1.1.2 christos /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
824 1.1.1.2 christos if (length == 0)
825 1.1.1.2 christos return -1;
826 1.1.1.2 christos
827 1.1 christos match = disassemble (memaddr, info, length, insn);
828 1.1 christos
829 1.1 christos if (!match)
830 1.1 christos {
831 1.1 christos int l = 0;
832 1.1 christos
833 1.1 christos status = info->read_memory_func (memaddr, buffer, code_length, info);
834 1.1 christos
835 1.1 christos while (l < code_length)
836 1.1 christos {
837 1.1 christos if (code_length - l == 2)
838 1.1 christos {
839 1.1 christos insn = bfd_getl16 (buffer + l) & 0xffff;
840 1.1 christos info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
841 1.1 christos l += 2;
842 1.1 christos }
843 1.1 christos else
844 1.1 christos {
845 1.1 christos insn = bfd_getl32 (buffer + l);
846 1.1 christos info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
847 1.1 christos l += 4;
848 1.1 christos }
849 1.1 christos }
850 1.1 christos }
851 1.1 christos
852 1.1 christos return code_length;
853 1.1 christos }
854