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