PR 14072
[deliverable/binutils-gdb.git] / opcodes / v850-dis.c
1 /* Disassemble V850 instructions.
2 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010,
3 2012 Free Software Foundation, Inc.
4
5 This file is part of the GNU opcodes library.
6
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)
10 any later version.
11
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.
16
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. */
21
22
23 #include "sysdep.h"
24 #include <stdio.h>
25 #include "opcode/v850.h"
26 #include "dis-asm.h"
27 #include "opintl.h"
28
29 static const char *const v850_reg_names[] =
30 {
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"
35 };
36
37 static const char *const v850_sreg_names[] =
38 {
39 "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
40 "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
41 "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
42 "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
43 "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
44 "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
45 "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
46 "fewr", "dbwr", "bsel"
47 };
48
49 static const char *const v850_cc_names[] =
50 {
51 "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
52 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
53 };
54
55 static const char *const v850_float_cc_names[] =
56 {
57 "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
58 "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
59 };
60
61
62 static void
63 print_value (int flags, bfd_vma memaddr, struct disassemble_info *info, long value)
64 {
65 if (flags & V850_PCREL)
66 {
67 bfd_vma addr = value + memaddr;
68 info->print_address_func (addr, info);
69 }
70 else if (flags & V850_OPERAND_DISP)
71 {
72 if (flags & V850_OPERAND_SIGNED)
73 {
74 info->fprintf_func (info->stream, "%ld", value);
75 }
76 else
77 {
78 info->fprintf_func (info->stream, "%lu", value);
79 }
80 }
81 else if (flags & V850E_IMMEDIATE32)
82 {
83 info->fprintf_func (info->stream, "0x%lx", value);
84 }
85 else
86 {
87 if (flags & V850_OPERAND_SIGNED)
88 {
89 info->fprintf_func (info->stream, "%ld", value);
90 }
91 else
92 {
93 info->fprintf_func (info->stream, "%lu", value);
94 }
95 }
96 }
97
98 static long
99 get_operand_value (const struct v850_operand *operand,
100 unsigned long insn,
101 int bytes_read,
102 bfd_vma memaddr,
103 struct disassemble_info * info,
104 bfd_boolean noerror,
105 int *invalid)
106 {
107 long value;
108 bfd_byte buffer[4];
109
110 if ((operand->flags & V850E_IMMEDIATE16)
111 || (operand->flags & V850E_IMMEDIATE16HI))
112 {
113 int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
114
115 if (status == 0)
116 {
117 value = bfd_getl16 (buffer);
118
119 if (operand->flags & V850E_IMMEDIATE16HI)
120 value <<= 16;
121
122 return value;
123 }
124
125 if (!noerror)
126 info->memory_error_func (status, memaddr + bytes_read, info);
127
128 return 0;
129 }
130
131 if (operand->flags & V850E_IMMEDIATE23)
132 {
133 int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
134
135 if (status == 0)
136 {
137 value = bfd_getl32 (buffer);
138
139 value = (operand->extract) (value, invalid);
140
141 return value;
142 }
143
144 if (!noerror)
145 info->memory_error_func (status, memaddr + bytes_read, info);
146
147 return 0;
148 }
149
150 if (operand->flags & V850E_IMMEDIATE32)
151 {
152 int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
153
154 if (status == 0)
155 {
156 bytes_read += 4;
157 value = bfd_getl32 (buffer);
158
159 return value;
160 }
161
162 if (!noerror)
163 info->memory_error_func (status, memaddr + bytes_read, info);
164
165 return 0;
166 }
167
168 if (operand->extract)
169 value = (operand->extract) (insn, invalid);
170 else
171 {
172 if (operand->bits == -1)
173 value = (insn & operand->shift);
174 else
175 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
176
177 if (operand->flags & V850_OPERAND_SIGNED)
178 value = ((long)(value << (sizeof (long)*8 - operand->bits))
179 >> (sizeof (long)*8 - operand->bits));
180 }
181
182 return value;
183 }
184
185
186 static int
187 disassemble (bfd_vma memaddr, struct disassemble_info *info, int bytes_read, unsigned long insn)
188 {
189 struct v850_opcode *op = (struct v850_opcode *)v850_opcodes;
190 const struct v850_operand *operand;
191 int match = 0;
192 int target_processor;
193
194 switch (info->mach)
195 {
196 case 0:
197 default:
198 target_processor = PROCESSOR_V850;
199 break;
200
201 case bfd_mach_v850e:
202 target_processor = PROCESSOR_V850E;
203 break;
204
205 case bfd_mach_v850e1:
206 target_processor = PROCESSOR_V850E;
207 break;
208
209 case bfd_mach_v850e2:
210 target_processor = PROCESSOR_V850E2;
211 break;
212
213 case bfd_mach_v850e2v3:
214 target_processor = PROCESSOR_V850E2V3;
215 break;
216 }
217
218 /* If this is a two byte insn, then mask off the high bits. */
219 if (bytes_read == 2)
220 insn &= 0xffff;
221
222 /* Find the opcode. */
223 while (op->name)
224 {
225 if ((op->mask & insn) == op->opcode
226 && (op->processors & target_processor)
227 && !(op->processors & PROCESSOR_OPTION_ALIAS))
228 {
229 /* Code check start. */
230 const unsigned char *opindex_ptr;
231 unsigned int opnum;
232 unsigned int memop;
233
234 for (opindex_ptr = op->operands, opnum = 1;
235 *opindex_ptr != 0;
236 opindex_ptr++, opnum++)
237 {
238 int invalid = 0;
239 long value;
240
241 operand = &v850_operands[*opindex_ptr];
242
243 value = get_operand_value (operand, insn, bytes_read, memaddr, info, 1, &invalid);
244
245 if (invalid)
246 goto next_opcode;
247
248 if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
249 goto next_opcode;
250
251 if ((operand->flags & V850_NOT_SA) && value == 0xd)
252 goto next_opcode;
253
254 if ((operand->flags & V850_NOT_IMM0) && value == 0)
255 goto next_opcode;
256 }
257
258 /* Code check end. */
259
260 match = 1;
261 (*info->fprintf_func) (info->stream, "%s\t", op->name);
262 #if 0
263 fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
264 insn, op->mask, op->opcode, op->name );
265 #endif
266
267 memop = op->memop;
268 /* Now print the operands.
269
270 MEMOP is the operand number at which a memory
271 address specification starts, or zero if this
272 instruction has no memory addresses.
273
274 A memory address is always two arguments.
275
276 This information allows us to determine when to
277 insert commas into the output stream as well as
278 when to insert disp[reg] expressions onto the
279 output stream. */
280
281 for (opindex_ptr = op->operands, opnum = 1;
282 *opindex_ptr != 0;
283 opindex_ptr++, opnum++)
284 {
285 bfd_boolean square = FALSE;
286 long value;
287 int flag;
288 char *prefix;
289
290 operand = &v850_operands[*opindex_ptr];
291
292 value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
293
294 /* The first operand is always output without any
295 special handling.
296
297 For the following arguments:
298
299 If memop && opnum == memop + 1, then we need '[' since
300 we're about to output the register used in a memory
301 reference.
302
303 If memop && opnum == memop + 2, then we need ']' since
304 we just finished the register in a memory reference. We
305 also need a ',' before this operand.
306
307 Else we just need a comma.
308
309 We may need to output a trailing ']' if the last operand
310 in an instruction is the register for a memory address.
311
312 The exception (and there's always an exception) is the
313 "jmp" insn which needs square brackets around it's only
314 register argument. */
315 prefix = "";
316 if (operand->flags & V850_OPERAND_BANG)
317 {
318 prefix = "!";
319 }
320 else if (operand->flags & V850_OPERAND_PERCENT)
321 {
322 prefix = "%";
323 }
324
325 if (opnum == 1 && opnum == memop)
326 {
327 info->fprintf_func (info->stream, "%s[", prefix);
328 square = TRUE;
329 }
330 else if (opnum > 1
331 && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
332 && opnum == memop)
333 {
334 info->fprintf_func (info->stream, "%s[", prefix);
335 square = TRUE;
336 }
337 else if (opnum > 1)
338 info->fprintf_func (info->stream, ", %s", prefix);
339
340 /* Extract the flags, ignoring ones which do not effect disassembly output. */
341 flag = operand->flags & (V850_OPERAND_REG
342 | V850_REG_EVEN
343 | V850_OPERAND_EP
344 | V850_OPERAND_SRG
345 | V850E_OPERAND_REG_LIST
346 | V850_OPERAND_CC
347 | V850_OPERAND_FLOAT_CC);
348
349 switch (flag)
350 {
351 case V850_OPERAND_REG: info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
352 case (V850_OPERAND_REG|V850_REG_EVEN): info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
353 case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break;
354 case V850_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
355
356 case V850E_OPERAND_REG_LIST:
357 {
358 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
359 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
360 int *regs;
361 int i;
362 unsigned long int mask = 0;
363 int pc = 0;
364
365
366 switch (operand->shift)
367 {
368 case 0xffe00001: regs = list12_regs; break;
369 default:
370 /* xgettext:c-format */
371 fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
372 abort ();
373 }
374
375 for (i = 0; i < 32; i++)
376 {
377 if (value & (1 << i))
378 {
379 switch (regs[ i ])
380 {
381 default: mask |= (1 << regs[ i ]); break;
382 /* xgettext:c-format */
383 case 0: fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
384 case -1: pc = 1; break;
385 }
386 }
387 }
388
389 info->fprintf_func (info->stream, "{");
390
391 if (mask || pc)
392 {
393 if (mask)
394 {
395 unsigned int bit;
396 int shown_one = 0;
397
398 for (bit = 0; bit < 32; bit++)
399 if (mask & (1 << bit))
400 {
401 unsigned long int first = bit;
402 unsigned long int last;
403
404 if (shown_one)
405 info->fprintf_func (info->stream, ", ");
406 else
407 shown_one = 1;
408
409 info->fprintf_func (info->stream, v850_reg_names[first]);
410
411 for (bit++; bit < 32; bit++)
412 if ((mask & (1 << bit)) == 0)
413 break;
414
415 last = bit;
416
417 if (last > first + 1)
418 {
419 info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
420 }
421 }
422 }
423
424 if (pc)
425 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
426 }
427
428 info->fprintf_func (info->stream, "}");
429 }
430 break;
431
432 case V850_OPERAND_CC: info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
433 case V850_OPERAND_FLOAT_CC: info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
434
435 default:
436 print_value (operand->flags, memaddr, info, value);
437 break;
438 }
439
440 if (square)
441 (*info->fprintf_func) (info->stream, "]");
442 }
443
444 /* All done. */
445 break;
446 }
447 next_opcode:
448 op++;
449 }
450
451 return match;
452 }
453
454 int
455 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
456 {
457 int status, status2, match;
458 bfd_byte buffer[8];
459 int length = 0, code_length = 0;
460 unsigned long insn = 0, insn2 = 0;
461 int target_processor;
462
463 switch (info->mach)
464 {
465 case 0:
466 default:
467 target_processor = PROCESSOR_V850;
468 break;
469
470 case bfd_mach_v850e:
471 target_processor = PROCESSOR_V850E;
472 break;
473
474 case bfd_mach_v850e1:
475 target_processor = PROCESSOR_V850E;
476 break;
477
478 case bfd_mach_v850e2:
479 target_processor = PROCESSOR_V850E2;
480 break;
481
482 case bfd_mach_v850e2v3:
483 target_processor = PROCESSOR_V850E2V3;
484 break;
485 }
486
487 status = info->read_memory_func (memaddr, buffer, 2, info);
488
489 if (status)
490 {
491 info->memory_error_func (status, memaddr, info);
492 return -1;
493 }
494
495 insn = bfd_getl16 (buffer);
496
497 status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
498
499 if (!status2)
500 {
501 insn2 = bfd_getl16 (buffer);
502 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
503 }
504
505 /* Special case. */
506 if (length == 0
507 && (target_processor == PROCESSOR_V850E2
508 || target_processor == PROCESSOR_V850E2V3))
509 {
510 if ((insn & 0xffff) == 0x02e0 /* jr 32bit */
511 && !status2 && (insn2 & 0x1) == 0)
512 {
513 length = 2;
514 code_length = 6;
515 }
516 else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */
517 && !status2 && (insn2 & 0x1) == 0)
518 {
519 length = 2;
520 code_length = 6;
521 }
522 else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */
523 && !status2 && (insn2 & 0x1) == 0)
524 {
525 length = 2;
526 code_length = 6;
527 }
528 }
529
530 if (length == 0
531 && target_processor == PROCESSOR_V850E2V3)
532 {
533 if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */
534 && !status2 && (insn2 & 0x000f) == 0x0005)
535 || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */
536 && !status2 && (insn2 & 0x000f) == 0x0005)
537 || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */
538 && !status2 && (insn2 & 0x000f) == 0x0007)
539 || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */
540 && !status2 && (insn2 & 0x000f) == 0x0007)
541 || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */
542 && !status2 && (insn2 & 0x000f) == 0x0009))
543 {
544 length = 4;
545 code_length = 6;
546 }
547 else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */
548 && !status2 && (insn2 & 0x000f) == 0x000d)
549 || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */
550 && !status2 && (insn2 & 0x000f) == 0x000d)
551 || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */
552 && !status2 && (insn2 & 0x000f) == 0x000f))
553 {
554 length = 4;
555 code_length = 6;
556 }
557 }
558
559 if (length == 0
560 && target_processor != PROCESSOR_V850)
561 {
562 if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */
563 {
564 length = 2;
565 code_length = 6;
566 }
567 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */
568 && !status2 && (insn2 & 0x001f) == 0x0013)
569 {
570 length = 4;
571 code_length = 6;
572 }
573 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */
574 && !status2 && (insn2 & 0x001f) == 0x000b)
575 {
576 length = 4;
577 code_length = 6;
578 }
579 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */
580 && !status2 && (insn2 & 0x001f) == 0x001b)
581 {
582 length = 4;
583 code_length = 8;
584 }
585 }
586
587 if (length == 4
588 || (length == 0
589 && (insn & 0x0600) == 0x0600))
590 {
591 /* This is a 4 byte insn. */
592 status = info->read_memory_func (memaddr, buffer, 4, info);
593 if (!status)
594 {
595 insn = bfd_getl32 (buffer);
596
597 if (!length)
598 length = code_length = 4;
599 }
600 }
601
602 if (code_length > length)
603 {
604 status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
605 if (status)
606 length = 0;
607 }
608
609 if (length == 0 && !status)
610 length = code_length = 2;
611
612 if (length == 2)
613 insn &= 0xffff;
614
615 match = disassemble (memaddr, info, length, insn);
616
617 if (!match)
618 {
619 int l = 0;
620
621 status = info->read_memory_func (memaddr, buffer, code_length, info);
622
623 while (l < code_length)
624 {
625 if (code_length - l == 2)
626 {
627 insn = bfd_getl16 (buffer + l) & 0xffff;
628 info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
629 l += 2;
630 }
631 else
632 {
633 insn = bfd_getl32 (buffer + l);
634 info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
635 l += 4;
636 }
637 }
638 }
639
640 return code_length;
641 }
This page took 0.042985 seconds and 5 git commands to generate.