xref: /netbsd-src/external/gpl3/binutils/dist/opcodes/v850-dis.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
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 }
636