xref: /netbsd-src/external/gpl3/gdb/dist/cpu/ip2k.opc (revision a2e2270fc5bff6bcbd2c81db532c53a470bd1be5)
1*a2e2270fSchristos/* IP2K opcode support.  -*- C -*-
2*a2e2270fSchristos   Copyright 2002, 2005, 2011 Free Software Foundation, Inc.
3*a2e2270fSchristos
4*a2e2270fSchristos   Contributed by Red Hat Inc;
5*a2e2270fSchristos
6*a2e2270fSchristos   This file is part of the GNU Binutils.
7*a2e2270fSchristos
8*a2e2270fSchristos   This program is free software; you can redistribute it and/or modify
9*a2e2270fSchristos   it under the terms of the GNU General Public License as published by
10*a2e2270fSchristos   the Free Software Foundation; either version 3 of the License, or
11*a2e2270fSchristos   (at your option) any later version.
12*a2e2270fSchristos
13*a2e2270fSchristos   This program is distributed in the hope that it will be useful,
14*a2e2270fSchristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
15*a2e2270fSchristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*a2e2270fSchristos   GNU General Public License for more details.
17*a2e2270fSchristos
18*a2e2270fSchristos   You should have received a copy of the GNU General Public License
19*a2e2270fSchristos   along with this program; if not, write to the Free Software
20*a2e2270fSchristos   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*a2e2270fSchristos   MA 02110-1301, USA.  */
22*a2e2270fSchristos
23*a2e2270fSchristos/*
24*a2e2270fSchristos   Each section is delimited with start and end markers.
25*a2e2270fSchristos
26*a2e2270fSchristos   <arch>-opc.h additions use: "-- opc.h"
27*a2e2270fSchristos   <arch>-opc.c additions use: "-- opc.c"
28*a2e2270fSchristos   <arch>-asm.c additions use: "-- asm.c"
29*a2e2270fSchristos   <arch>-dis.c additions use: "-- dis.c"
30*a2e2270fSchristos   <arch>-ibd.h additions use: "-- ibd.h".  */
31*a2e2270fSchristos
32*a2e2270fSchristos/* -- opc.h */
33*a2e2270fSchristos
34*a2e2270fSchristos/* Check applicability of instructions against machines.  */
35*a2e2270fSchristos#define CGEN_VALIDATE_INSN_SUPPORTED
36*a2e2270fSchristos
37*a2e2270fSchristos/* Allows reason codes to be output when assembler errors occur.  */
38*a2e2270fSchristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS
39*a2e2270fSchristos
40*a2e2270fSchristos/* Override disassembly hashing - there are variable bits in the top
41*a2e2270fSchristos   byte of these instructions.  */
42*a2e2270fSchristos#define CGEN_DIS_HASH_SIZE 8
43*a2e2270fSchristos#define CGEN_DIS_HASH(buf, value) \
44*a2e2270fSchristos  (((* (unsigned char*) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
45*a2e2270fSchristos
46*a2e2270fSchristos#define CGEN_ASM_HASH_SIZE 127
47*a2e2270fSchristos#define CGEN_ASM_HASH(insn) ip2k_asm_hash (insn)
48*a2e2270fSchristos
49*a2e2270fSchristosextern unsigned int ip2k_asm_hash (const char *);
50*a2e2270fSchristosextern int ip2k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
51*a2e2270fSchristos
52*a2e2270fSchristos/* -- opc.c */
53*a2e2270fSchristos
54*a2e2270fSchristos#include "safe-ctype.h"
55*a2e2270fSchristos
56*a2e2270fSchristos/* A better hash function for instruction mnemonics.  */
57*a2e2270fSchristosunsigned int
58*a2e2270fSchristosip2k_asm_hash (const char* insn)
59*a2e2270fSchristos{
60*a2e2270fSchristos  unsigned int hash;
61*a2e2270fSchristos  const char* m = insn;
62*a2e2270fSchristos
63*a2e2270fSchristos  for (hash = 0; *m && ! ISSPACE (*m); m++)
64*a2e2270fSchristos    hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
65*a2e2270fSchristos
66*a2e2270fSchristos  /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
67*a2e2270fSchristos
68*a2e2270fSchristos  return hash % CGEN_ASM_HASH_SIZE;
69*a2e2270fSchristos}
70*a2e2270fSchristos
71*a2e2270fSchristos
72*a2e2270fSchristos/* Special check to ensure that instruction exists for given machine.  */
73*a2e2270fSchristos
74*a2e2270fSchristosint
75*a2e2270fSchristosip2k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
76*a2e2270fSchristos{
77*a2e2270fSchristos  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
78*a2e2270fSchristos
79*a2e2270fSchristos  /* No mach attribute?  Assume it's supported for all machs.  */
80*a2e2270fSchristos  if (machs == 0)
81*a2e2270fSchristos    return 1;
82*a2e2270fSchristos
83*a2e2270fSchristos  return (machs & cd->machs) != 0;
84*a2e2270fSchristos}
85*a2e2270fSchristos
86*a2e2270fSchristos
87*a2e2270fSchristos/* -- asm.c */
88*a2e2270fSchristos
89*a2e2270fSchristosstatic const char *
90*a2e2270fSchristosparse_fr (CGEN_CPU_DESC cd,
91*a2e2270fSchristos	  const char **strp,
92*a2e2270fSchristos	  int opindex,
93*a2e2270fSchristos	  unsigned long *valuep)
94*a2e2270fSchristos{
95*a2e2270fSchristos  const char *errmsg;
96*a2e2270fSchristos  const char *old_strp;
97*a2e2270fSchristos  char *afteroffset;
98*a2e2270fSchristos  enum cgen_parse_operand_result result_type;
99*a2e2270fSchristos  bfd_vma value;
100*a2e2270fSchristos  extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
101*a2e2270fSchristos  bfd_vma tempvalue;
102*a2e2270fSchristos
103*a2e2270fSchristos  old_strp = *strp;
104*a2e2270fSchristos  afteroffset = NULL;
105*a2e2270fSchristos
106*a2e2270fSchristos  /* Check here to see if you're about to try parsing a w as the first arg
107*a2e2270fSchristos     and return an error if you are.  */
108*a2e2270fSchristos  if ((strncmp (*strp, "w", 1) == 0) || (strncmp (*strp, "W", 1) == 0))
109*a2e2270fSchristos    {
110*a2e2270fSchristos      (*strp)++;
111*a2e2270fSchristos
112*a2e2270fSchristos      if ((strncmp (*strp, ",", 1) == 0) || ISSPACE (**strp))
113*a2e2270fSchristos	{
114*a2e2270fSchristos	  /* We've been passed a w.  Return with an error message so that
115*a2e2270fSchristos	     cgen will try the next parsing option.  */
116*a2e2270fSchristos	  errmsg = _("W keyword invalid in FR operand slot.");
117*a2e2270fSchristos	  return errmsg;
118*a2e2270fSchristos	}
119*a2e2270fSchristos      *strp = old_strp;
120*a2e2270fSchristos    }
121*a2e2270fSchristos
122*a2e2270fSchristos  /* Attempt parse as register keyword. */
123*a2e2270fSchristos  errmsg = cgen_parse_keyword (cd, strp, & ip2k_cgen_opval_register_names,
124*a2e2270fSchristos			       (long *) valuep);
125*a2e2270fSchristos  if (*strp != NULL
126*a2e2270fSchristos      && errmsg == NULL)
127*a2e2270fSchristos    return errmsg;
128*a2e2270fSchristos
129*a2e2270fSchristos  /* Attempt to parse for "(IP)".  */
130*a2e2270fSchristos  afteroffset = strstr (*strp, "(IP)");
131*a2e2270fSchristos
132*a2e2270fSchristos  if (afteroffset == NULL)
133*a2e2270fSchristos    /* Make sure it's not in lower case.  */
134*a2e2270fSchristos    afteroffset = strstr (*strp, "(ip)");
135*a2e2270fSchristos
136*a2e2270fSchristos  if (afteroffset != NULL)
137*a2e2270fSchristos    {
138*a2e2270fSchristos      if (afteroffset != *strp)
139*a2e2270fSchristos	{
140*a2e2270fSchristos	  /* Invalid offset present.  */
141*a2e2270fSchristos	  errmsg = _("offset(IP) is not a valid form");
142*a2e2270fSchristos	  return errmsg;
143*a2e2270fSchristos	}
144*a2e2270fSchristos      else
145*a2e2270fSchristos	{
146*a2e2270fSchristos	  *strp += 4;
147*a2e2270fSchristos	  *valuep = 0;
148*a2e2270fSchristos	  errmsg = NULL;
149*a2e2270fSchristos	  return errmsg;
150*a2e2270fSchristos	}
151*a2e2270fSchristos    }
152*a2e2270fSchristos
153*a2e2270fSchristos  /* Attempt to parse for DP. ex: mov w, offset(DP)
154*a2e2270fSchristos                                  mov offset(DP),w   */
155*a2e2270fSchristos
156*a2e2270fSchristos  /* Try parsing it as an address and see what comes back.  */
157*a2e2270fSchristos  afteroffset = strstr (*strp, "(DP)");
158*a2e2270fSchristos
159*a2e2270fSchristos  if (afteroffset == NULL)
160*a2e2270fSchristos    /* Maybe it's in lower case.  */
161*a2e2270fSchristos    afteroffset = strstr (*strp, "(dp)");
162*a2e2270fSchristos
163*a2e2270fSchristos  if (afteroffset != NULL)
164*a2e2270fSchristos    {
165*a2e2270fSchristos      if (afteroffset == *strp)
166*a2e2270fSchristos	{
167*a2e2270fSchristos	  /* No offset present. Use 0 by default.  */
168*a2e2270fSchristos	  tempvalue = 0;
169*a2e2270fSchristos	  errmsg = NULL;
170*a2e2270fSchristos	}
171*a2e2270fSchristos      else
172*a2e2270fSchristos	errmsg = cgen_parse_address (cd, strp, opindex,
173*a2e2270fSchristos				     BFD_RELOC_IP2K_FR_OFFSET,
174*a2e2270fSchristos				     & result_type, & tempvalue);
175*a2e2270fSchristos
176*a2e2270fSchristos      if (errmsg == NULL)
177*a2e2270fSchristos	{
178*a2e2270fSchristos	  if (tempvalue <= 127)
179*a2e2270fSchristos	    {
180*a2e2270fSchristos	      /* Value is ok.  Fix up the first 2 bits and return.  */
181*a2e2270fSchristos	      *valuep = 0x0100 | tempvalue;
182*a2e2270fSchristos	      *strp += 4; /* Skip over the (DP) in *strp.  */
183*a2e2270fSchristos	      return errmsg;
184*a2e2270fSchristos	    }
185*a2e2270fSchristos	  else
186*a2e2270fSchristos	    {
187*a2e2270fSchristos	      /* Found something there in front of (DP) but it's out
188*a2e2270fSchristos		 of range.  */
189*a2e2270fSchristos	      errmsg = _("(DP) offset out of range.");
190*a2e2270fSchristos	      return errmsg;
191*a2e2270fSchristos	    }
192*a2e2270fSchristos	}
193*a2e2270fSchristos    }
194*a2e2270fSchristos
195*a2e2270fSchristos
196*a2e2270fSchristos  /* Attempt to parse for SP. ex: mov w, offset(SP)
197*a2e2270fSchristos                                  mov offset(SP), w.  */
198*a2e2270fSchristos  afteroffset = strstr (*strp, "(SP)");
199*a2e2270fSchristos
200*a2e2270fSchristos  if (afteroffset == NULL)
201*a2e2270fSchristos    /* Maybe it's in lower case.  */
202*a2e2270fSchristos    afteroffset = strstr (*strp, "(sp)");
203*a2e2270fSchristos
204*a2e2270fSchristos  if (afteroffset != NULL)
205*a2e2270fSchristos    {
206*a2e2270fSchristos      if (afteroffset == *strp)
207*a2e2270fSchristos	{
208*a2e2270fSchristos	  /* No offset present. Use 0 by default.  */
209*a2e2270fSchristos	  tempvalue = 0;
210*a2e2270fSchristos	  errmsg = NULL;
211*a2e2270fSchristos	}
212*a2e2270fSchristos      else
213*a2e2270fSchristos	errmsg = cgen_parse_address (cd, strp, opindex,
214*a2e2270fSchristos				     BFD_RELOC_IP2K_FR_OFFSET,
215*a2e2270fSchristos				     & result_type, & tempvalue);
216*a2e2270fSchristos
217*a2e2270fSchristos      if (errmsg == NULL)
218*a2e2270fSchristos	{
219*a2e2270fSchristos	  if (tempvalue <= 127)
220*a2e2270fSchristos	    {
221*a2e2270fSchristos	      /* Value is ok.  Fix up the first 2 bits and return.  */
222*a2e2270fSchristos	      *valuep = 0x0180 | tempvalue;
223*a2e2270fSchristos	      *strp += 4; /* Skip over the (SP) in *strp.  */
224*a2e2270fSchristos	      return errmsg;
225*a2e2270fSchristos	    }
226*a2e2270fSchristos	  else
227*a2e2270fSchristos	    {
228*a2e2270fSchristos	      /* Found something there in front of (SP) but it's out
229*a2e2270fSchristos		 of range.  */
230*a2e2270fSchristos	      errmsg = _("(SP) offset out of range.");
231*a2e2270fSchristos	      return errmsg;
232*a2e2270fSchristos	    }
233*a2e2270fSchristos	}
234*a2e2270fSchristos    }
235*a2e2270fSchristos
236*a2e2270fSchristos  /* Attempt to parse as an address.  */
237*a2e2270fSchristos  *strp = old_strp;
238*a2e2270fSchristos  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR9,
239*a2e2270fSchristos			       & result_type, & value);
240*a2e2270fSchristos  if (errmsg == NULL)
241*a2e2270fSchristos    {
242*a2e2270fSchristos      *valuep = value;
243*a2e2270fSchristos
244*a2e2270fSchristos      /* If a parenthesis is found, warn about invalid form.  */
245*a2e2270fSchristos      if (**strp == '(')
246*a2e2270fSchristos	errmsg = _("illegal use of parentheses");
247*a2e2270fSchristos
248*a2e2270fSchristos      /* If a numeric value is specified, ensure that it is between
249*a2e2270fSchristos	 1 and 255.  */
250*a2e2270fSchristos      else if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
251*a2e2270fSchristos	{
252*a2e2270fSchristos	  if (value < 0x1 || value > 0xff)
253*a2e2270fSchristos	    errmsg = _("operand out of range (not between 1 and 255)");
254*a2e2270fSchristos	}
255*a2e2270fSchristos    }
256*a2e2270fSchristos  return errmsg;
257*a2e2270fSchristos}
258*a2e2270fSchristos
259*a2e2270fSchristosstatic const char *
260*a2e2270fSchristosparse_addr16 (CGEN_CPU_DESC cd,
261*a2e2270fSchristos	      const char **strp,
262*a2e2270fSchristos	      int opindex,
263*a2e2270fSchristos	      unsigned long *valuep)
264*a2e2270fSchristos{
265*a2e2270fSchristos  const char *errmsg;
266*a2e2270fSchristos  enum cgen_parse_operand_result result_type;
267*a2e2270fSchristos  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
268*a2e2270fSchristos  bfd_vma value;
269*a2e2270fSchristos
270*a2e2270fSchristos  if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16H)
271*a2e2270fSchristos    code = BFD_RELOC_IP2K_HI8DATA;
272*a2e2270fSchristos  else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16L)
273*a2e2270fSchristos    code = BFD_RELOC_IP2K_LO8DATA;
274*a2e2270fSchristos  else
275*a2e2270fSchristos    {
276*a2e2270fSchristos      /* Something is very wrong. opindex has to be one of the above.  */
277*a2e2270fSchristos      errmsg = _("parse_addr16: invalid opindex.");
278*a2e2270fSchristos      return errmsg;
279*a2e2270fSchristos    }
280*a2e2270fSchristos
281*a2e2270fSchristos  errmsg = cgen_parse_address (cd, strp, opindex, code,
282*a2e2270fSchristos			       & result_type, & value);
283*a2e2270fSchristos  if (errmsg == NULL)
284*a2e2270fSchristos    {
285*a2e2270fSchristos      /* We either have a relocation or a number now.  */
286*a2e2270fSchristos      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
287*a2e2270fSchristos	{
288*a2e2270fSchristos	  /* We got a number back.  */
289*a2e2270fSchristos	  if (code == BFD_RELOC_IP2K_HI8DATA)
290*a2e2270fSchristos            value >>= 8;
291*a2e2270fSchristos	  else
292*a2e2270fSchristos	    /* code = BFD_RELOC_IP2K_LOW8DATA.  */
293*a2e2270fSchristos	    value &= 0x00FF;
294*a2e2270fSchristos	}
295*a2e2270fSchristos      *valuep = value;
296*a2e2270fSchristos    }
297*a2e2270fSchristos
298*a2e2270fSchristos  return errmsg;
299*a2e2270fSchristos}
300*a2e2270fSchristos
301*a2e2270fSchristosstatic const char *
302*a2e2270fSchristosparse_addr16_cjp (CGEN_CPU_DESC cd,
303*a2e2270fSchristos		  const char **strp,
304*a2e2270fSchristos		  int opindex,
305*a2e2270fSchristos		  unsigned long *valuep)
306*a2e2270fSchristos{
307*a2e2270fSchristos  const char *errmsg;
308*a2e2270fSchristos  enum cgen_parse_operand_result result_type;
309*a2e2270fSchristos  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
310*a2e2270fSchristos  bfd_vma value;
311*a2e2270fSchristos
312*a2e2270fSchristos  if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP)
313*a2e2270fSchristos    code = BFD_RELOC_IP2K_ADDR16CJP;
314*a2e2270fSchristos  else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P)
315*a2e2270fSchristos    code = BFD_RELOC_IP2K_PAGE3;
316*a2e2270fSchristos
317*a2e2270fSchristos  errmsg = cgen_parse_address (cd, strp, opindex, code,
318*a2e2270fSchristos			       & result_type, & value);
319*a2e2270fSchristos  if (errmsg == NULL)
320*a2e2270fSchristos    {
321*a2e2270fSchristos      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
322*a2e2270fSchristos	{
323*a2e2270fSchristos	  if ((value & 0x1) == 0)  /* If the address is even .... */
324*a2e2270fSchristos	    {
325*a2e2270fSchristos	      if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP)
326*a2e2270fSchristos                *valuep = (value >> 1) & 0x1FFF;  /* Should mask be 1FFF?  */
327*a2e2270fSchristos	      else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P)
328*a2e2270fSchristos                *valuep = (value >> 14) & 0x7;
329*a2e2270fSchristos	    }
330*a2e2270fSchristos          else
331*a2e2270fSchristos 	    errmsg = _("Byte address required. - must be even.");
332*a2e2270fSchristos	}
333*a2e2270fSchristos      else if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
334*a2e2270fSchristos	{
335*a2e2270fSchristos	  /* This will happen for things like (s2-s1) where s2 and s1
336*a2e2270fSchristos	     are labels.  */
337*a2e2270fSchristos	  *valuep = value;
338*a2e2270fSchristos	}
339*a2e2270fSchristos      else
340*a2e2270fSchristos        errmsg = _("cgen_parse_address returned a symbol. Literal required.");
341*a2e2270fSchristos    }
342*a2e2270fSchristos  return errmsg;
343*a2e2270fSchristos}
344*a2e2270fSchristos
345*a2e2270fSchristosstatic const char *
346*a2e2270fSchristosparse_lit8 (CGEN_CPU_DESC cd,
347*a2e2270fSchristos	    const char **strp,
348*a2e2270fSchristos	    int opindex,
349*a2e2270fSchristos	    long *valuep)
350*a2e2270fSchristos{
351*a2e2270fSchristos  const char *errmsg;
352*a2e2270fSchristos  enum cgen_parse_operand_result result_type;
353*a2e2270fSchristos  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
354*a2e2270fSchristos  bfd_vma value;
355*a2e2270fSchristos
356*a2e2270fSchristos  /* Parse %OP relocating operators.  */
357*a2e2270fSchristos  if (strncmp (*strp, "%bank", 5) == 0)
358*a2e2270fSchristos    {
359*a2e2270fSchristos      *strp += 5;
360*a2e2270fSchristos      code = BFD_RELOC_IP2K_BANK;
361*a2e2270fSchristos    }
362*a2e2270fSchristos  else if (strncmp (*strp, "%lo8data", 8) == 0)
363*a2e2270fSchristos    {
364*a2e2270fSchristos      *strp += 8;
365*a2e2270fSchristos      code = BFD_RELOC_IP2K_LO8DATA;
366*a2e2270fSchristos    }
367*a2e2270fSchristos  else if (strncmp (*strp, "%hi8data", 8) == 0)
368*a2e2270fSchristos    {
369*a2e2270fSchristos      *strp += 8;
370*a2e2270fSchristos      code = BFD_RELOC_IP2K_HI8DATA;
371*a2e2270fSchristos    }
372*a2e2270fSchristos  else if (strncmp (*strp, "%ex8data", 8) == 0)
373*a2e2270fSchristos    {
374*a2e2270fSchristos      *strp += 8;
375*a2e2270fSchristos      code = BFD_RELOC_IP2K_EX8DATA;
376*a2e2270fSchristos    }
377*a2e2270fSchristos  else if (strncmp (*strp, "%lo8insn", 8) == 0)
378*a2e2270fSchristos    {
379*a2e2270fSchristos      *strp += 8;
380*a2e2270fSchristos      code = BFD_RELOC_IP2K_LO8INSN;
381*a2e2270fSchristos    }
382*a2e2270fSchristos  else if (strncmp (*strp, "%hi8insn", 8) == 0)
383*a2e2270fSchristos    {
384*a2e2270fSchristos      *strp += 8;
385*a2e2270fSchristos      code = BFD_RELOC_IP2K_HI8INSN;
386*a2e2270fSchristos    }
387*a2e2270fSchristos
388*a2e2270fSchristos  /* Parse %op operand.  */
389*a2e2270fSchristos  if (code != BFD_RELOC_NONE)
390*a2e2270fSchristos    {
391*a2e2270fSchristos      errmsg = cgen_parse_address (cd, strp, opindex, code,
392*a2e2270fSchristos				   & result_type, & value);
393*a2e2270fSchristos      if ((errmsg == NULL) &&
394*a2e2270fSchristos	  (result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED))
395*a2e2270fSchristos	errmsg = _("percent-operator operand is not a symbol");
396*a2e2270fSchristos
397*a2e2270fSchristos      *valuep = value;
398*a2e2270fSchristos    }
399*a2e2270fSchristos  /* Parse as a number.  */
400*a2e2270fSchristos  else
401*a2e2270fSchristos    {
402*a2e2270fSchristos      errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
403*a2e2270fSchristos
404*a2e2270fSchristos      /* Truncate to eight bits to accept both signed and unsigned input.  */
405*a2e2270fSchristos      if (errmsg == NULL)
406*a2e2270fSchristos	*valuep &= 0xFF;
407*a2e2270fSchristos    }
408*a2e2270fSchristos
409*a2e2270fSchristos  return errmsg;
410*a2e2270fSchristos}
411*a2e2270fSchristos
412*a2e2270fSchristosstatic const char *
413*a2e2270fSchristosparse_bit3 (CGEN_CPU_DESC cd,
414*a2e2270fSchristos	    const char **strp,
415*a2e2270fSchristos	    int opindex,
416*a2e2270fSchristos	    unsigned long *valuep)
417*a2e2270fSchristos{
418*a2e2270fSchristos  const char *errmsg;
419*a2e2270fSchristos  char mode = 0;
420*a2e2270fSchristos  long count = 0;
421*a2e2270fSchristos  unsigned long value;
422*a2e2270fSchristos
423*a2e2270fSchristos  if (strncmp (*strp, "%bit", 4) == 0)
424*a2e2270fSchristos    {
425*a2e2270fSchristos      *strp += 4;
426*a2e2270fSchristos      mode = 1;
427*a2e2270fSchristos    }
428*a2e2270fSchristos  else if (strncmp (*strp, "%msbbit", 7) == 0)
429*a2e2270fSchristos    {
430*a2e2270fSchristos      *strp += 7;
431*a2e2270fSchristos      mode = 1;
432*a2e2270fSchristos    }
433*a2e2270fSchristos  else if (strncmp (*strp, "%lsbbit", 7) == 0)
434*a2e2270fSchristos    {
435*a2e2270fSchristos      *strp += 7;
436*a2e2270fSchristos      mode = 2;
437*a2e2270fSchristos    }
438*a2e2270fSchristos
439*a2e2270fSchristos  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
440*a2e2270fSchristos  if (errmsg)
441*a2e2270fSchristos    return errmsg;
442*a2e2270fSchristos
443*a2e2270fSchristos  if (mode)
444*a2e2270fSchristos    {
445*a2e2270fSchristos      value = * valuep;
446*a2e2270fSchristos      if (value == 0)
447*a2e2270fSchristos	{
448*a2e2270fSchristos	  errmsg = _("Attempt to find bit index of 0");
449*a2e2270fSchristos	  return errmsg;
450*a2e2270fSchristos	}
451*a2e2270fSchristos
452*a2e2270fSchristos      if (mode == 1)
453*a2e2270fSchristos	{
454*a2e2270fSchristos	  count = 31;
455*a2e2270fSchristos	  while ((value & 0x80000000) == 0)
456*a2e2270fSchristos	    {
457*a2e2270fSchristos	      count--;
458*a2e2270fSchristos	      value <<= 1;
459*a2e2270fSchristos	    }
460*a2e2270fSchristos	}
461*a2e2270fSchristos      else if (mode == 2)
462*a2e2270fSchristos	{
463*a2e2270fSchristos	  count = 0;
464*a2e2270fSchristos	  while ((value & 0x00000001) == 0)
465*a2e2270fSchristos	    {
466*a2e2270fSchristos	      count++;
467*a2e2270fSchristos	      value >>= 1;
468*a2e2270fSchristos	    }
469*a2e2270fSchristos	}
470*a2e2270fSchristos
471*a2e2270fSchristos      *valuep = count;
472*a2e2270fSchristos    }
473*a2e2270fSchristos
474*a2e2270fSchristos  return errmsg;
475*a2e2270fSchristos}
476*a2e2270fSchristos
477*a2e2270fSchristos/* -- dis.c */
478*a2e2270fSchristos
479*a2e2270fSchristosstatic void
480*a2e2270fSchristosprint_fr (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
481*a2e2270fSchristos	  void * dis_info,
482*a2e2270fSchristos	  long value,
483*a2e2270fSchristos	  unsigned int attrs ATTRIBUTE_UNUSED,
484*a2e2270fSchristos	  bfd_vma pc ATTRIBUTE_UNUSED,
485*a2e2270fSchristos	  int length ATTRIBUTE_UNUSED)
486*a2e2270fSchristos{
487*a2e2270fSchristos  disassemble_info *info = (disassemble_info *) dis_info;
488*a2e2270fSchristos  const CGEN_KEYWORD_ENTRY *ke;
489*a2e2270fSchristos  extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
490*a2e2270fSchristos  long offsettest;
491*a2e2270fSchristos  long offsetvalue;
492*a2e2270fSchristos
493*a2e2270fSchristos  if (value == 0) /* This is (IP).  */
494*a2e2270fSchristos    {
495*a2e2270fSchristos      (*info->fprintf_func) (info->stream, "%s", "(IP)");
496*a2e2270fSchristos      return;
497*a2e2270fSchristos    }
498*a2e2270fSchristos
499*a2e2270fSchristos  offsettest = value >> 7;
500*a2e2270fSchristos  offsetvalue = value & 0x7F;
501*a2e2270fSchristos
502*a2e2270fSchristos  /* Check to see if first two bits are 10 -> (DP).  */
503*a2e2270fSchristos  if (offsettest == 2)
504*a2e2270fSchristos    {
505*a2e2270fSchristos      if (offsetvalue == 0)
506*a2e2270fSchristos	(*info->fprintf_func) (info->stream, "%s","(DP)");
507*a2e2270fSchristos      else
508*a2e2270fSchristos	(*info->fprintf_func) (info->stream, "$%lx%s", offsetvalue, "(DP)");
509*a2e2270fSchristos      return;
510*a2e2270fSchristos    }
511*a2e2270fSchristos
512*a2e2270fSchristos  /* Check to see if first two bits are 11 -> (SP).  */
513*a2e2270fSchristos  if (offsettest == 3)
514*a2e2270fSchristos    {
515*a2e2270fSchristos      if (offsetvalue == 0)
516*a2e2270fSchristos	(*info->fprintf_func) (info->stream, "%s", "(SP)");
517*a2e2270fSchristos      else
518*a2e2270fSchristos	(*info->fprintf_func) (info->stream, "$%lx%s", offsetvalue,"(SP)");
519*a2e2270fSchristos      return;
520*a2e2270fSchristos    }
521*a2e2270fSchristos
522*a2e2270fSchristos  /* Attempt to print as a register keyword.  */
523*a2e2270fSchristos  ke = cgen_keyword_lookup_value (& ip2k_cgen_opval_register_names, value);
524*a2e2270fSchristos
525*a2e2270fSchristos  if (ke != NULL)
526*a2e2270fSchristos    (*info->fprintf_func) (info->stream, "%s", ke->name);
527*a2e2270fSchristos  else
528*a2e2270fSchristos    /* Print as an address literal.  */
529*a2e2270fSchristos    (*info->fprintf_func) (info->stream, "$%02lx", value);
530*a2e2270fSchristos}
531*a2e2270fSchristos
532*a2e2270fSchristosstatic void
533*a2e2270fSchristosprint_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
534*a2e2270fSchristos		 void * dis_info,
535*a2e2270fSchristos		 long value,
536*a2e2270fSchristos		 unsigned int attrs ATTRIBUTE_UNUSED,
537*a2e2270fSchristos		 bfd_vma pc ATTRIBUTE_UNUSED,
538*a2e2270fSchristos		 int length ATTRIBUTE_UNUSED)
539*a2e2270fSchristos{
540*a2e2270fSchristos  disassemble_info *info = (disassemble_info *) dis_info;
541*a2e2270fSchristos
542*a2e2270fSchristos  (*info->fprintf_func) (info->stream, "$%lx", value);
543*a2e2270fSchristos}
544*a2e2270fSchristos
545*a2e2270fSchristosstatic void
546*a2e2270fSchristosprint_dollarhex8 (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
547*a2e2270fSchristos		  void * dis_info,
548*a2e2270fSchristos		  long value,
549*a2e2270fSchristos		  unsigned int attrs ATTRIBUTE_UNUSED,
550*a2e2270fSchristos		  bfd_vma pc ATTRIBUTE_UNUSED,
551*a2e2270fSchristos		  int length ATTRIBUTE_UNUSED)
552*a2e2270fSchristos{
553*a2e2270fSchristos  disassemble_info *info = (disassemble_info *) dis_info;
554*a2e2270fSchristos
555*a2e2270fSchristos  (*info->fprintf_func) (info->stream, "$%02lx", value);
556*a2e2270fSchristos}
557*a2e2270fSchristos
558*a2e2270fSchristosstatic void
559*a2e2270fSchristosprint_dollarhex_addr16h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
560*a2e2270fSchristos			 void * dis_info,
561*a2e2270fSchristos			 long value,
562*a2e2270fSchristos			 unsigned int attrs ATTRIBUTE_UNUSED,
563*a2e2270fSchristos			 bfd_vma pc ATTRIBUTE_UNUSED,
564*a2e2270fSchristos			 int length ATTRIBUTE_UNUSED)
565*a2e2270fSchristos{
566*a2e2270fSchristos  disassemble_info *info = (disassemble_info *) dis_info;
567*a2e2270fSchristos
568*a2e2270fSchristos  /* This is a loadh instruction. Shift the value to the left
569*a2e2270fSchristos     by 8 bits so that disassembled code will reassemble properly.  */
570*a2e2270fSchristos  value = ((value << 8) & 0xFF00);
571*a2e2270fSchristos
572*a2e2270fSchristos  (*info->fprintf_func) (info->stream, "$%04lx", value);
573*a2e2270fSchristos}
574*a2e2270fSchristos
575*a2e2270fSchristosstatic void
576*a2e2270fSchristosprint_dollarhex_addr16l (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
577*a2e2270fSchristos			 void * dis_info,
578*a2e2270fSchristos			 long value,
579*a2e2270fSchristos			 unsigned int attrs ATTRIBUTE_UNUSED,
580*a2e2270fSchristos			 bfd_vma pc ATTRIBUTE_UNUSED,
581*a2e2270fSchristos			 int length ATTRIBUTE_UNUSED)
582*a2e2270fSchristos{
583*a2e2270fSchristos  disassemble_info *info = (disassemble_info *) dis_info;
584*a2e2270fSchristos
585*a2e2270fSchristos  (*info->fprintf_func) (info->stream, "$%04lx", value);
586*a2e2270fSchristos}
587*a2e2270fSchristos
588*a2e2270fSchristosstatic void
589*a2e2270fSchristosprint_dollarhex_p (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
590*a2e2270fSchristos		   void * dis_info,
591*a2e2270fSchristos		   long value,
592*a2e2270fSchristos		   unsigned int attrs ATTRIBUTE_UNUSED,
593*a2e2270fSchristos		   bfd_vma pc ATTRIBUTE_UNUSED,
594*a2e2270fSchristos		   int length ATTRIBUTE_UNUSED)
595*a2e2270fSchristos{
596*a2e2270fSchristos  disassemble_info *info = (disassemble_info *) dis_info;
597*a2e2270fSchristos
598*a2e2270fSchristos  value = ((value << 14) & 0x1C000);
599*a2e2270fSchristos  ;value = (value  & 0x1FFFF);
600*a2e2270fSchristos  (*info->fprintf_func) (info->stream, "$%05lx", value);
601*a2e2270fSchristos}
602*a2e2270fSchristos
603*a2e2270fSchristosstatic void
604*a2e2270fSchristosprint_dollarhex_cj (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
605*a2e2270fSchristos		    void * dis_info,
606*a2e2270fSchristos		    long value,
607*a2e2270fSchristos		    unsigned int attrs ATTRIBUTE_UNUSED,
608*a2e2270fSchristos		    bfd_vma pc ATTRIBUTE_UNUSED,
609*a2e2270fSchristos		    int length ATTRIBUTE_UNUSED)
610*a2e2270fSchristos{
611*a2e2270fSchristos  disassemble_info *info = (disassemble_info *) dis_info;
612*a2e2270fSchristos
613*a2e2270fSchristos  value = ((value << 1) & 0x1FFFF);
614*a2e2270fSchristos  (*info->fprintf_func) (info->stream, "$%05lx", value);
615*a2e2270fSchristos}
616*a2e2270fSchristos
617*a2e2270fSchristosstatic void
618*a2e2270fSchristosprint_decimal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
619*a2e2270fSchristos	       void * dis_info,
620*a2e2270fSchristos	       long value,
621*a2e2270fSchristos	       unsigned int attrs ATTRIBUTE_UNUSED,
622*a2e2270fSchristos	       bfd_vma pc ATTRIBUTE_UNUSED,
623*a2e2270fSchristos	       int length ATTRIBUTE_UNUSED)
624*a2e2270fSchristos{
625*a2e2270fSchristos  disassemble_info *info = (disassemble_info *) dis_info;
626*a2e2270fSchristos
627*a2e2270fSchristos  (*info->fprintf_func) (info->stream, "%ld", value);
628*a2e2270fSchristos}
629*a2e2270fSchristos
630*a2e2270fSchristos
631*a2e2270fSchristos
632*a2e2270fSchristos/* -- */
633*a2e2270fSchristos
634