2013-01-24 Hafiz Abid Qadeer <abidh@codesourcery.com>
[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;
dd42f060
NC
121 else if (value & 0x8000)
122 value |= (-1L << 16);
1cd986c5
NC
123
124 return value;
125 }
126
127 if (!noerror)
128 info->memory_error_func (status, memaddr + bytes_read, info);
129
130 return 0;
131 }
132
133 if (operand->flags & V850E_IMMEDIATE23)
134 {
135 int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
136
137 if (status == 0)
138 {
139 value = bfd_getl32 (buffer);
140
141 value = (operand->extract) (value, invalid);
142
143 return value;
144 }
145
146 if (!noerror)
147 info->memory_error_func (status, memaddr + bytes_read, info);
148
149 return 0;
150 }
151
152 if (operand->flags & V850E_IMMEDIATE32)
153 {
154 int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
155
156 if (status == 0)
157 {
158 bytes_read += 4;
159 value = bfd_getl32 (buffer);
160
161 return value;
162 }
163
164 if (!noerror)
165 info->memory_error_func (status, memaddr + bytes_read, info);
166
167 return 0;
168 }
169
170 if (operand->extract)
171 value = (operand->extract) (insn, invalid);
172 else
173 {
174 if (operand->bits == -1)
175 value = (insn & operand->shift);
176 else
177 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
178
179 if (operand->flags & V850_OPERAND_SIGNED)
180 value = ((long)(value << (sizeof (long)*8 - operand->bits))
181 >> (sizeof (long)*8 - operand->bits));
182 }
183
184 return value;
185}
186
187
188static int
189disassemble (bfd_vma memaddr, struct disassemble_info *info, int bytes_read, unsigned long insn)
190{
191 struct v850_opcode *op = (struct v850_opcode *)v850_opcodes;
192 const struct v850_operand *operand;
193 int match = 0;
194 int target_processor;
252b5132
RH
195
196 switch (info->mach)
197 {
198 case 0:
199 default:
200 target_processor = PROCESSOR_V850;
201 break;
202
203 case bfd_mach_v850e:
204 target_processor = PROCESSOR_V850E;
205 break;
8ad30312
NC
206
207 case bfd_mach_v850e1:
1cd986c5
NC
208 target_processor = PROCESSOR_V850E;
209 break;
210
211 case bfd_mach_v850e2:
212 target_processor = PROCESSOR_V850E2;
213 break;
214
215 case bfd_mach_v850e2v3:
216 target_processor = PROCESSOR_V850E2V3;
8ad30312 217 break;
252b5132 218 }
47b0e7ad 219
1cd986c5
NC
220 /* If this is a two byte insn, then mask off the high bits. */
221 if (bytes_read == 2)
222 insn &= 0xffff;
223
252b5132
RH
224 /* Find the opcode. */
225 while (op->name)
226 {
227 if ((op->mask & insn) == op->opcode
1cd986c5
NC
228 && (op->processors & target_processor)
229 && !(op->processors & PROCESSOR_OPTION_ALIAS))
252b5132 230 {
1cd986c5 231 /* Code check start. */
b34976b6
AM
232 const unsigned char *opindex_ptr;
233 unsigned int opnum;
234 unsigned int memop;
252b5132 235
1cd986c5
NC
236 for (opindex_ptr = op->operands, opnum = 1;
237 *opindex_ptr != 0;
238 opindex_ptr++, opnum++)
239 {
240 int invalid = 0;
241 long value;
242
243 operand = &v850_operands[*opindex_ptr];
244
245 value = get_operand_value (operand, insn, bytes_read, memaddr, info, 1, &invalid);
246
247 if (invalid)
248 goto next_opcode;
249
250 if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
251 goto next_opcode;
252
253 if ((operand->flags & V850_NOT_SA) && value == 0xd)
254 goto next_opcode;
255
256 if ((operand->flags & V850_NOT_IMM0) && value == 0)
257 goto next_opcode;
258 }
259
260 /* Code check end. */
261
252b5132
RH
262 match = 1;
263 (*info->fprintf_func) (info->stream, "%s\t", op->name);
1cd986c5
NC
264#if 0
265 fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
266 insn, op->mask, op->opcode, op->name );
267#endif
252b5132
RH
268
269 memop = op->memop;
270 /* Now print the operands.
271
272 MEMOP is the operand number at which a memory
273 address specification starts, or zero if this
274 instruction has no memory addresses.
275
276 A memory address is always two arguments.
277
278 This information allows us to determine when to
279 insert commas into the output stream as well as
280 when to insert disp[reg] expressions onto the
281 output stream. */
47b0e7ad 282
252b5132
RH
283 for (opindex_ptr = op->operands, opnum = 1;
284 *opindex_ptr != 0;
285 opindex_ptr++, opnum++)
286 {
7d063384 287 bfd_boolean square = FALSE;
b34976b6
AM
288 long value;
289 int flag;
1cd986c5 290 char *prefix;
47b0e7ad 291
252b5132 292 operand = &v850_operands[*opindex_ptr];
47b0e7ad 293
1cd986c5 294 value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
252b5132
RH
295
296 /* The first operand is always output without any
297 special handling.
298
299 For the following arguments:
300
301 If memop && opnum == memop + 1, then we need '[' since
302 we're about to output the register used in a memory
303 reference.
304
305 If memop && opnum == memop + 2, then we need ']' since
306 we just finished the register in a memory reference. We
307 also need a ',' before this operand.
308
309 Else we just need a comma.
310
311 We may need to output a trailing ']' if the last operand
47b0e7ad 312 in an instruction is the register for a memory address.
252b5132 313
04ee5257 314 The exception (and there's always an exception) are the
252b5132 315 "jmp" insn which needs square brackets around it's only
04ee5257
NC
316 register argument, and the clr1/not1/set1/tst1 insns
317 which [...] around their second register argument. */
318
1cd986c5
NC
319 prefix = "";
320 if (operand->flags & V850_OPERAND_BANG)
321 {
322 prefix = "!";
323 }
324 else if (operand->flags & V850_OPERAND_PERCENT)
325 {
326 prefix = "%";
327 }
252b5132 328
1cd986c5 329 if (opnum == 1 && opnum == memop)
7d063384
NC
330 {
331 info->fprintf_func (info->stream, "%s[", prefix);
332 square = TRUE;
333 }
1cd986c5
NC
334 else if (opnum > 1
335 && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
336 && opnum == memop)
7d063384
NC
337 {
338 info->fprintf_func (info->stream, "%s[", prefix);
339 square = TRUE;
340 }
04ee5257
NC
341 else if (opnum == 2
342 && ( op->opcode == 0x00e407e0 /* clr1 */
343 || op->opcode == 0x00e207e0 /* not1 */
344 || op->opcode == 0x00e007e0 /* set1 */
345 || op->opcode == 0x00e607e0 /* tst1 */
346 ))
347 {
348 info->fprintf_func (info->stream, ", %s[", prefix);
349 square = TRUE;
350 }
1cd986c5
NC
351 else if (opnum > 1)
352 info->fprintf_func (info->stream, ", %s", prefix);
353
354 /* Extract the flags, ignoring ones which do not effect disassembly output. */
355 flag = operand->flags & (V850_OPERAND_REG
356 | V850_REG_EVEN
357 | V850_OPERAND_EP
358 | V850_OPERAND_SRG
359 | V850E_OPERAND_REG_LIST
360 | V850_OPERAND_CC
361 | V850_OPERAND_FLOAT_CC);
47b0e7ad 362
252b5132
RH
363 switch (flag)
364 {
1cd986c5
NC
365 case V850_OPERAND_REG: info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
366 case (V850_OPERAND_REG|V850_REG_EVEN): info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
367 case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break;
368 case V850_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
47b0e7ad 369
1cd986c5 370 case V850E_OPERAND_REG_LIST:
252b5132 371 {
1cd986c5
NC
372 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
b34976b6
AM
374 int *regs;
375 int i;
252b5132 376 unsigned long int mask = 0;
b34976b6 377 int pc = 0;
1cd986c5 378
47b0e7ad 379
252b5132
RH
380 switch (operand->shift)
381 {
382 case 0xffe00001: regs = list12_regs; break;
252b5132
RH
383 default:
384 /* xgettext:c-format */
1cd986c5 385 fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
47b0e7ad 386 abort ();
252b5132
RH
387 }
388
389 for (i = 0; i < 32; i++)
390 {
391 if (value & (1 << i))
392 {
393 switch (regs[ i ])
394 {
395 default: mask |= (1 << regs[ i ]); break;
396 /* xgettext:c-format */
1cd986c5 397 case 0: fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
b34976b6 398 case -1: pc = 1; break;
252b5132
RH
399 }
400 }
401 }
402
403 info->fprintf_func (info->stream, "{");
47b0e7ad 404
1cd986c5 405 if (mask || pc)
252b5132
RH
406 {
407 if (mask)
408 {
409 unsigned int bit;
b34976b6 410 int shown_one = 0;
47b0e7ad 411
252b5132
RH
412 for (bit = 0; bit < 32; bit++)
413 if (mask & (1 << bit))
414 {
415 unsigned long int first = bit;
416 unsigned long int last;
417
418 if (shown_one)
419 info->fprintf_func (info->stream, ", ");
420 else
b34976b6 421 shown_one = 1;
47b0e7ad 422
48891606 423 info->fprintf_func (info->stream, "%s", v850_reg_names[first]);
47b0e7ad 424
252b5132
RH
425 for (bit++; bit < 32; bit++)
426 if ((mask & (1 << bit)) == 0)
427 break;
428
429 last = bit;
430
431 if (last > first + 1)
1cd986c5
NC
432 {
433 info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
434 }
252b5132
RH
435 }
436 }
47b0e7ad 437
252b5132
RH
438 if (pc)
439 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
252b5132 440 }
47b0e7ad 441
252b5132
RH
442 info->fprintf_func (info->stream, "}");
443 }
252b5132 444 break;
47b0e7ad 445
1cd986c5
NC
446 case V850_OPERAND_CC: info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
447 case V850_OPERAND_FLOAT_CC: info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
448
449 default:
450 print_value (operand->flags, memaddr, info, value);
252b5132 451 break;
47b0e7ad 452 }
252b5132 453
7d063384 454 if (square)
252b5132
RH
455 (*info->fprintf_func) (info->stream, "]");
456 }
457
252b5132
RH
458 /* All done. */
459 break;
460 }
1cd986c5 461 next_opcode:
252b5132
RH
462 op++;
463 }
464
1cd986c5 465 return match;
252b5132
RH
466}
467
47b0e7ad
NC
468int
469print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
252b5132 470{
1cd986c5
NC
471 int status, status2, match;
472 bfd_byte buffer[8];
473 int length = 0, code_length = 0;
474 unsigned long insn = 0, insn2 = 0;
475 int target_processor;
476
477 switch (info->mach)
478 {
479 case 0:
480 default:
481 target_processor = PROCESSOR_V850;
482 break;
483
484 case bfd_mach_v850e:
485 target_processor = PROCESSOR_V850E;
486 break;
487
488 case bfd_mach_v850e1:
489 target_processor = PROCESSOR_V850E;
490 break;
491
492 case bfd_mach_v850e2:
493 target_processor = PROCESSOR_V850E2;
494 break;
495
496 case bfd_mach_v850e2v3:
497 target_processor = PROCESSOR_V850E2V3;
498 break;
499 }
252b5132 500
252b5132 501 status = info->read_memory_func (memaddr, buffer, 2, info);
1cd986c5
NC
502
503 if (status)
504 {
505 info->memory_error_func (status, memaddr, info);
506 return -1;
507 }
508
509 insn = bfd_getl16 (buffer);
510
511 status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
512
513 if (!status2)
252b5132 514 {
1cd986c5
NC
515 insn2 = bfd_getl16 (buffer);
516 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
517 }
47b0e7ad 518
1cd986c5
NC
519 /* Special case. */
520 if (length == 0
521 && (target_processor == PROCESSOR_V850E2
522 || target_processor == PROCESSOR_V850E2V3))
523 {
524 if ((insn & 0xffff) == 0x02e0 /* jr 32bit */
525 && !status2 && (insn2 & 0x1) == 0)
526 {
527 length = 2;
528 code_length = 6;
529 }
530 else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */
531 && !status2 && (insn2 & 0x1) == 0)
532 {
533 length = 2;
534 code_length = 6;
535 }
536 else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */
537 && !status2 && (insn2 & 0x1) == 0)
252b5132 538 {
1cd986c5
NC
539 length = 2;
540 code_length = 6;
541 }
542 }
252b5132 543
1cd986c5
NC
544 if (length == 0
545 && target_processor == PROCESSOR_V850E2V3)
546 {
547 if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */
548 && !status2 && (insn2 & 0x000f) == 0x0005)
549 || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */
550 && !status2 && (insn2 & 0x000f) == 0x0005)
551 || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */
552 && !status2 && (insn2 & 0x000f) == 0x0007)
553 || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */
554 && !status2 && (insn2 & 0x000f) == 0x0007)
555 || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */
556 && !status2 && (insn2 & 0x000f) == 0x0009))
557 {
558 length = 4;
559 code_length = 6;
560 }
561 else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */
562 && !status2 && (insn2 & 0x000f) == 0x000d)
563 || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */
564 && !status2 && (insn2 & 0x000f) == 0x000d)
565 || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */
566 && !status2 && (insn2 & 0x000f) == 0x000f))
567 {
568 length = 4;
569 code_length = 6;
252b5132
RH
570 }
571 }
47b0e7ad 572
1cd986c5
NC
573 if (length == 0
574 && target_processor != PROCESSOR_V850)
252b5132 575 {
1cd986c5
NC
576 if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */
577 {
578 length = 2;
579 code_length = 6;
580 }
581 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */
582 && !status2 && (insn2 & 0x001f) == 0x0013)
583 {
584 length = 4;
585 code_length = 6;
586 }
587 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */
588 && !status2 && (insn2 & 0x001f) == 0x000b)
589 {
590 length = 4;
591 code_length = 6;
592 }
593 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */
594 && !status2 && (insn2 & 0x001f) == 0x001b)
595 {
596 length = 4;
597 code_length = 8;
598 }
599 }
600
601 if (length == 4
602 || (length == 0
603 && (insn & 0x0600) == 0x0600))
604 {
605 /* This is a 4 byte insn. */
606 status = info->read_memory_func (memaddr, buffer, 4, info);
607 if (!status)
608 {
609 insn = bfd_getl32 (buffer);
610
611 if (!length)
612 length = code_length = 4;
613 }
614 }
615
616 if (code_length > length)
617 {
618 status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
619 if (status)
620 length = 0;
621 }
622
623 if (length == 0 && !status)
624 length = code_length = 2;
625
626 if (length == 2)
627 insn &= 0xffff;
628
629 match = disassemble (memaddr, info, length, insn);
630
631 if (!match)
632 {
633 int l = 0;
634
635 status = info->read_memory_func (memaddr, buffer, code_length, info);
636
637 while (l < code_length)
638 {
639 if (code_length - l == 2)
640 {
641 insn = bfd_getl16 (buffer + l) & 0xffff;
642 info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
643 l += 2;
644 }
645 else
646 {
647 insn = bfd_getl32 (buffer + l);
648 info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
649 l += 4;
650 }
651 }
252b5132
RH
652 }
653
1cd986c5 654 return code_length;
252b5132 655}
This page took 0.825602 seconds and 4 git commands to generate.