* lib/ld-lib.exp (run_dump_test): For options "warning" and
[deliverable/binutils-gdb.git] / opcodes / v850-dis.c
CommitLineData
252b5132 1/* Disassemble V850 instructions.
1cd986c5 2 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010
b34976b6 3 Free Software Foundation, Inc.
252b5132 4
9b201bb5
NC
5 This file is part of the GNU opcodes library.
6
7 This library is free software; you can redistribute it and/or modify
8ad30312 8 it under the terms of the GNU General Public License as published by
9b201bb5
NC
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
252b5132 11
9b201bb5
NC
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.
252b5132 16
8ad30312
NC
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
47b0e7ad
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
252b5132
RH
21
22
23#include <stdio.h>
24
0d8dfecf 25#include "sysdep.h"
47b0e7ad 26#include "opcode/v850.h"
252b5132
RH
27#include "dis-asm.h"
28#include "opintl.h"
29
30static const char *const v850_reg_names[] =
1cd986c5
NC
31{
32 "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
47b0e7ad
NC
33 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
34 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1cd986c5
NC
35 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
36};
252b5132
RH
37
38static const char *const v850_sreg_names[] =
1cd986c5
NC
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};
252b5132
RH
49
50static const char *const v850_cc_names[] =
1cd986c5
NC
51{
52 "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
53 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
54};
252b5132 55
1cd986c5 56static const char *const v850_float_cc_names[] =
252b5132 57{
1cd986c5
NC
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};
47b0e7ad 61
47b0e7ad 62
1cd986c5
NC
63static void
64print_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}
47b0e7ad 98
1cd986c5
NC
99static long
100get_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
187static int
188disassemble (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;
252b5132
RH
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;
8ad30312
NC
205
206 case bfd_mach_v850e1:
1cd986c5
NC
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;
8ad30312 216 break;
252b5132 217 }
47b0e7ad 218
1cd986c5
NC
219 /* If this is a two byte insn, then mask off the high bits. */
220 if (bytes_read == 2)
221 insn &= 0xffff;
222
252b5132
RH
223 /* Find the opcode. */
224 while (op->name)
225 {
226 if ((op->mask & insn) == op->opcode
1cd986c5
NC
227 && (op->processors & target_processor)
228 && !(op->processors & PROCESSOR_OPTION_ALIAS))
252b5132 229 {
1cd986c5 230 /* Code check start. */
b34976b6
AM
231 const unsigned char *opindex_ptr;
232 unsigned int opnum;
233 unsigned int memop;
252b5132 234
1cd986c5
NC
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
252b5132
RH
261 match = 1;
262 (*info->fprintf_func) (info->stream, "%s\t", op->name);
1cd986c5
NC
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
252b5132
RH
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. */
47b0e7ad 281
252b5132
RH
282 for (opindex_ptr = op->operands, opnum = 1;
283 *opindex_ptr != 0;
284 opindex_ptr++, opnum++)
285 {
7d063384 286 bfd_boolean square = FALSE;
b34976b6
AM
287 long value;
288 int flag;
1cd986c5 289 char *prefix;
47b0e7ad 290
252b5132 291 operand = &v850_operands[*opindex_ptr];
47b0e7ad 292
1cd986c5 293 value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
252b5132
RH
294
295 /* The first operand is always output without any
296 special handling.
297
298 For the following arguments:
299
300 If memop && opnum == memop + 1, then we need '[' since
301 we're about to output the register used in a memory
302 reference.
303
304 If memop && opnum == memop + 2, then we need ']' since
305 we just finished the register in a memory reference. We
306 also need a ',' before this operand.
307
308 Else we just need a comma.
309
310 We may need to output a trailing ']' if the last operand
47b0e7ad 311 in an instruction is the register for a memory address.
252b5132
RH
312
313 The exception (and there's always an exception) is the
314 "jmp" insn which needs square brackets around it's only
315 register argument. */
1cd986c5
NC
316 prefix = "";
317 if (operand->flags & V850_OPERAND_BANG)
318 {
319 prefix = "!";
320 }
321 else if (operand->flags & V850_OPERAND_PERCENT)
322 {
323 prefix = "%";
324 }
252b5132 325
1cd986c5 326 if (opnum == 1 && opnum == memop)
7d063384
NC
327 {
328 info->fprintf_func (info->stream, "%s[", prefix);
329 square = TRUE;
330 }
1cd986c5
NC
331 else if (opnum > 1
332 && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
333 && opnum == memop)
7d063384
NC
334 {
335 info->fprintf_func (info->stream, "%s[", prefix);
336 square = TRUE;
337 }
1cd986c5
NC
338 else if (opnum > 1)
339 info->fprintf_func (info->stream, ", %s", prefix);
340
341 /* Extract the flags, ignoring ones which do not effect disassembly output. */
342 flag = operand->flags & (V850_OPERAND_REG
343 | V850_REG_EVEN
344 | V850_OPERAND_EP
345 | V850_OPERAND_SRG
346 | V850E_OPERAND_REG_LIST
347 | V850_OPERAND_CC
348 | V850_OPERAND_FLOAT_CC);
47b0e7ad 349
252b5132
RH
350 switch (flag)
351 {
1cd986c5
NC
352 case V850_OPERAND_REG: info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
353 case (V850_OPERAND_REG|V850_REG_EVEN): info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
354 case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break;
355 case V850_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
47b0e7ad 356
1cd986c5 357 case V850E_OPERAND_REG_LIST:
252b5132 358 {
1cd986c5
NC
359 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
360 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
b34976b6
AM
361 int *regs;
362 int i;
252b5132 363 unsigned long int mask = 0;
b34976b6 364 int pc = 0;
1cd986c5 365
47b0e7ad 366
252b5132
RH
367 switch (operand->shift)
368 {
369 case 0xffe00001: regs = list12_regs; break;
252b5132
RH
370 default:
371 /* xgettext:c-format */
1cd986c5 372 fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
47b0e7ad 373 abort ();
252b5132
RH
374 }
375
376 for (i = 0; i < 32; i++)
377 {
378 if (value & (1 << i))
379 {
380 switch (regs[ i ])
381 {
382 default: mask |= (1 << regs[ i ]); break;
383 /* xgettext:c-format */
1cd986c5 384 case 0: fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
b34976b6 385 case -1: pc = 1; break;
252b5132
RH
386 }
387 }
388 }
389
390 info->fprintf_func (info->stream, "{");
47b0e7ad 391
1cd986c5 392 if (mask || pc)
252b5132
RH
393 {
394 if (mask)
395 {
396 unsigned int bit;
b34976b6 397 int shown_one = 0;
47b0e7ad 398
252b5132
RH
399 for (bit = 0; bit < 32; bit++)
400 if (mask & (1 << bit))
401 {
402 unsigned long int first = bit;
403 unsigned long int last;
404
405 if (shown_one)
406 info->fprintf_func (info->stream, ", ");
407 else
b34976b6 408 shown_one = 1;
47b0e7ad 409
1cd986c5 410 info->fprintf_func (info->stream, v850_reg_names[first]);
47b0e7ad 411
252b5132
RH
412 for (bit++; bit < 32; bit++)
413 if ((mask & (1 << bit)) == 0)
414 break;
415
416 last = bit;
417
418 if (last > first + 1)
1cd986c5
NC
419 {
420 info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
421 }
252b5132
RH
422 }
423 }
47b0e7ad 424
252b5132
RH
425 if (pc)
426 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
252b5132 427 }
47b0e7ad 428
252b5132
RH
429 info->fprintf_func (info->stream, "}");
430 }
252b5132 431 break;
47b0e7ad 432
1cd986c5
NC
433 case V850_OPERAND_CC: info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
434 case V850_OPERAND_FLOAT_CC: info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
435
436 default:
437 print_value (operand->flags, memaddr, info, value);
252b5132 438 break;
47b0e7ad 439 }
252b5132 440
7d063384 441 if (square)
252b5132
RH
442 (*info->fprintf_func) (info->stream, "]");
443 }
444
252b5132
RH
445 /* All done. */
446 break;
447 }
1cd986c5 448 next_opcode:
252b5132
RH
449 op++;
450 }
451
1cd986c5 452 return match;
252b5132
RH
453}
454
47b0e7ad
NC
455int
456print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
252b5132 457{
1cd986c5
NC
458 int status, status2, match;
459 bfd_byte buffer[8];
460 int length = 0, code_length = 0;
461 unsigned long insn = 0, insn2 = 0;
462 int target_processor;
463
464 switch (info->mach)
465 {
466 case 0:
467 default:
468 target_processor = PROCESSOR_V850;
469 break;
470
471 case bfd_mach_v850e:
472 target_processor = PROCESSOR_V850E;
473 break;
474
475 case bfd_mach_v850e1:
476 target_processor = PROCESSOR_V850E;
477 break;
478
479 case bfd_mach_v850e2:
480 target_processor = PROCESSOR_V850E2;
481 break;
482
483 case bfd_mach_v850e2v3:
484 target_processor = PROCESSOR_V850E2V3;
485 break;
486 }
252b5132 487
252b5132 488 status = info->read_memory_func (memaddr, buffer, 2, info);
1cd986c5
NC
489
490 if (status)
491 {
492 info->memory_error_func (status, memaddr, info);
493 return -1;
494 }
495
496 insn = bfd_getl16 (buffer);
497
498 status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
499
500 if (!status2)
252b5132 501 {
1cd986c5
NC
502 insn2 = bfd_getl16 (buffer);
503 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
504 }
47b0e7ad 505
1cd986c5
NC
506 /* Special case. */
507 if (length == 0
508 && (target_processor == PROCESSOR_V850E2
509 || target_processor == PROCESSOR_V850E2V3))
510 {
511 if ((insn & 0xffff) == 0x02e0 /* jr 32bit */
512 && !status2 && (insn2 & 0x1) == 0)
513 {
514 length = 2;
515 code_length = 6;
516 }
517 else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */
518 && !status2 && (insn2 & 0x1) == 0)
519 {
520 length = 2;
521 code_length = 6;
522 }
523 else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */
524 && !status2 && (insn2 & 0x1) == 0)
252b5132 525 {
1cd986c5
NC
526 length = 2;
527 code_length = 6;
528 }
529 }
252b5132 530
1cd986c5
NC
531 if (length == 0
532 && target_processor == PROCESSOR_V850E2V3)
533 {
534 if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */
535 && !status2 && (insn2 & 0x000f) == 0x0005)
536 || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */
537 && !status2 && (insn2 & 0x000f) == 0x0005)
538 || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */
539 && !status2 && (insn2 & 0x000f) == 0x0007)
540 || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */
541 && !status2 && (insn2 & 0x000f) == 0x0007)
542 || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */
543 && !status2 && (insn2 & 0x000f) == 0x0009))
544 {
545 length = 4;
546 code_length = 6;
547 }
548 else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */
549 && !status2 && (insn2 & 0x000f) == 0x000d)
550 || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */
551 && !status2 && (insn2 & 0x000f) == 0x000d)
552 || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */
553 && !status2 && (insn2 & 0x000f) == 0x000f))
554 {
555 length = 4;
556 code_length = 6;
252b5132
RH
557 }
558 }
47b0e7ad 559
1cd986c5
NC
560 if (length == 0
561 && target_processor != PROCESSOR_V850)
252b5132 562 {
1cd986c5
NC
563 if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */
564 {
565 length = 2;
566 code_length = 6;
567 }
568 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */
569 && !status2 && (insn2 & 0x001f) == 0x0013)
570 {
571 length = 4;
572 code_length = 6;
573 }
574 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */
575 && !status2 && (insn2 & 0x001f) == 0x000b)
576 {
577 length = 4;
578 code_length = 6;
579 }
580 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */
581 && !status2 && (insn2 & 0x001f) == 0x001b)
582 {
583 length = 4;
584 code_length = 8;
585 }
586 }
587
588 if (length == 4
589 || (length == 0
590 && (insn & 0x0600) == 0x0600))
591 {
592 /* This is a 4 byte insn. */
593 status = info->read_memory_func (memaddr, buffer, 4, info);
594 if (!status)
595 {
596 insn = bfd_getl32 (buffer);
597
598 if (!length)
599 length = code_length = 4;
600 }
601 }
602
603 if (code_length > length)
604 {
605 status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
606 if (status)
607 length = 0;
608 }
609
610 if (length == 0 && !status)
611 length = code_length = 2;
612
613 if (length == 2)
614 insn &= 0xffff;
615
616 match = disassemble (memaddr, info, length, insn);
617
618 if (!match)
619 {
620 int l = 0;
621
622 status = info->read_memory_func (memaddr, buffer, code_length, info);
623
624 while (l < code_length)
625 {
626 if (code_length - l == 2)
627 {
628 insn = bfd_getl16 (buffer + l) & 0xffff;
629 info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
630 l += 2;
631 }
632 else
633 {
634 insn = bfd_getl32 (buffer + l);
635 info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
636 l += 4;
637 }
638 }
252b5132
RH
639 }
640
1cd986c5 641 return code_length;
252b5132 642}
This page took 0.624214 seconds and 4 git commands to generate.