1440a403fSchristos/* OpenRISC 1000 opcode support.  -*- C -*-
2440a403fSchristos   Copyright 2000-2014 Free Software Foundation, Inc.
3440a403fSchristos
4440a403fSchristos   Originally ontributed for OR32 by Red Hat Inc;
5440a403fSchristos
6440a403fSchristos   This file is part of the GNU Binutils.
7440a403fSchristos
8440a403fSchristos   This program is free software; you can redistribute it and/or modify
9440a403fSchristos   it under the terms of the GNU General Public License as published by
10440a403fSchristos   the Free Software Foundation; either version 3 of the License, or
11440a403fSchristos   (at your option) any later version.
12440a403fSchristos
13440a403fSchristos   This program is distributed in the hope that it will be useful,
14440a403fSchristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
15440a403fSchristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16440a403fSchristos   GNU General Public License for more details.
17440a403fSchristos
18440a403fSchristos   You should have received a copy of the GNU General Public License
19440a403fSchristos   along with this program; if not, see <http://www.gnu.org/licenses/>. */
20440a403fSchristos
21440a403fSchristos/* This file is an addendum to or1k.cpu.  Heavy use of C code isn't
22440a403fSchristos   appropriate in .cpu files, so it resides here.  This especially applies
23440a403fSchristos   to assembly/disassembly where parsing/printing can be quite involved.
24440a403fSchristos   Such things aren't really part of the specification of the cpu, per se,
25440a403fSchristos   so .cpu files provide the general framework and .opc files handle the
26440a403fSchristos   nitty-gritty details as necessary.
27440a403fSchristos
28440a403fSchristos   Each section is delimited with start and end markers.
29440a403fSchristos
30440a403fSchristos   <arch>-opc.h additions use: "-- opc.h"
31440a403fSchristos   <arch>-opc.c additions use: "-- opc.c"
32440a403fSchristos   <arch>-asm.c additions use: "-- asm.c"
33440a403fSchristos   <arch>-dis.c additions use: "-- dis.c"
34440a403fSchristos   <arch>-ibd.h additions use: "-- ibd.h"  */
35440a403fSchristos
36440a403fSchristos/* -- opc.h */
37440a403fSchristos
38440a403fSchristos#undef  CGEN_DIS_HASH_SIZE
39440a403fSchristos#define CGEN_DIS_HASH_SIZE 256
40440a403fSchristos#undef  CGEN_DIS_HASH
41440a403fSchristos#define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
42440a403fSchristos
43*b88e3e88Schristos/* Check applicability of instructions against machines.  */
44*b88e3e88Schristos#define CGEN_VALIDATE_INSN_SUPPORTED
45*b88e3e88Schristos
46*b88e3e88Schristosextern int or1k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
47*b88e3e88Schristos
48440a403fSchristos/* -- */
49440a403fSchristos
50440a403fSchristos/* -- opc.c */
51*b88e3e88Schristos
52*b88e3e88Schristos/* Special check to ensure that instruction exists for given machine.  */
53*b88e3e88Schristos
54*b88e3e88Schristosint
55*b88e3e88Schristosor1k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
56*b88e3e88Schristos{
57*b88e3e88Schristos  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
58*b88e3e88Schristos
59*b88e3e88Schristos  /* No mach attribute?  Assume it's supported for all machs.  */
60*b88e3e88Schristos  if (machs == 0)
61*b88e3e88Schristos    return 1;
62*b88e3e88Schristos
63*b88e3e88Schristos  return ((machs & cd->machs) != 0);
64*b88e3e88Schristos}
65*b88e3e88Schristos
66440a403fSchristos/* -- */
67440a403fSchristos
68440a403fSchristos/* -- asm.c */
69440a403fSchristos
70440a403fSchristosstatic const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
71*b88e3e88Schristosstatic const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
72*b88e3e88Schristosstatic const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
73440a403fSchristos
74440a403fSchristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS
75440a403fSchristos
76440a403fSchristosstatic const char *
77440a403fSchristosparse_disp26 (CGEN_CPU_DESC cd,
78440a403fSchristos	      const char ** strp,
79440a403fSchristos	      int opindex,
80*b88e3e88Schristos	      int opinfo ATTRIBUTE_UNUSED,
81440a403fSchristos	      enum cgen_parse_operand_result * resultp,
82440a403fSchristos	      bfd_vma * valuep)
83440a403fSchristos{
84*b88e3e88Schristos  const char *str = *strp;
85440a403fSchristos  const char *errmsg = NULL;
86*b88e3e88Schristos  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
87440a403fSchristos
88*b88e3e88Schristos  if (strncasecmp (str, "plta(", 5) == 0)
89440a403fSchristos    {
90*b88e3e88Schristos      *strp = str + 5;
91*b88e3e88Schristos      reloc = BFD_RELOC_OR1K_PLTA26;
92440a403fSchristos    }
93*b88e3e88Schristos  else if (strncasecmp (str, "plt(", 4) == 0)
94*b88e3e88Schristos    {
95*b88e3e88Schristos      *strp = str + 4;
96*b88e3e88Schristos      reloc = BFD_RELOC_OR1K_PLT26;
97*b88e3e88Schristos    }
98*b88e3e88Schristos
99*b88e3e88Schristos  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
100*b88e3e88Schristos
101*b88e3e88Schristos  if (reloc != BFD_RELOC_OR1K_REL_26)
102*b88e3e88Schristos    {
103*b88e3e88Schristos      if (**strp != ')')
104*b88e3e88Schristos	errmsg = MISSING_CLOSING_PARENTHESIS;
105*b88e3e88Schristos      else
106*b88e3e88Schristos	++*strp;
107*b88e3e88Schristos    }
108*b88e3e88Schristos
109*b88e3e88Schristos  return errmsg;
110440a403fSchristos}
111440a403fSchristos
112440a403fSchristosstatic const char *
113*b88e3e88Schristosparse_disp21 (CGEN_CPU_DESC cd,
114*b88e3e88Schristos	      const char ** strp,
115*b88e3e88Schristos	      int opindex,
116*b88e3e88Schristos	      int opinfo ATTRIBUTE_UNUSED,
117*b88e3e88Schristos	      enum cgen_parse_operand_result * resultp,
118*b88e3e88Schristos	      bfd_vma * valuep)
119*b88e3e88Schristos{
120*b88e3e88Schristos  const char *str = *strp;
121*b88e3e88Schristos  const char *errmsg = NULL;
122*b88e3e88Schristos  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
123*b88e3e88Schristos
124*b88e3e88Schristos  if (strncasecmp (str, "got(", 4) == 0)
125*b88e3e88Schristos    {
126*b88e3e88Schristos      *strp = str + 4;
127*b88e3e88Schristos      reloc = BFD_RELOC_OR1K_GOT_PG21;
128*b88e3e88Schristos    }
129*b88e3e88Schristos  else if (strncasecmp (str, "tlsgd(", 6) == 0)
130*b88e3e88Schristos    {
131*b88e3e88Schristos      *strp = str + 6;
132*b88e3e88Schristos      reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
133*b88e3e88Schristos    }
134*b88e3e88Schristos  else if (strncasecmp (str, "tlsldm(", 7) == 0)
135*b88e3e88Schristos    {
136*b88e3e88Schristos      *strp = str + 7;
137*b88e3e88Schristos      reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
138*b88e3e88Schristos    }
139*b88e3e88Schristos  else if (strncasecmp (str, "gottp(", 6) == 0)
140*b88e3e88Schristos    {
141*b88e3e88Schristos      *strp = str + 6;
142*b88e3e88Schristos      reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
143*b88e3e88Schristos    }
144*b88e3e88Schristos
145*b88e3e88Schristos  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
146*b88e3e88Schristos
147*b88e3e88Schristos  if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
148*b88e3e88Schristos    {
149*b88e3e88Schristos      if (**strp != ')')
150*b88e3e88Schristos	errmsg = MISSING_CLOSING_PARENTHESIS;
151*b88e3e88Schristos      else
152*b88e3e88Schristos	++*strp;
153*b88e3e88Schristos    }
154*b88e3e88Schristos
155*b88e3e88Schristos  return errmsg;
156*b88e3e88Schristos}
157*b88e3e88Schristos
158*b88e3e88Schristosenum or1k_rclass
159*b88e3e88Schristos{
160*b88e3e88Schristos  RCLASS_DIRECT   = 0,
161*b88e3e88Schristos  RCLASS_GOT      = 1,
162*b88e3e88Schristos  RCLASS_GOTPC    = 2,
163*b88e3e88Schristos  RCLASS_GOTOFF   = 3,
164*b88e3e88Schristos  RCLASS_TLSGD    = 4,
165*b88e3e88Schristos  RCLASS_TLSLDM   = 5,
166*b88e3e88Schristos  RCLASS_DTPOFF   = 6,
167*b88e3e88Schristos  RCLASS_GOTTPOFF = 7,
168*b88e3e88Schristos  RCLASS_TPOFF    = 8,
169*b88e3e88Schristos};
170*b88e3e88Schristos
171*b88e3e88Schristosenum or1k_rtype
172*b88e3e88Schristos{
173*b88e3e88Schristos  RTYPE_LO = 0,
174*b88e3e88Schristos  RTYPE_SLO = 1,
175*b88e3e88Schristos  RTYPE_PO = 2,
176*b88e3e88Schristos  RTYPE_SPO = 3,
177*b88e3e88Schristos  RTYPE_HI = 4,
178*b88e3e88Schristos  RTYPE_AHI = 5,
179*b88e3e88Schristos};
180*b88e3e88Schristos
181*b88e3e88Schristos#define RCLASS_SHIFT 3
182*b88e3e88Schristos#define RTYPE_MASK   7
183*b88e3e88Schristos
184*b88e3e88Schristosstatic const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
185*b88e3e88Schristos  { BFD_RELOC_LO16,
186*b88e3e88Schristos    BFD_RELOC_OR1K_SLO16,
187*b88e3e88Schristos    BFD_RELOC_OR1K_LO13,
188*b88e3e88Schristos    BFD_RELOC_OR1K_SLO13,
189*b88e3e88Schristos    BFD_RELOC_HI16,
190*b88e3e88Schristos    BFD_RELOC_HI16_S, },
191*b88e3e88Schristos  { BFD_RELOC_OR1K_GOT16,
192*b88e3e88Schristos    BFD_RELOC_UNUSED,
193*b88e3e88Schristos    BFD_RELOC_OR1K_GOT_LO13,
194*b88e3e88Schristos    BFD_RELOC_UNUSED,
195*b88e3e88Schristos    BFD_RELOC_UNUSED,
196*b88e3e88Schristos    BFD_RELOC_UNUSED },
197*b88e3e88Schristos  { BFD_RELOC_OR1K_GOTPC_LO16,
198*b88e3e88Schristos    BFD_RELOC_UNUSED,
199*b88e3e88Schristos    BFD_RELOC_UNUSED,
200*b88e3e88Schristos    BFD_RELOC_UNUSED,
201*b88e3e88Schristos    BFD_RELOC_OR1K_GOTPC_HI16,
202*b88e3e88Schristos    BFD_RELOC_UNUSED },
203*b88e3e88Schristos  { BFD_RELOC_LO16_GOTOFF,
204*b88e3e88Schristos    BFD_RELOC_OR1K_GOTOFF_SLO16,
205*b88e3e88Schristos    BFD_RELOC_UNUSED,
206*b88e3e88Schristos    BFD_RELOC_UNUSED,
207*b88e3e88Schristos    BFD_RELOC_HI16_GOTOFF,
208*b88e3e88Schristos    BFD_RELOC_HI16_S_GOTOFF },
209*b88e3e88Schristos  { BFD_RELOC_OR1K_TLS_GD_LO16,
210*b88e3e88Schristos    BFD_RELOC_UNUSED,
211*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_GD_LO13,
212*b88e3e88Schristos    BFD_RELOC_UNUSED,
213*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_GD_HI16,
214*b88e3e88Schristos    BFD_RELOC_UNUSED },
215*b88e3e88Schristos  { BFD_RELOC_OR1K_TLS_LDM_LO16,
216*b88e3e88Schristos    BFD_RELOC_UNUSED,
217*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_LDM_LO13,
218*b88e3e88Schristos    BFD_RELOC_UNUSED,
219*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_LDM_HI16,
220*b88e3e88Schristos    BFD_RELOC_UNUSED },
221*b88e3e88Schristos  { BFD_RELOC_OR1K_TLS_LDO_LO16,
222*b88e3e88Schristos    BFD_RELOC_UNUSED,
223*b88e3e88Schristos    BFD_RELOC_UNUSED,
224*b88e3e88Schristos    BFD_RELOC_UNUSED,
225*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_LDO_HI16,
226*b88e3e88Schristos    BFD_RELOC_UNUSED },
227*b88e3e88Schristos  { BFD_RELOC_OR1K_TLS_IE_LO16,
228*b88e3e88Schristos    BFD_RELOC_UNUSED,
229*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_IE_LO13,
230*b88e3e88Schristos    BFD_RELOC_UNUSED,
231*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_IE_HI16,
232*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_IE_AHI16 },
233*b88e3e88Schristos  { BFD_RELOC_OR1K_TLS_LE_LO16,
234*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_LE_SLO16,
235*b88e3e88Schristos    BFD_RELOC_UNUSED,
236*b88e3e88Schristos    BFD_RELOC_UNUSED,
237*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_LE_HI16,
238*b88e3e88Schristos    BFD_RELOC_OR1K_TLS_LE_AHI16 },
239*b88e3e88Schristos};
240*b88e3e88Schristos
241*b88e3e88Schristosstatic int
242*b88e3e88Schristosparse_reloc (const char **strp)
243*b88e3e88Schristos{
244*b88e3e88Schristos    const char *str = *strp;
245*b88e3e88Schristos    enum or1k_rclass cls = RCLASS_DIRECT;
246*b88e3e88Schristos    enum or1k_rtype typ;
247*b88e3e88Schristos
248*b88e3e88Schristos    if (strncasecmp (str, "got(", 4) == 0)
249*b88e3e88Schristos      {
250*b88e3e88Schristos	*strp = str + 4;
251*b88e3e88Schristos	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
252*b88e3e88Schristos      }
253*b88e3e88Schristos    if (strncasecmp (str, "gotpo(", 6) == 0)
254*b88e3e88Schristos      {
255*b88e3e88Schristos	*strp = str + 6;
256*b88e3e88Schristos	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
257*b88e3e88Schristos      }
258*b88e3e88Schristos    if (strncasecmp (str, "gottppo(", 8) == 0)
259*b88e3e88Schristos      {
260*b88e3e88Schristos	*strp = str + 8;
261*b88e3e88Schristos	return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
262*b88e3e88Schristos      }
263*b88e3e88Schristos
264*b88e3e88Schristos    if (strncasecmp (str, "gotpc", 5) == 0)
265*b88e3e88Schristos      {
266*b88e3e88Schristos	str += 5;
267*b88e3e88Schristos	cls = RCLASS_GOTPC;
268*b88e3e88Schristos      }
269*b88e3e88Schristos    else if (strncasecmp (str, "gotoff", 6) == 0)
270*b88e3e88Schristos      {
271*b88e3e88Schristos	str += 6;
272*b88e3e88Schristos	cls = RCLASS_GOTOFF;
273*b88e3e88Schristos      }
274*b88e3e88Schristos    else if (strncasecmp (str, "tlsgd", 5) == 0)
275*b88e3e88Schristos      {
276*b88e3e88Schristos	str += 5;
277*b88e3e88Schristos	cls = RCLASS_TLSGD;
278*b88e3e88Schristos      }
279*b88e3e88Schristos    else if (strncasecmp (str, "tlsldm", 6) == 0)
280*b88e3e88Schristos      {
281*b88e3e88Schristos	str += 6;
282*b88e3e88Schristos	cls = RCLASS_TLSLDM;
283*b88e3e88Schristos      }
284*b88e3e88Schristos    else if (strncasecmp (str, "dtpoff", 6) == 0)
285*b88e3e88Schristos      {
286*b88e3e88Schristos	str += 6;
287*b88e3e88Schristos	cls = RCLASS_DTPOFF;
288*b88e3e88Schristos      }
289*b88e3e88Schristos    else if (strncasecmp (str, "gottpoff", 8) == 0)
290*b88e3e88Schristos      {
291*b88e3e88Schristos	str += 8;
292*b88e3e88Schristos	cls = RCLASS_GOTTPOFF;
293*b88e3e88Schristos      }
294*b88e3e88Schristos    else if (strncasecmp (str, "tpoff", 5) == 0)
295*b88e3e88Schristos      {
296*b88e3e88Schristos	str += 5;
297*b88e3e88Schristos	cls = RCLASS_TPOFF;
298*b88e3e88Schristos      }
299*b88e3e88Schristos
300*b88e3e88Schristos    if (strncasecmp (str, "hi(", 3) == 0)
301*b88e3e88Schristos      {
302*b88e3e88Schristos	str += 3;
303*b88e3e88Schristos	typ = RTYPE_HI;
304*b88e3e88Schristos      }
305*b88e3e88Schristos    else if (strncasecmp (str, "lo(", 3) == 0)
306*b88e3e88Schristos      {
307*b88e3e88Schristos	str += 3;
308*b88e3e88Schristos	typ = RTYPE_LO;
309*b88e3e88Schristos      }
310*b88e3e88Schristos    else if (strncasecmp (str, "ha(", 3) == 0)
311*b88e3e88Schristos      {
312*b88e3e88Schristos	str += 3;
313*b88e3e88Schristos	typ = RTYPE_AHI;
314*b88e3e88Schristos      }
315*b88e3e88Schristos    else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
316*b88e3e88Schristos      {
317*b88e3e88Schristos	str += 3;
318*b88e3e88Schristos	typ = RTYPE_PO;
319*b88e3e88Schristos      }
320*b88e3e88Schristos    else
321*b88e3e88Schristos      return -1;
322*b88e3e88Schristos
323*b88e3e88Schristos    *strp = str;
324*b88e3e88Schristos    return (cls << RCLASS_SHIFT) | typ;
325*b88e3e88Schristos}
326*b88e3e88Schristos
327*b88e3e88Schristosstatic const char *
328*b88e3e88Schristosparse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
329*b88e3e88Schristos	     long *valuep, int splitp)
330440a403fSchristos{
331440a403fSchristos  const char *errmsg;
332440a403fSchristos  enum cgen_parse_operand_result result_type;
333*b88e3e88Schristos  bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
334*b88e3e88Schristos  enum or1k_rtype reloc_type;
335*b88e3e88Schristos  int reloc_code;
336*b88e3e88Schristos  bfd_vma ret;
337440a403fSchristos
338440a403fSchristos  if (**strp == '#')
339440a403fSchristos    ++*strp;
340440a403fSchristos
341*b88e3e88Schristos  reloc_code = parse_reloc (strp);
342*b88e3e88Schristos  reloc_type = reloc_code & RTYPE_MASK;
343*b88e3e88Schristos  if (reloc_code >= 0)
344*b88e3e88Schristos    {
345*b88e3e88Schristos      enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
346*b88e3e88Schristos      if (splitp)
347*b88e3e88Schristos	{
348*b88e3e88Schristos	  if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
349*b88e3e88Schristos	      && reloc_class != RCLASS_GOT)
350*b88e3e88Schristos	    /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
351*b88e3e88Schristos	    reloc_type |= 1;
352*b88e3e88Schristos	  else
353*b88e3e88Schristos	    return INVALID_STORE_RELOC;
354*b88e3e88Schristos	}
355*b88e3e88Schristos      reloc = or1k_imm16_relocs[reloc_class][reloc_type];
356*b88e3e88Schristos    }
357*b88e3e88Schristos
358*b88e3e88Schristos  if (reloc != BFD_RELOC_UNUSED)
359440a403fSchristos    {
360440a403fSchristos      bfd_vma value;
361440a403fSchristos
362*b88e3e88Schristos      errmsg = cgen_parse_address (cd, strp, opindex, reloc,
363440a403fSchristos				   &result_type, &value);
364440a403fSchristos      if (**strp != ')')
365440a403fSchristos	errmsg = MISSING_CLOSING_PARENTHESIS;
366440a403fSchristos      ++*strp;
367440a403fSchristos
368440a403fSchristos      ret = value;
369440a403fSchristos
370*b88e3e88Schristos      if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
371*b88e3e88Schristos	switch (reloc_type)
372440a403fSchristos	  {
373*b88e3e88Schristos	  case RTYPE_AHI:
374*b88e3e88Schristos	    ret += 0x8000;
375*b88e3e88Schristos	    /* FALLTHRU */
376*b88e3e88Schristos	  case RTYPE_HI:
377440a403fSchristos	    ret >>= 16;
378*b88e3e88Schristos	    /* FALLTHRU */
379*b88e3e88Schristos	  case RTYPE_LO:
380*b88e3e88Schristos	  case RTYPE_SLO:
381440a403fSchristos	    ret &= 0xffff;
382440a403fSchristos	    ret = (ret ^ 0x8000) - 0x8000;
383*b88e3e88Schristos	    break;
384*b88e3e88Schristos	  case RTYPE_PO:
385*b88e3e88Schristos	  case RTYPE_SPO:
386*b88e3e88Schristos	    ret &= 0x1fff;
387*b88e3e88Schristos	    break;
388*b88e3e88Schristos	  default:
389*b88e3e88Schristos	    errmsg = INVALID_RELOC_TYPE;
390440a403fSchristos	  }
391440a403fSchristos    }
392440a403fSchristos  else
393440a403fSchristos    {
394440a403fSchristos      long value;
395440a403fSchristos      errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
396440a403fSchristos      ret = value;
397440a403fSchristos    }
398440a403fSchristos
399440a403fSchristos  if (errmsg == NULL)
400440a403fSchristos    *valuep = ret;
401440a403fSchristos
402440a403fSchristos  return errmsg;
403440a403fSchristos}
404440a403fSchristos
405440a403fSchristosstatic const char *
406*b88e3e88Schristosparse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
407440a403fSchristos{
408*b88e3e88Schristos  return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
409*b88e3e88Schristos}
410440a403fSchristos
411*b88e3e88Schristosstatic const char *
412*b88e3e88Schristosparse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
413*b88e3e88Schristos		    long *valuep)
414*b88e3e88Schristos{
415*b88e3e88Schristos  return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
416*b88e3e88Schristos}
417*b88e3e88Schristos
418*b88e3e88Schristosstatic const char *
419*b88e3e88Schristosparse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
420*b88e3e88Schristos	      unsigned long *valuep)
421*b88e3e88Schristos{
422*b88e3e88Schristos  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
423440a403fSchristos  if (errmsg == NULL)
424440a403fSchristos    *valuep &= 0xffff;
425440a403fSchristos  return errmsg;
426440a403fSchristos}
427440a403fSchristos
428*b88e3e88Schristosstatic const char *
429*b88e3e88Schristosparse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
430*b88e3e88Schristos		    unsigned long *valuep)
431*b88e3e88Schristos{
432*b88e3e88Schristos  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
433*b88e3e88Schristos  if (errmsg == NULL)
434*b88e3e88Schristos    *valuep &= 0xffff;
435*b88e3e88Schristos  return errmsg;
436*b88e3e88Schristos}
437*b88e3e88Schristos
438*b88e3e88Schristos/* Parse register pairs with syntax rA,rB to a flag + rA value.  */
439*b88e3e88Schristos
440*b88e3e88Schristosstatic const char *
441*b88e3e88Schristosparse_regpair (CGEN_CPU_DESC cd, const char **strp,
442*b88e3e88Schristos	       int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
443*b88e3e88Schristos{
444*b88e3e88Schristos  long reg1_index;
445*b88e3e88Schristos  long reg2_index;
446*b88e3e88Schristos  const char *errmsg;
447*b88e3e88Schristos
448*b88e3e88Schristos  /* The first part should just be a register.  */
449*b88e3e88Schristos  errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
450*b88e3e88Schristos			       &reg1_index);
451*b88e3e88Schristos
452*b88e3e88Schristos  /* If that worked skip the comma separator.  */
453*b88e3e88Schristos  if (errmsg == NULL)
454*b88e3e88Schristos    {
455*b88e3e88Schristos      if (**strp == ',')
456*b88e3e88Schristos	++*strp;
457*b88e3e88Schristos      else
458*b88e3e88Schristos	errmsg = "Unexpected character, expected ','";
459*b88e3e88Schristos    }
460*b88e3e88Schristos
461*b88e3e88Schristos  /* If that worked the next part is just another register.  */
462*b88e3e88Schristos  if (errmsg == NULL)
463*b88e3e88Schristos    errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
464*b88e3e88Schristos				 &reg2_index);
465*b88e3e88Schristos
466*b88e3e88Schristos  /* Validate the register pair is valid and create the output value.  */
467*b88e3e88Schristos  if (errmsg == NULL)
468*b88e3e88Schristos    {
469*b88e3e88Schristos      int regoffset = reg2_index - reg1_index;
470*b88e3e88Schristos
471*b88e3e88Schristos      if (regoffset == 1 || regoffset == 2)
472*b88e3e88Schristos	{
473*b88e3e88Schristos	  unsigned short offsetmask;
474*b88e3e88Schristos	  unsigned short value;
475*b88e3e88Schristos
476*b88e3e88Schristos	  offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
477*b88e3e88Schristos	  value = offsetmask | reg1_index;
478*b88e3e88Schristos
479*b88e3e88Schristos	  *valuep = value;
480*b88e3e88Schristos	}
481*b88e3e88Schristos      else
482*b88e3e88Schristos	errmsg = "Invalid register pair, offset not 1 or 2.";
483*b88e3e88Schristos    }
484*b88e3e88Schristos
485*b88e3e88Schristos  return errmsg;
486*b88e3e88Schristos}
487*b88e3e88Schristos
488*b88e3e88Schristos/* -- */
489*b88e3e88Schristos
490*b88e3e88Schristos/* -- dis.c */
491*b88e3e88Schristos
492*b88e3e88Schristosstatic void
493*b88e3e88Schristosprint_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
494*b88e3e88Schristos	       void * dis_info,
495*b88e3e88Schristos	       long value,
496*b88e3e88Schristos	       unsigned int attrs ATTRIBUTE_UNUSED,
497*b88e3e88Schristos	       bfd_vma pc ATTRIBUTE_UNUSED,
498*b88e3e88Schristos	       int length ATTRIBUTE_UNUSED)
499*b88e3e88Schristos{
500*b88e3e88Schristos  disassemble_info *info = dis_info;
501*b88e3e88Schristos  char reg1_index;
502*b88e3e88Schristos  char reg2_index;
503*b88e3e88Schristos
504*b88e3e88Schristos  reg1_index = value & 0x1f;
505*b88e3e88Schristos  reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
506*b88e3e88Schristos
507*b88e3e88Schristos  (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
508*b88e3e88Schristos}
509*b88e3e88Schristos
510440a403fSchristos/* -- */
511440a403fSchristos
512440a403fSchristos/* -- ibd.h */
513440a403fSchristos
514440a403fSchristos/* -- */
515