* v850-dis.c (disassemble): Place square parentheses around second
[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) are the
313 "jmp" insn which needs square brackets around it's only
314 register argument, and the clr1/not1/set1/tst1 insns
315 which [...] around their second register argument. */
316
317 prefix = "";
318 if (operand->flags & V850_OPERAND_BANG)
319 {
320 prefix = "!";
321 }
322 else if (operand->flags & V850_OPERAND_PERCENT)
323 {
324 prefix = "%";
325 }
326
327 if (opnum == 1 && opnum == memop)
328 {
329 info->fprintf_func (info->stream, "%s[", prefix);
330 square = TRUE;
331 }
332 else if (opnum > 1
333 && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
334 && opnum == memop)
335 {
336 info->fprintf_func (info->stream, "%s[", prefix);
337 square = TRUE;
338 }
339 else if (opnum == 2
340 && ( op->opcode == 0x00e407e0 /* clr1 */
341 || op->opcode == 0x00e207e0 /* not1 */
342 || op->opcode == 0x00e007e0 /* set1 */
343 || op->opcode == 0x00e607e0 /* tst1 */
344 ))
345 {
346 info->fprintf_func (info->stream, ", %s[", prefix);
347 square = TRUE;
348 }
349 else if (opnum > 1)
350 info->fprintf_func (info->stream, ", %s", prefix);
351
352 /* Extract the flags, ignoring ones which do not effect disassembly output. */
353 flag = operand->flags & (V850_OPERAND_REG
354 | V850_REG_EVEN
355 | V850_OPERAND_EP
356 | V850_OPERAND_SRG
357 | V850E_OPERAND_REG_LIST
358 | V850_OPERAND_CC
359 | V850_OPERAND_FLOAT_CC);
360
361 switch (flag)
362 {
363 case V850_OPERAND_REG: info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
364 case (V850_OPERAND_REG|V850_REG_EVEN): info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
365 case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break;
366 case V850_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
367
368 case V850E_OPERAND_REG_LIST:
369 {
370 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
372 int *regs;
373 int i;
374 unsigned long int mask = 0;
375 int pc = 0;
376
377
378 switch (operand->shift)
379 {
380 case 0xffe00001: regs = list12_regs; break;
381 default:
382 /* xgettext:c-format */
383 fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
384 abort ();
385 }
386
387 for (i = 0; i < 32; i++)
388 {
389 if (value & (1 << i))
390 {
391 switch (regs[ i ])
392 {
393 default: mask |= (1 << regs[ i ]); break;
394 /* xgettext:c-format */
395 case 0: fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
396 case -1: pc = 1; break;
397 }
398 }
399 }
400
401 info->fprintf_func (info->stream, "{");
402
403 if (mask || pc)
404 {
405 if (mask)
406 {
407 unsigned int bit;
408 int shown_one = 0;
409
410 for (bit = 0; bit < 32; bit++)
411 if (mask & (1 << bit))
412 {
413 unsigned long int first = bit;
414 unsigned long int last;
415
416 if (shown_one)
417 info->fprintf_func (info->stream, ", ");
418 else
419 shown_one = 1;
420
421 info->fprintf_func (info->stream, "%s", v850_reg_names[first]);
422
423 for (bit++; bit < 32; bit++)
424 if ((mask & (1 << bit)) == 0)
425 break;
426
427 last = bit;
428
429 if (last > first + 1)
430 {
431 info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
432 }
433 }
434 }
435
436 if (pc)
437 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
438 }
439
440 info->fprintf_func (info->stream, "}");
441 }
442 break;
443
444 case V850_OPERAND_CC: info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
445 case V850_OPERAND_FLOAT_CC: info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
446
447 default:
448 print_value (operand->flags, memaddr, info, value);
449 break;
450 }
451
452 if (square)
453 (*info->fprintf_func) (info->stream, "]");
454 }
455
456 /* All done. */
457 break;
458 }
459 next_opcode:
460 op++;
461 }
462
463 return match;
464 }
465
466 int
467 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
468 {
469 int status, status2, match;
470 bfd_byte buffer[8];
471 int length = 0, code_length = 0;
472 unsigned long insn = 0, insn2 = 0;
473 int target_processor;
474
475 switch (info->mach)
476 {
477 case 0:
478 default:
479 target_processor = PROCESSOR_V850;
480 break;
481
482 case bfd_mach_v850e:
483 target_processor = PROCESSOR_V850E;
484 break;
485
486 case bfd_mach_v850e1:
487 target_processor = PROCESSOR_V850E;
488 break;
489
490 case bfd_mach_v850e2:
491 target_processor = PROCESSOR_V850E2;
492 break;
493
494 case bfd_mach_v850e2v3:
495 target_processor = PROCESSOR_V850E2V3;
496 break;
497 }
498
499 status = info->read_memory_func (memaddr, buffer, 2, info);
500
501 if (status)
502 {
503 info->memory_error_func (status, memaddr, info);
504 return -1;
505 }
506
507 insn = bfd_getl16 (buffer);
508
509 status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
510
511 if (!status2)
512 {
513 insn2 = bfd_getl16 (buffer);
514 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
515 }
516
517 /* Special case. */
518 if (length == 0
519 && (target_processor == PROCESSOR_V850E2
520 || target_processor == PROCESSOR_V850E2V3))
521 {
522 if ((insn & 0xffff) == 0x02e0 /* jr 32bit */
523 && !status2 && (insn2 & 0x1) == 0)
524 {
525 length = 2;
526 code_length = 6;
527 }
528 else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */
529 && !status2 && (insn2 & 0x1) == 0)
530 {
531 length = 2;
532 code_length = 6;
533 }
534 else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */
535 && !status2 && (insn2 & 0x1) == 0)
536 {
537 length = 2;
538 code_length = 6;
539 }
540 }
541
542 if (length == 0
543 && target_processor == PROCESSOR_V850E2V3)
544 {
545 if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */
546 && !status2 && (insn2 & 0x000f) == 0x0005)
547 || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */
548 && !status2 && (insn2 & 0x000f) == 0x0005)
549 || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */
550 && !status2 && (insn2 & 0x000f) == 0x0007)
551 || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */
552 && !status2 && (insn2 & 0x000f) == 0x0007)
553 || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */
554 && !status2 && (insn2 & 0x000f) == 0x0009))
555 {
556 length = 4;
557 code_length = 6;
558 }
559 else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */
560 && !status2 && (insn2 & 0x000f) == 0x000d)
561 || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */
562 && !status2 && (insn2 & 0x000f) == 0x000d)
563 || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */
564 && !status2 && (insn2 & 0x000f) == 0x000f))
565 {
566 length = 4;
567 code_length = 6;
568 }
569 }
570
571 if (length == 0
572 && target_processor != PROCESSOR_V850)
573 {
574 if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */
575 {
576 length = 2;
577 code_length = 6;
578 }
579 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */
580 && !status2 && (insn2 & 0x001f) == 0x0013)
581 {
582 length = 4;
583 code_length = 6;
584 }
585 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */
586 && !status2 && (insn2 & 0x001f) == 0x000b)
587 {
588 length = 4;
589 code_length = 6;
590 }
591 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */
592 && !status2 && (insn2 & 0x001f) == 0x001b)
593 {
594 length = 4;
595 code_length = 8;
596 }
597 }
598
599 if (length == 4
600 || (length == 0
601 && (insn & 0x0600) == 0x0600))
602 {
603 /* This is a 4 byte insn. */
604 status = info->read_memory_func (memaddr, buffer, 4, info);
605 if (!status)
606 {
607 insn = bfd_getl32 (buffer);
608
609 if (!length)
610 length = code_length = 4;
611 }
612 }
613
614 if (code_length > length)
615 {
616 status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
617 if (status)
618 length = 0;
619 }
620
621 if (length == 0 && !status)
622 length = code_length = 2;
623
624 if (length == 2)
625 insn &= 0xffff;
626
627 match = disassemble (memaddr, info, length, insn);
628
629 if (!match)
630 {
631 int l = 0;
632
633 status = info->read_memory_func (memaddr, buffer, code_length, info);
634
635 while (l < code_length)
636 {
637 if (code_length - l == 2)
638 {
639 insn = bfd_getl16 (buffer + l) & 0xffff;
640 info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
641 l += 2;
642 }
643 else
644 {
645 insn = bfd_getl32 (buffer + l);
646 info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
647 l += 4;
648 }
649 }
650 }
651
652 return code_length;
653 }
This page took 0.086068 seconds and 5 git commands to generate.