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