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
30static 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
38static 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
50static 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
56static 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
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}
98
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;
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
448int
449print_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