* v850-dis.c (disassemble): Always print a closing square brace if
[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 bfd_boolean square = FALSE;
287 long value;
288 int flag;
289 char *prefix;
290
291 operand = &v850_operands[*opindex_ptr];
292
293 value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
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
311 in an instruction is the register for a memory address.
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. */
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 }
325
326 if (opnum == 1 && opnum == memop)
327 {
328 info->fprintf_func (info->stream, "%s[", prefix);
329 square = TRUE;
330 }
331 else if (opnum > 1
332 && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
333 && opnum == memop)
334 {
335 info->fprintf_func (info->stream, "%s[", prefix);
336 square = TRUE;
337 }
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);
349
350 switch (flag)
351 {
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;
356
357 case V850E_OPERAND_REG_LIST:
358 {
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 };
361 int *regs;
362 int i;
363 unsigned long int mask = 0;
364 int pc = 0;
365
366
367 switch (operand->shift)
368 {
369 case 0xffe00001: regs = list12_regs; break;
370 default:
371 /* xgettext:c-format */
372 fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
373 abort ();
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 */
384 case 0: fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
385 case -1: pc = 1; break;
386 }
387 }
388 }
389
390 info->fprintf_func (info->stream, "{");
391
392 if (mask || pc)
393 {
394 if (mask)
395 {
396 unsigned int bit;
397 int shown_one = 0;
398
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
408 shown_one = 1;
409
410 info->fprintf_func (info->stream, v850_reg_names[first]);
411
412 for (bit++; bit < 32; bit++)
413 if ((mask & (1 << bit)) == 0)
414 break;
415
416 last = bit;
417
418 if (last > first + 1)
419 {
420 info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
421 }
422 }
423 }
424
425 if (pc)
426 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
427 }
428
429 info->fprintf_func (info->stream, "}");
430 }
431 break;
432
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);
438 break;
439 }
440
441 if (square)
442 (*info->fprintf_func) (info->stream, "]");
443 }
444
445 /* All done. */
446 break;
447 }
448 next_opcode:
449 op++;
450 }
451
452 return match;
453 }
454
455 int
456 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
457 {
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 }
487
488 status = info->read_memory_func (memaddr, buffer, 2, info);
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)
501 {
502 insn2 = bfd_getl16 (buffer);
503 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
504 }
505
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)
525 {
526 length = 2;
527 code_length = 6;
528 }
529 }
530
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;
557 }
558 }
559
560 if (length == 0
561 && target_processor != PROCESSOR_V850)
562 {
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 }
639 }
640
641 return code_length;
642 }
This page took 0.072338 seconds and 5 git commands to generate.