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