Fix spelling typo.
[deliverable/binutils-gdb.git] / opcodes / v850-dis.c
CommitLineData
252b5132 1/* Disassemble V850 instructions.
df7b86aa
NC
2 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010,
3 2012 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
0d8dfecf 23#include "sysdep.h"
df7b86aa 24#include <stdio.h>
47b0e7ad 25#include "opcode/v850.h"
252b5132
RH
26#include "dis-asm.h"
27#include "opintl.h"
28
29static const char *const v850_reg_names[] =
1cd986c5
NC
30{
31 "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
47b0e7ad
NC
32 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
33 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1cd986c5
NC
34 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
35};
252b5132
RH
36
37static const char *const v850_sreg_names[] =
1cd986c5
NC
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};
252b5132
RH
48
49static const char *const v850_cc_names[] =
1cd986c5
NC
50{
51 "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
52 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
53};
252b5132 54
1cd986c5 55static const char *const v850_float_cc_names[] =
252b5132 56{
1cd986c5
NC
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};
47b0e7ad 60
47b0e7ad 61
1cd986c5
NC
62static void
63print_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}
47b0e7ad 97
1cd986c5
NC
98static long
99get_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
186static int
187disassemble (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;
252b5132
RH
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;
8ad30312
NC
204
205 case bfd_mach_v850e1:
1cd986c5
NC
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;
8ad30312 215 break;
252b5132 216 }
47b0e7ad 217
1cd986c5
NC
218 /* If this is a two byte insn, then mask off the high bits. */
219 if (bytes_read == 2)
220 insn &= 0xffff;
221
252b5132
RH
222 /* Find the opcode. */
223 while (op->name)
224 {
225 if ((op->mask & insn) == op->opcode
1cd986c5
NC
226 && (op->processors & target_processor)
227 && !(op->processors & PROCESSOR_OPTION_ALIAS))
252b5132 228 {
1cd986c5 229 /* Code check start. */
b34976b6
AM
230 const unsigned char *opindex_ptr;
231 unsigned int opnum;
232 unsigned int memop;
252b5132 233
1cd986c5
NC
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
252b5132
RH
260 match = 1;
261 (*info->fprintf_func) (info->stream, "%s\t", op->name);
1cd986c5
NC
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
252b5132
RH
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. */
47b0e7ad 280
252b5132
RH
281 for (opindex_ptr = op->operands, opnum = 1;
282 *opindex_ptr != 0;
283 opindex_ptr++, opnum++)
284 {
7d063384 285 bfd_boolean square = FALSE;
b34976b6
AM
286 long value;
287 int flag;
1cd986c5 288 char *prefix;
47b0e7ad 289
252b5132 290 operand = &v850_operands[*opindex_ptr];
47b0e7ad 291
1cd986c5 292 value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
252b5132
RH
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
47b0e7ad 310 in an instruction is the register for a memory address.
252b5132 311
04ee5257 312 The exception (and there's always an exception) are the
252b5132 313 "jmp" insn which needs square brackets around it's only
04ee5257
NC
314 register argument, and the clr1/not1/set1/tst1 insns
315 which [...] around their second register argument. */
316
1cd986c5
NC
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 }
252b5132 326
1cd986c5 327 if (opnum == 1 && opnum == memop)
7d063384
NC
328 {
329 info->fprintf_func (info->stream, "%s[", prefix);
330 square = TRUE;
331 }
1cd986c5
NC
332 else if (opnum > 1
333 && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
334 && opnum == memop)
7d063384
NC
335 {
336 info->fprintf_func (info->stream, "%s[", prefix);
337 square = TRUE;
338 }
04ee5257
NC
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 }
1cd986c5
NC
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);
47b0e7ad 360
252b5132
RH
361 switch (flag)
362 {
1cd986c5
NC
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;
47b0e7ad 367
1cd986c5 368 case V850E_OPERAND_REG_LIST:
252b5132 369 {
1cd986c5
NC
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 };
b34976b6
AM
372 int *regs;
373 int i;
252b5132 374 unsigned long int mask = 0;
b34976b6 375 int pc = 0;
1cd986c5 376
47b0e7ad 377
252b5132
RH
378 switch (operand->shift)
379 {
380 case 0xffe00001: regs = list12_regs; break;
252b5132
RH
381 default:
382 /* xgettext:c-format */
1cd986c5 383 fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
47b0e7ad 384 abort ();
252b5132
RH
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 */
1cd986c5 395 case 0: fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
b34976b6 396 case -1: pc = 1; break;
252b5132
RH
397 }
398 }
399 }
400
401 info->fprintf_func (info->stream, "{");
47b0e7ad 402
1cd986c5 403 if (mask || pc)
252b5132
RH
404 {
405 if (mask)
406 {
407 unsigned int bit;
b34976b6 408 int shown_one = 0;
47b0e7ad 409
252b5132
RH
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
b34976b6 419 shown_one = 1;
47b0e7ad 420
48891606 421 info->fprintf_func (info->stream, "%s", v850_reg_names[first]);
47b0e7ad 422
252b5132
RH
423 for (bit++; bit < 32; bit++)
424 if ((mask & (1 << bit)) == 0)
425 break;
426
427 last = bit;
428
429 if (last > first + 1)
1cd986c5
NC
430 {
431 info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
432 }
252b5132
RH
433 }
434 }
47b0e7ad 435
252b5132
RH
436 if (pc)
437 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
252b5132 438 }
47b0e7ad 439
252b5132
RH
440 info->fprintf_func (info->stream, "}");
441 }
252b5132 442 break;
47b0e7ad 443
1cd986c5
NC
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);
252b5132 449 break;
47b0e7ad 450 }
252b5132 451
7d063384 452 if (square)
252b5132
RH
453 (*info->fprintf_func) (info->stream, "]");
454 }
455
252b5132
RH
456 /* All done. */
457 break;
458 }
1cd986c5 459 next_opcode:
252b5132
RH
460 op++;
461 }
462
1cd986c5 463 return match;
252b5132
RH
464}
465
47b0e7ad
NC
466int
467print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
252b5132 468{
1cd986c5
NC
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 }
252b5132 498
252b5132 499 status = info->read_memory_func (memaddr, buffer, 2, info);
1cd986c5
NC
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)
252b5132 512 {
1cd986c5
NC
513 insn2 = bfd_getl16 (buffer);
514 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
515 }
47b0e7ad 516
1cd986c5
NC
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)
252b5132 536 {
1cd986c5
NC
537 length = 2;
538 code_length = 6;
539 }
540 }
252b5132 541
1cd986c5
NC
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;
252b5132
RH
568 }
569 }
47b0e7ad 570
1cd986c5
NC
571 if (length == 0
572 && target_processor != PROCESSOR_V850)
252b5132 573 {
1cd986c5
NC
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 }
252b5132
RH
650 }
651
1cd986c5 652 return code_length;
252b5132 653}
This page took 0.735998 seconds and 4 git commands to generate.