1211501Sanchie/* Disassemble V850 instructions.
2211501Sanchie   Copyright (C) 1996-2022 Free Software Foundation, Inc.
3211501Sanchie
4211501Sanchie   This file is part of the GNU opcodes library.
5211501Sanchie
6211501Sanchie   This library is free software; you can redistribute it and/or modify
7211501Sanchie   it under the terms of the GNU General Public License as published by
8211501Sanchie   the Free Software Foundation; either version 3, or (at your option)
9211501Sanchie   any later version.
10211501Sanchie
11211501Sanchie   It is distributed in the hope that it will be useful, but WITHOUT
12211501Sanchie   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13211501Sanchie   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14211501Sanchie   License for more details.
15211501Sanchie
16211501Sanchie   You should have received a copy of the GNU General Public License
17211501Sanchie   along with this program; if not, write to the Free Software
18211501Sanchie   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19211501Sanchie   MA 02110-1301, USA.  */
20211501Sanchie
21211501Sanchie
22211501Sanchie#include "sysdep.h"
23211501Sanchie#include <stdio.h>
24211501Sanchie#include <string.h>
25211501Sanchie#include "opcode/v850.h"
26211501Sanchie#include "disassemble.h"
27211501Sanchie#include "opintl.h"
28211501Sanchie#include "libiberty.h"
29211501Sanchie
30254889Smarkjstatic const int v850_cacheop_codes[] =
31254889Smarkj{
32211501Sanchie  0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06,
33211501Sanchie  0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1
34211501Sanchie};
35211501Sanchie
36211501Sanchiestatic const int v850_prefop_codes[] =
37211501Sanchie{ 0x00, 0x04, -1};
38254889Smarkj
39211501Sanchiestatic void
40211501Sanchieprint_value (int flags,
41211501Sanchie	     bfd_vma memaddr,
42211501Sanchie	     struct disassemble_info *info,
43211501Sanchie	     long value)
44211501Sanchie{
45211501Sanchie  if (flags & V850_PCREL)
46211501Sanchie    {
47211501Sanchie      bfd_vma addr = value + memaddr;
48211501Sanchie
49211501Sanchie      if (flags & V850_INVERSE_PCREL)
50211501Sanchie	addr = memaddr - value;
51211501Sanchie      info->print_address_func (addr, info);
52254889Smarkj    }
53211501Sanchie  else if (flags & V850_OPERAND_DISP)
54211501Sanchie    {
55211501Sanchie      if (flags & V850_OPERAND_SIGNED)
56211501Sanchie        {
57211501Sanchie          info->fprintf_func (info->stream, "%ld", value);
58211501Sanchie        }
59211501Sanchie      else
60211501Sanchie        {
61211501Sanchie          info->fprintf_func (info->stream, "%lu", value);
62227293Sed        }
63211501Sanchie    }
64211501Sanchie  else if ((flags & V850E_IMMEDIATE32)
65211501Sanchie	   || (flags & V850E_IMMEDIATE16HI))
66211501Sanchie    {
67215701Sdim      info->fprintf_func (info->stream, "0x%lx", value);
68211501Sanchie    }
69211501Sanchie  else
70211501Sanchie    {
71211501Sanchie      if (flags & V850_OPERAND_SIGNED)
72211501Sanchie	{
73211501Sanchie	  info->fprintf_func (info->stream, "%ld", value);
74211501Sanchie	}
75211501Sanchie      else
76211501Sanchie	{
77211501Sanchie	  info->fprintf_func (info->stream, "%lu", value);
78211501Sanchie	}
79211501Sanchie    }
80211501Sanchie}
81211501Sanchie
82211501Sanchiestatic long
83211501Sanchieget_operand_value (const struct v850_operand *operand,
84211501Sanchie		   unsigned long insn,
85211501Sanchie		   int bytes_read,
86211501Sanchie		   bfd_vma memaddr,
87211501Sanchie		   struct disassemble_info * info,
88211501Sanchie		   bool noerror,
89211501Sanchie		   int *invalid)
90211501Sanchie{
91211501Sanchie  unsigned long value;
92211501Sanchie  bfd_byte buffer[4];
93211501Sanchie
94211501Sanchie  if ((operand->flags & V850E_IMMEDIATE16)
95211501Sanchie      || (operand->flags & V850E_IMMEDIATE16HI))
96211501Sanchie    {
97211501Sanchie      int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
98211501Sanchie
99211501Sanchie      if (status == 0)
100211501Sanchie	{
101211501Sanchie	  value = bfd_getl16 (buffer);
102211501Sanchie
103211501Sanchie	  if (operand->flags & V850E_IMMEDIATE16HI)
104211501Sanchie	    value <<= 16;
105211501Sanchie	  else if (value & 0x8000)
106211501Sanchie	    value |= (-1UL << 16);
107211501Sanchie
108211501Sanchie	  return value;
109211501Sanchie	}
110211501Sanchie
111211501Sanchie      if (!noerror)
112211501Sanchie	info->memory_error_func (status, memaddr + bytes_read, info);
113211501Sanchie
114211501Sanchie      return 0;
115211501Sanchie    }
116211501Sanchie
117211501Sanchie  if (operand->flags & V850E_IMMEDIATE23)
118211501Sanchie    {
119211501Sanchie      int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
120211501Sanchie
121211501Sanchie      if (status == 0)
122211501Sanchie	{
123211501Sanchie	  value = bfd_getl32 (buffer);
124211501Sanchie
125211501Sanchie	  value = (operand->extract) (value, invalid);
126211501Sanchie
127211501Sanchie	  return value;
128211501Sanchie	}
129211501Sanchie
130211501Sanchie      if (!noerror)
131211501Sanchie	info->memory_error_func (status, memaddr + bytes_read, info);
132211501Sanchie
133211501Sanchie      return 0;
134211501Sanchie    }
135211501Sanchie
136211501Sanchie  if (operand->flags & V850E_IMMEDIATE32)
137211501Sanchie    {
138211501Sanchie      int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
139211501Sanchie
140211501Sanchie      if (status == 0)
141211501Sanchie	{
142211501Sanchie	  bytes_read += 4;
143211501Sanchie	  value = bfd_getl32 (buffer);
144211501Sanchie
145211501Sanchie	  return value;
146211501Sanchie	}
147211501Sanchie
148211501Sanchie      if (!noerror)
149211501Sanchie	info->memory_error_func (status, memaddr + bytes_read, info);
150211501Sanchie
151211501Sanchie      return 0;
152211501Sanchie    }
153211501Sanchie
154211501Sanchie  if (operand->extract)
155211501Sanchie    value = (operand->extract) (insn, invalid);
156211501Sanchie  else
157211501Sanchie    {
158211501Sanchie      if (operand->bits == -1)
159211501Sanchie	value = (insn & operand->shift);
160211501Sanchie      else
161211501Sanchie	value = (insn >> operand->shift) & ((1ul << operand->bits) - 1);
162211501Sanchie
163211501Sanchie      if (operand->flags & V850_OPERAND_SIGNED)
164211501Sanchie	{
165211501Sanchie	  unsigned long sign = 1ul << (operand->bits - 1);
166211501Sanchie	  value = (value ^ sign) - sign;
167211501Sanchie	}
168211501Sanchie    }
169211501Sanchie
170211501Sanchie  return value;
171211501Sanchie}
172211501Sanchie
173211501Sanchiestatic const char *
174211501Sanchieget_v850_sreg_name (unsigned int reg)
175211501Sanchie{
176211501Sanchie  static const char *const v850_sreg_names[] =
177211501Sanchie    {
178211501Sanchie     "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
179211501Sanchie     "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
180211501Sanchie     "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
181211501Sanchie     "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
182211501Sanchie     "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
183211501Sanchie     "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
184211501Sanchie     "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
185211501Sanchie     "fewr", "dbwr", "bsel"
186211501Sanchie    };
187254523Sandre
188254523Sandre  if (reg < ARRAY_SIZE (v850_sreg_names))
189254889Smarkj    return v850_sreg_names[reg];
190254889Smarkj  return _("<invalid s-reg number>");
191211501Sanchie}
192211501Sanchie
193211501Sanchiestatic const char *
194211501Sanchieget_v850_reg_name (unsigned int reg)
195211501Sanchie{
196211501Sanchie  static const char *const v850_reg_names[] =
197211501Sanchie    {
198211501Sanchie     "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
199211501Sanchie     "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
200211501Sanchie     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
201211501Sanchie     "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
202211501Sanchie    };
203211501Sanchie
204211501Sanchie  if (reg < ARRAY_SIZE (v850_reg_names))
205211501Sanchie    return v850_reg_names[reg];
206211501Sanchie  return _("<invalid reg number>");
207211501Sanchie}
208211501Sanchie
209211501Sanchiestatic const char *
210211501Sanchieget_v850_vreg_name (unsigned int reg)
211211501Sanchie{
212211501Sanchie  static const char *const v850_vreg_names[] =
213211501Sanchie    {
214211501Sanchie     "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9",
215211501Sanchie     "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18",
216211501Sanchie     "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27",
217211501Sanchie     "vr28", "vr29", "vr30", "vr31"
218211501Sanchie    };
219211501Sanchie
220211501Sanchie  if (reg < ARRAY_SIZE (v850_vreg_names))
221211501Sanchie    return v850_vreg_names[reg];
222211501Sanchie  return _("<invalid v-reg number>");
223211501Sanchie}
224211501Sanchie
225211501Sanchiestatic const char *
226211501Sanchieget_v850_cc_name (unsigned int reg)
227211501Sanchie{
228211501Sanchie  static const char *const v850_cc_names[] =
229211501Sanchie    {
230211501Sanchie     "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
231211501Sanchie     "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
232211501Sanchie    };
233211501Sanchie
234211501Sanchie  if (reg < ARRAY_SIZE (v850_cc_names))
235211501Sanchie    return v850_cc_names[reg];
236211501Sanchie  return _("<invalid CC-reg number>");
237211501Sanchie}
238211501Sanchie
239211501Sanchiestatic const char *
240211501Sanchieget_v850_float_cc_name (unsigned int reg)
241211501Sanchie{
242211501Sanchie  static const char *const v850_float_cc_names[] =
243211501Sanchie    {
244211501Sanchie     "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
245211501Sanchie     "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
246211501Sanchie    };
247211501Sanchie
248211501Sanchie  if (reg < ARRAY_SIZE (v850_float_cc_names))
249211501Sanchie    return v850_float_cc_names[reg];
250211501Sanchie  return _("<invalid float-CC-reg number>");
251211501Sanchie}
252211501Sanchie
253211501Sanchiestatic const char *
254211501Sanchieget_v850_cacheop_name (unsigned int reg)
255211501Sanchie{
256211501Sanchie  static const char *const v850_cacheop_names[] =
257211501Sanchie    {
258211501Sanchie     "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd",
259211501Sanchie     "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd"
260211501Sanchie    };
261211501Sanchie
262211501Sanchie  if (reg < ARRAY_SIZE (v850_cacheop_names))
263211501Sanchie    return v850_cacheop_names[reg];
264211501Sanchie  return _("<invalid cacheop number>");
265211501Sanchie}
266211501Sanchie
267211501Sanchiestatic const char *
268211501Sanchieget_v850_prefop_name (unsigned int reg)
269211501Sanchie{
270211501Sanchie  static const char *const v850_prefop_names[] =
271211501Sanchie    { "prefi", "prefd" };
272211501Sanchie
273211501Sanchie  if (reg < ARRAY_SIZE (v850_prefop_names))
274211501Sanchie    return v850_prefop_names[reg];
275211501Sanchie  return _("<invalid prefop number>");
276211501Sanchie}
277211501Sanchie
278211501Sanchiestatic int
279211501Sanchiedisassemble (bfd_vma memaddr,
280211501Sanchie	     struct disassemble_info *info,
281211501Sanchie	     int bytes_read,
282211501Sanchie	     unsigned long insn)
283211501Sanchie{
284211501Sanchie  struct v850_opcode *op = (struct v850_opcode *) v850_opcodes;
285211501Sanchie  const struct v850_operand *operand;
286211501Sanchie  int match = 0;
287211501Sanchie  int target_processor;
288211501Sanchie
289211501Sanchie  switch (info->mach)
290211501Sanchie    {
291211501Sanchie    case 0:
292211501Sanchie    default:
293211501Sanchie      target_processor = PROCESSOR_V850;
294211501Sanchie      break;
295211501Sanchie
296211501Sanchie    case bfd_mach_v850e:
297211501Sanchie      target_processor = PROCESSOR_V850E;
298211501Sanchie      break;
299211501Sanchie
300211501Sanchie    case bfd_mach_v850e1:
301211501Sanchie      target_processor = PROCESSOR_V850E;
302211501Sanchie      break;
303211501Sanchie
304211501Sanchie    case bfd_mach_v850e2:
305211501Sanchie      target_processor = PROCESSOR_V850E2;
306211501Sanchie      break;
307211501Sanchie
308211501Sanchie    case bfd_mach_v850e2v3:
309211501Sanchie      target_processor = PROCESSOR_V850E2V3;
310211501Sanchie      break;
311211501Sanchie
312211501Sanchie    case bfd_mach_v850e3v5:
313211501Sanchie      target_processor = PROCESSOR_V850E3V5;
314211501Sanchie      break;
315211501Sanchie    }
316211501Sanchie
317211501Sanchie  /* If this is a two byte insn, then mask off the high bits.  */
318211501Sanchie  if (bytes_read == 2)
319211501Sanchie    insn &= 0xffff;
320211501Sanchie
321211501Sanchie  /* Find the opcode.  */
322211501Sanchie  while (op->name)
323211501Sanchie    {
324211501Sanchie      if ((op->mask & insn) == op->opcode
325211501Sanchie	  && (op->processors & target_processor)
326211501Sanchie	  && !(op->processors & PROCESSOR_OPTION_ALIAS))
327211501Sanchie	{
328211501Sanchie	  /* Code check start.  */
329211501Sanchie	  const unsigned char *opindex_ptr;
330211501Sanchie	  unsigned int opnum;
331211501Sanchie	  unsigned int memop;
332211501Sanchie
333211501Sanchie	  for (opindex_ptr = op->operands, opnum = 1;
334211501Sanchie	       *opindex_ptr != 0;
335211501Sanchie	       opindex_ptr++, opnum++)
336211501Sanchie	    {
337211501Sanchie	      int invalid = 0;
338211501Sanchie	      long value;
339211501Sanchie
340211501Sanchie	      operand = &v850_operands[*opindex_ptr];
341211501Sanchie
342211501Sanchie	      value = get_operand_value (operand, insn, bytes_read, memaddr,
343211501Sanchie					 info, 1, &invalid);
344211501Sanchie
345211501Sanchie	      if (invalid)
346211501Sanchie		goto next_opcode;
347211501Sanchie
348211501Sanchie              if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
349211501Sanchie		goto next_opcode;
350211501Sanchie
351211501Sanchie	      if ((operand->flags & V850_NOT_SA) && value == 0xd)
352211501Sanchie		goto next_opcode;
353211501Sanchie
354211501Sanchie	      if ((operand->flags & V850_NOT_IMM0) && value == 0)
355211501Sanchie		goto next_opcode;
356211501Sanchie	    }
357211501Sanchie
358211501Sanchie	  /* Code check end.  */
359211501Sanchie
360211501Sanchie	  match = 1;
361211501Sanchie	  (*info->fprintf_func) (info->stream, "%s\t", op->name);
362211501Sanchie#if 0
363211501Sanchie	  fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
364211501Sanchie		   insn, op->mask, op->opcode, op->name );
365211501Sanchie#endif
366211501Sanchie
367211501Sanchie	  memop = op->memop;
368211501Sanchie	  /* Now print the operands.
369211501Sanchie
370211501Sanchie	     MEMOP is the operand number at which a memory
371211501Sanchie	     address specification starts, or zero if this
372241394Skevlo	     instruction has no memory addresses.
373211501Sanchie
374211501Sanchie	     A memory address is always two arguments.
375211501Sanchie
376	     This information allows us to determine when to
377	     insert commas into the output stream as well as
378	     when to insert disp[reg] expressions onto the
379	     output stream.  */
380
381	  for (opindex_ptr = op->operands, opnum = 1;
382	       *opindex_ptr != 0;
383	       opindex_ptr++, opnum++)
384	    {
385	      bool square = false;
386	      long value;
387	      int flag;
388	      char *prefix;
389
390	      operand = &v850_operands[*opindex_ptr];
391
392	      value = get_operand_value (operand, insn, bytes_read, memaddr,
393					 info, 0, 0);
394
395	      /* The first operand is always output without any
396		 special handling.
397
398		 For the following arguments:
399
400		   If memop && opnum == memop + 1, then we need '[' since
401		   we're about to output the register used in a memory
402		   reference.
403
404		   If memop && opnum == memop + 2, then we need ']' since
405		   we just finished the register in a memory reference.  We
406		   also need a ',' before this operand.
407
408		   Else we just need a comma.
409
410		   We may need to output a trailing ']' if the last operand
411		   in an instruction is the register for a memory address.
412
413		   The exception (and there's always an exception) are the
414		   "jmp" insn which needs square brackets around it's only
415		   register argument, and the clr1/not1/set1/tst1 insns
416		   which [...] around their second register argument.  */
417
418	      prefix = "";
419	      if (operand->flags & V850_OPERAND_BANG)
420		{
421		  prefix = "!";
422		}
423	      else if (operand->flags & V850_OPERAND_PERCENT)
424		{
425		  prefix = "%";
426		}
427
428	      if (opnum == 1 && opnum == memop)
429		{
430		  info->fprintf_func (info->stream, "%s[", prefix);
431		  square = true;
432		}
433	      else if (   (strcmp ("stc.w", op->name) == 0
434			|| strcmp ("cache", op->name) == 0
435			|| strcmp ("pref",  op->name) == 0)
436		       && opnum == 2 && opnum == memop)
437		{
438		  info->fprintf_func (info->stream, ", [");
439		  square = true;
440		}
441	      else if (   (strcmp (op->name, "pushsp") == 0
442			|| strcmp (op->name, "popsp") == 0
443			|| strcmp (op->name, "dbpush" ) == 0)
444		       && opnum == 2)
445		{
446		  info->fprintf_func (info->stream, "-");
447		}
448	      else if (opnum > 1
449		       && (v850_operands[*(opindex_ptr - 1)].flags
450			   & V850_OPERAND_DISP) != 0
451		       && opnum == memop)
452		{
453		  info->fprintf_func (info->stream, "%s[", prefix);
454		  square = true;
455		}
456	      else if (opnum == 2
457		       && (   op->opcode == 0x00e407e0 /* clr1 */
458			   || op->opcode == 0x00e207e0 /* not1 */
459			   || op->opcode == 0x00e007e0 /* set1 */
460			   || op->opcode == 0x00e607e0 /* tst1 */
461			   ))
462		{
463		  info->fprintf_func (info->stream, ", %s[", prefix);
464		  square = true;
465		}
466	      else if (opnum > 1)
467		info->fprintf_func (info->stream, ", %s", prefix);
468
469 	      /* Extract the flags, ignoring ones which do not
470		 effect disassembly output.  */
471	      flag = operand->flags & (V850_OPERAND_REG
472				       | V850_REG_EVEN
473				       | V850_OPERAND_EP
474				       | V850_OPERAND_SRG
475				       | V850E_OPERAND_REG_LIST
476				       | V850_OPERAND_CC
477				       | V850_OPERAND_VREG
478				       | V850_OPERAND_CACHEOP
479				       | V850_OPERAND_PREFOP
480				       | V850_OPERAND_FLOAT_CC);
481
482	      switch (flag)
483		{
484		case V850_OPERAND_REG:
485		  info->fprintf_func (info->stream, "%s", get_v850_reg_name (value));
486		  break;
487		case (V850_OPERAND_REG|V850_REG_EVEN):
488		  info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2));
489		  break;
490		case V850_OPERAND_EP:
491		  info->fprintf_func (info->stream, "ep");
492		  break;
493		case V850_OPERAND_SRG:
494		  info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value));
495		  break;
496		case V850E_OPERAND_REG_LIST:
497		  {
498		    static int list12_regs[32]   = { 30, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
499						     0,  0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
500		    int *regs;
501		    int i;
502		    unsigned int mask = 0;
503		    int pc = 0;
504
505		    switch (operand->shift)
506		      {
507		      case 0xffe00001: regs = list12_regs; break;
508		      default:
509			/* xgettext:c-format */
510			opcodes_error_handler (_("unknown operand shift: %x"),
511					       operand->shift);
512			abort ();
513		      }
514
515		    for (i = 0; i < 32; i++)
516		      {
517			if (value & (1u << i))
518			  {
519			    switch (regs[ i ])
520			      {
521			      default:
522				mask |= (1u << regs[ i ]);
523				break;
524			      case 0:
525				/* xgettext:c-format */
526				opcodes_error_handler (_("unknown reg: %d"), i);
527				abort ();
528				break;
529			      case -1:
530				pc = 1;
531				break;
532			      }
533			  }
534		      }
535
536		    info->fprintf_func (info->stream, "{");
537
538		    if (mask || pc)
539		      {
540			if (mask)
541			  {
542			    unsigned int bit;
543			    int shown_one = 0;
544
545			    for (bit = 0; bit < 32; bit++)
546			      if (mask & (1u << bit))
547				{
548				  unsigned int first = bit;
549				  unsigned int last;
550
551				  if (shown_one)
552				    info->fprintf_func (info->stream, ", ");
553				  else
554				    shown_one = 1;
555
556				  info->fprintf_func (info->stream, "%s", get_v850_reg_name (first));
557
558				  for (bit++; bit < 32; bit++)
559				    if ((mask & (1u << bit)) == 0)
560				      break;
561
562				  last = bit;
563
564				  if (last > first + 1)
565				    {
566				      info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1));
567				    }
568				}
569			  }
570
571			if (pc)
572			  info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
573		      }
574
575		    info->fprintf_func (info->stream, "}");
576		  }
577		  break;
578
579		case V850_OPERAND_CC:
580		  info->fprintf_func (info->stream, "%s", get_v850_cc_name (value));
581		  break;
582
583		case V850_OPERAND_FLOAT_CC:
584		  info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value));
585		  break;
586
587		case V850_OPERAND_CACHEOP:
588		  {
589		    int idx;
590
591		    for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
592		      {
593			if (value == v850_cacheop_codes[idx])
594			  {
595			    info->fprintf_func (info->stream, "%s",
596						get_v850_cacheop_name (idx));
597			    goto MATCH_CACHEOP_CODE;
598			  }
599		      }
600		    info->fprintf_func (info->stream, "%d", (int) value);
601		  }
602		MATCH_CACHEOP_CODE:
603		  break;
604
605		case V850_OPERAND_PREFOP:
606		  {
607		    int idx;
608
609		    for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
610		      {
611			if (value == v850_prefop_codes[idx])
612			  {
613			    info->fprintf_func (info->stream, "%s",
614						get_v850_prefop_name (idx));
615			    goto MATCH_PREFOP_CODE;
616			  }
617		      }
618		    info->fprintf_func (info->stream, "%d", (int) value);
619		  }
620		MATCH_PREFOP_CODE:
621		  break;
622
623		case V850_OPERAND_VREG:
624		  info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value));
625		  break;
626
627		default:
628		  print_value (operand->flags, memaddr, info, value);
629		  break;
630		}
631
632	      if (square)
633		(*info->fprintf_func) (info->stream, "]");
634	    }
635
636	  /* All done. */
637	  break;
638	}
639    next_opcode:
640      op++;
641    }
642
643  return match;
644}
645
646int
647print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
648{
649  int status, status2, match;
650  bfd_byte buffer[8];
651  int length = 0, code_length = 0;
652  unsigned long insn = 0, insn2 = 0;
653  int target_processor;
654
655  switch (info->mach)
656    {
657    case 0:
658    default:
659      target_processor = PROCESSOR_V850;
660      break;
661
662    case bfd_mach_v850e:
663      target_processor = PROCESSOR_V850E;
664      break;
665
666    case bfd_mach_v850e1:
667      target_processor = PROCESSOR_V850E;
668      break;
669
670    case bfd_mach_v850e2:
671      target_processor = PROCESSOR_V850E2;
672      break;
673
674    case bfd_mach_v850e2v3:
675      target_processor = PROCESSOR_V850E2V3;
676      break;
677
678    case bfd_mach_v850e3v5:
679      target_processor = PROCESSOR_V850E3V5;
680      break;
681    }
682
683  status = info->read_memory_func (memaddr, buffer, 2, info);
684
685  if (status)
686    {
687      info->memory_error_func (status, memaddr, info);
688      return -1;
689    }
690
691  insn = bfd_getl16 (buffer);
692
693  status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
694
695  if (!status2)
696    {
697      insn2 = bfd_getl16 (buffer);
698      /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
699    }
700
701  /* Special case.  */
702  if (length == 0
703      && ((target_processor & PROCESSOR_V850E2_UP) != 0))
704    {
705      if ((insn & 0xffff) == 0x02e0		/* jr 32bit */
706	  && !status2 && (insn2 & 0x1) == 0)
707	{
708	  length = 2;
709	  code_length = 6;
710	}
711      else if ((insn & 0xffe0) == 0x02e0	/* jarl 32bit */
712	       && !status2 && (insn2 & 0x1) == 0)
713	{
714	  length = 2;
715	  code_length = 6;
716	}
717      else if ((insn & 0xffe0) == 0x06e0	/* jmp 32bit */
718	       && !status2 && (insn2 & 0x1) == 0)
719	{
720	  length = 2;
721	  code_length = 6;
722	}
723    }
724
725  if (length == 0
726      && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
727    {
728      if (   ((insn & 0xffe0) == 0x07a0		/* ld.dw 23bit (v850e3v5) */
729	      && !status2 && (insn2 & 0x000f) == 0x0009)
730	  || ((insn & 0xffe0) == 0x07a0		/* st.dw 23bit (v850e3v5) */
731	      && !status2 && (insn2 & 0x000f) == 0x000f))
732	{
733	  length = 4;
734	  code_length = 6;
735	}
736    }
737
738  if (length == 0
739      && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
740    {
741      if (((insn & 0xffe0) == 0x0780		/* ld.b 23bit */
742	   && !status2 && (insn2 & 0x000f) == 0x0005)
743	  || ((insn & 0xffe0) == 0x07a0		/* ld.bu 23bit */
744	      && !status2 && (insn2 & 0x000f) == 0x0005)
745	  || ((insn & 0xffe0) == 0x0780		/* ld.h 23bit */
746	      && !status2 && (insn2 & 0x000f) == 0x0007)
747	  || ((insn & 0xffe0) == 0x07a0		/* ld.hu 23bit */
748	      && !status2 && (insn2 & 0x000f) == 0x0007)
749	  || ((insn & 0xffe0) == 0x0780		/* ld.w 23bit */
750	      && !status2 && (insn2 & 0x000f) == 0x0009))
751	{
752	  length = 4;
753	  code_length = 6;
754	}
755      else if (((insn & 0xffe0) == 0x0780	/* st.b 23bit */
756	       && !status2 && (insn2 & 0x000f) == 0x000d)
757	      || ((insn & 0xffe0) == 0x07a0	/* st.h 23bit */
758		  && !status2 && (insn2 & 0x000f) == 0x000d)
759	      || ((insn & 0xffe0) == 0x0780	/* st.w 23bit */
760		  && !status2 && (insn2 & 0x000f) == 0x000f))
761	{
762	  length = 4;
763	  code_length = 6;
764	}
765    }
766
767  if (length == 0
768      && target_processor != PROCESSOR_V850)
769    {
770      if ((insn & 0xffe0) == 0x0620)		/* 32 bit MOV */
771	{
772	  length = 2;
773	  code_length = 6;
774	}
775      else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16<<16 */
776	       && !status2 && (insn2 & 0x001f) == 0x0013)
777	{
778	  length = 4;
779	  code_length = 6;
780	}
781      else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm16 */
782	       && !status2 && (insn2 & 0x001f) == 0x000b)
783	{
784	  length = 4;
785	  code_length = 6;
786	}
787      else if ((insn & 0xffc0) == 0x0780	/* prepare {list}, imm5, imm32 */
788	       && !status2 && (insn2 & 0x001f) == 0x001b)
789	{
790	  length = 4;
791	  code_length = 8;
792	}
793    }
794
795  if (length == 4
796      || (length == 0
797	  && (insn & 0x0600) == 0x0600))
798    {
799      /* This is a 4 byte insn.  */
800      status = info->read_memory_func (memaddr, buffer, 4, info);
801      if (!status)
802	{
803	  insn = bfd_getl32 (buffer);
804
805	  if (!length)
806	    length = code_length = 4;
807	}
808    }
809
810  if (code_length > length)
811    {
812      status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
813      if (status)
814	length = 0;
815    }
816
817  if (length == 0 && !status)
818    length = code_length = 2;
819
820  if (length == 2)
821    insn &= 0xffff;
822
823  /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
824  if (length == 0)
825    return -1;
826
827  match = disassemble (memaddr, info, length, insn);
828
829  if (!match)
830    {
831      int l = 0;
832
833      status = info->read_memory_func (memaddr, buffer, code_length, info);
834
835      while (l < code_length)
836	{
837	  if (code_length - l == 2)
838	    {
839	      insn = bfd_getl16 (buffer + l) & 0xffff;
840	      info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
841	      l += 2;
842	    }
843	  else
844	    {
845	      insn = bfd_getl32 (buffer + l);
846	      info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
847	      l += 4;
848	    }
849	}
850    }
851
852  return code_length;
853}
854