xref: /netbsd-src/external/gpl3/binutils.old/dist/cpu/or1k.opc (revision e992f068c547fd6e84b3f104dc2340adcc955732)
116dce513Schristos/* OpenRISC 1000 opcode support.  -*- C -*-
216dce513Schristos   Copyright 2000-2014 Free Software Foundation, Inc.
316dce513Schristos
416dce513Schristos   Originally ontributed for OR32 by Red Hat Inc;
516dce513Schristos
616dce513Schristos   This file is part of the GNU Binutils.
716dce513Schristos
816dce513Schristos   This program is free software; you can redistribute it and/or modify
916dce513Schristos   it under the terms of the GNU General Public License as published by
1016dce513Schristos   the Free Software Foundation; either version 3 of the License, or
1116dce513Schristos   (at your option) any later version.
1216dce513Schristos
1316dce513Schristos   This program is distributed in the hope that it will be useful,
1416dce513Schristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
1516dce513Schristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1616dce513Schristos   GNU General Public License for more details.
1716dce513Schristos
1816dce513Schristos   You should have received a copy of the GNU General Public License
1916dce513Schristos   along with this program; if not, see <http://www.gnu.org/licenses/>. */
2016dce513Schristos
2116dce513Schristos/* This file is an addendum to or1k.cpu.  Heavy use of C code isn't
2216dce513Schristos   appropriate in .cpu files, so it resides here.  This especially applies
2316dce513Schristos   to assembly/disassembly where parsing/printing can be quite involved.
2416dce513Schristos   Such things aren't really part of the specification of the cpu, per se,
2516dce513Schristos   so .cpu files provide the general framework and .opc files handle the
2616dce513Schristos   nitty-gritty details as necessary.
2716dce513Schristos
2816dce513Schristos   Each section is delimited with start and end markers.
2916dce513Schristos
3016dce513Schristos   <arch>-opc.h additions use: "-- opc.h"
3116dce513Schristos   <arch>-opc.c additions use: "-- opc.c"
3216dce513Schristos   <arch>-asm.c additions use: "-- asm.c"
3316dce513Schristos   <arch>-dis.c additions use: "-- dis.c"
3416dce513Schristos   <arch>-ibd.h additions use: "-- ibd.h"  */
3516dce513Schristos
3616dce513Schristos/* -- opc.h */
3716dce513Schristos
3816dce513Schristos#undef  CGEN_DIS_HASH_SIZE
3916dce513Schristos#define CGEN_DIS_HASH_SIZE 256
4016dce513Schristos#undef  CGEN_DIS_HASH
4116dce513Schristos#define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
4216dce513Schristos
43012573ebSchristos/* Check applicability of instructions against machines.  */
44012573ebSchristos#define CGEN_VALIDATE_INSN_SUPPORTED
45012573ebSchristos
46012573ebSchristosextern int or1k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
47012573ebSchristos
4816dce513Schristos/* -- */
4916dce513Schristos
5016dce513Schristos/* -- opc.c */
51012573ebSchristos
52012573ebSchristos/* Special check to ensure that instruction exists for given machine.  */
53012573ebSchristos
54012573ebSchristosint
55012573ebSchristosor1k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
56012573ebSchristos{
57012573ebSchristos  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
58012573ebSchristos
59012573ebSchristos  /* No mach attribute?  Assume it's supported for all machs.  */
60012573ebSchristos  if (machs == 0)
61012573ebSchristos    return 1;
62012573ebSchristos
63012573ebSchristos  return ((machs & cd->machs) != 0);
64012573ebSchristos}
65012573ebSchristos
6616dce513Schristos/* -- */
6716dce513Schristos
6816dce513Schristos/* -- asm.c */
6916dce513Schristos
7016dce513Schristosstatic const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
71012573ebSchristosstatic const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
72012573ebSchristosstatic const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
7316dce513Schristos
7416dce513Schristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS
7516dce513Schristos
7616dce513Schristosstatic const char *
7716dce513Schristosparse_disp26 (CGEN_CPU_DESC cd,
7816dce513Schristos	      const char ** strp,
7916dce513Schristos	      int opindex,
80012573ebSchristos	      int opinfo ATTRIBUTE_UNUSED,
8116dce513Schristos	      enum cgen_parse_operand_result * resultp,
8216dce513Schristos	      bfd_vma * valuep)
8316dce513Schristos{
84012573ebSchristos  const char *str = *strp;
8516dce513Schristos  const char *errmsg = NULL;
86012573ebSchristos  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
8716dce513Schristos
88012573ebSchristos  if (strncasecmp (str, "plta(", 5) == 0)
8916dce513Schristos    {
90012573ebSchristos      *strp = str + 5;
91012573ebSchristos      reloc = BFD_RELOC_OR1K_PLTA26;
9216dce513Schristos    }
93012573ebSchristos  else if (strncasecmp (str, "plt(", 4) == 0)
94012573ebSchristos    {
95012573ebSchristos      *strp = str + 4;
96012573ebSchristos      reloc = BFD_RELOC_OR1K_PLT26;
97012573ebSchristos    }
98012573ebSchristos
99012573ebSchristos  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
100012573ebSchristos
101012573ebSchristos  if (reloc != BFD_RELOC_OR1K_REL_26)
102012573ebSchristos    {
103012573ebSchristos      if (**strp != ')')
104012573ebSchristos	errmsg = MISSING_CLOSING_PARENTHESIS;
105012573ebSchristos      else
106012573ebSchristos	++*strp;
107012573ebSchristos    }
108012573ebSchristos
109012573ebSchristos  return errmsg;
11016dce513Schristos}
11116dce513Schristos
11216dce513Schristosstatic const char *
113012573ebSchristosparse_disp21 (CGEN_CPU_DESC cd,
114012573ebSchristos	      const char ** strp,
115012573ebSchristos	      int opindex,
116012573ebSchristos	      int opinfo ATTRIBUTE_UNUSED,
117012573ebSchristos	      enum cgen_parse_operand_result * resultp,
118012573ebSchristos	      bfd_vma * valuep)
119012573ebSchristos{
120012573ebSchristos  const char *str = *strp;
121012573ebSchristos  const char *errmsg = NULL;
122012573ebSchristos  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
123012573ebSchristos
124012573ebSchristos  if (strncasecmp (str, "got(", 4) == 0)
125012573ebSchristos    {
126012573ebSchristos      *strp = str + 4;
127012573ebSchristos      reloc = BFD_RELOC_OR1K_GOT_PG21;
128012573ebSchristos    }
129012573ebSchristos  else if (strncasecmp (str, "tlsgd(", 6) == 0)
130012573ebSchristos    {
131012573ebSchristos      *strp = str + 6;
132012573ebSchristos      reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
133012573ebSchristos    }
134012573ebSchristos  else if (strncasecmp (str, "tlsldm(", 7) == 0)
135012573ebSchristos    {
136012573ebSchristos      *strp = str + 7;
137012573ebSchristos      reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
138012573ebSchristos    }
139012573ebSchristos  else if (strncasecmp (str, "gottp(", 6) == 0)
140012573ebSchristos    {
141012573ebSchristos      *strp = str + 6;
142012573ebSchristos      reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
143012573ebSchristos    }
144012573ebSchristos
145012573ebSchristos  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
146012573ebSchristos
147012573ebSchristos  if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
148012573ebSchristos    {
149012573ebSchristos      if (**strp != ')')
150012573ebSchristos	errmsg = MISSING_CLOSING_PARENTHESIS;
151012573ebSchristos      else
152012573ebSchristos	++*strp;
153012573ebSchristos    }
154012573ebSchristos
155012573ebSchristos  return errmsg;
156012573ebSchristos}
157012573ebSchristos
158012573ebSchristosenum or1k_rclass
159012573ebSchristos{
160012573ebSchristos  RCLASS_DIRECT   = 0,
161012573ebSchristos  RCLASS_GOT      = 1,
162012573ebSchristos  RCLASS_GOTPC    = 2,
163012573ebSchristos  RCLASS_GOTOFF   = 3,
164012573ebSchristos  RCLASS_TLSGD    = 4,
165012573ebSchristos  RCLASS_TLSLDM   = 5,
166012573ebSchristos  RCLASS_DTPOFF   = 6,
167012573ebSchristos  RCLASS_GOTTPOFF = 7,
168012573ebSchristos  RCLASS_TPOFF    = 8,
169012573ebSchristos};
170012573ebSchristos
171012573ebSchristosenum or1k_rtype
172012573ebSchristos{
173012573ebSchristos  RTYPE_LO = 0,
174012573ebSchristos  RTYPE_SLO = 1,
175012573ebSchristos  RTYPE_PO = 2,
176012573ebSchristos  RTYPE_SPO = 3,
177012573ebSchristos  RTYPE_HI = 4,
178012573ebSchristos  RTYPE_AHI = 5,
179012573ebSchristos};
180012573ebSchristos
181012573ebSchristos#define RCLASS_SHIFT 3
182012573ebSchristos#define RTYPE_MASK   7
183012573ebSchristos
184012573ebSchristosstatic const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
185012573ebSchristos  { BFD_RELOC_LO16,
186012573ebSchristos    BFD_RELOC_OR1K_SLO16,
187012573ebSchristos    BFD_RELOC_OR1K_LO13,
188012573ebSchristos    BFD_RELOC_OR1K_SLO13,
189012573ebSchristos    BFD_RELOC_HI16,
190012573ebSchristos    BFD_RELOC_HI16_S, },
191012573ebSchristos  { BFD_RELOC_OR1K_GOT16,
192012573ebSchristos    BFD_RELOC_UNUSED,
193012573ebSchristos    BFD_RELOC_OR1K_GOT_LO13,
194012573ebSchristos    BFD_RELOC_UNUSED,
195012573ebSchristos    BFD_RELOC_UNUSED,
196*e992f068Schristos    BFD_RELOC_OR1K_GOT_AHI16 },
197012573ebSchristos  { BFD_RELOC_OR1K_GOTPC_LO16,
198012573ebSchristos    BFD_RELOC_UNUSED,
199012573ebSchristos    BFD_RELOC_UNUSED,
200012573ebSchristos    BFD_RELOC_UNUSED,
201012573ebSchristos    BFD_RELOC_OR1K_GOTPC_HI16,
202012573ebSchristos    BFD_RELOC_UNUSED },
203012573ebSchristos  { BFD_RELOC_LO16_GOTOFF,
204012573ebSchristos    BFD_RELOC_OR1K_GOTOFF_SLO16,
205012573ebSchristos    BFD_RELOC_UNUSED,
206012573ebSchristos    BFD_RELOC_UNUSED,
207012573ebSchristos    BFD_RELOC_HI16_GOTOFF,
208012573ebSchristos    BFD_RELOC_HI16_S_GOTOFF },
209012573ebSchristos  { BFD_RELOC_OR1K_TLS_GD_LO16,
210012573ebSchristos    BFD_RELOC_UNUSED,
211012573ebSchristos    BFD_RELOC_OR1K_TLS_GD_LO13,
212012573ebSchristos    BFD_RELOC_UNUSED,
213012573ebSchristos    BFD_RELOC_OR1K_TLS_GD_HI16,
214012573ebSchristos    BFD_RELOC_UNUSED },
215012573ebSchristos  { BFD_RELOC_OR1K_TLS_LDM_LO16,
216012573ebSchristos    BFD_RELOC_UNUSED,
217012573ebSchristos    BFD_RELOC_OR1K_TLS_LDM_LO13,
218012573ebSchristos    BFD_RELOC_UNUSED,
219012573ebSchristos    BFD_RELOC_OR1K_TLS_LDM_HI16,
220012573ebSchristos    BFD_RELOC_UNUSED },
221012573ebSchristos  { BFD_RELOC_OR1K_TLS_LDO_LO16,
222012573ebSchristos    BFD_RELOC_UNUSED,
223012573ebSchristos    BFD_RELOC_UNUSED,
224012573ebSchristos    BFD_RELOC_UNUSED,
225012573ebSchristos    BFD_RELOC_OR1K_TLS_LDO_HI16,
226012573ebSchristos    BFD_RELOC_UNUSED },
227012573ebSchristos  { BFD_RELOC_OR1K_TLS_IE_LO16,
228012573ebSchristos    BFD_RELOC_UNUSED,
229012573ebSchristos    BFD_RELOC_OR1K_TLS_IE_LO13,
230012573ebSchristos    BFD_RELOC_UNUSED,
231012573ebSchristos    BFD_RELOC_OR1K_TLS_IE_HI16,
232012573ebSchristos    BFD_RELOC_OR1K_TLS_IE_AHI16 },
233012573ebSchristos  { BFD_RELOC_OR1K_TLS_LE_LO16,
234012573ebSchristos    BFD_RELOC_OR1K_TLS_LE_SLO16,
235012573ebSchristos    BFD_RELOC_UNUSED,
236012573ebSchristos    BFD_RELOC_UNUSED,
237012573ebSchristos    BFD_RELOC_OR1K_TLS_LE_HI16,
238012573ebSchristos    BFD_RELOC_OR1K_TLS_LE_AHI16 },
239012573ebSchristos};
240012573ebSchristos
241012573ebSchristosstatic int
242012573ebSchristosparse_reloc (const char **strp)
243012573ebSchristos{
244012573ebSchristos    const char *str = *strp;
245012573ebSchristos    enum or1k_rclass cls = RCLASS_DIRECT;
246012573ebSchristos    enum or1k_rtype typ;
247012573ebSchristos
248012573ebSchristos    if (strncasecmp (str, "got(", 4) == 0)
249012573ebSchristos      {
250012573ebSchristos	*strp = str + 4;
251012573ebSchristos	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
252012573ebSchristos      }
253012573ebSchristos    if (strncasecmp (str, "gotpo(", 6) == 0)
254012573ebSchristos      {
255012573ebSchristos	*strp = str + 6;
256012573ebSchristos	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
257012573ebSchristos      }
258012573ebSchristos    if (strncasecmp (str, "gottppo(", 8) == 0)
259012573ebSchristos      {
260012573ebSchristos	*strp = str + 8;
261012573ebSchristos	return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
262012573ebSchristos      }
263012573ebSchristos
264012573ebSchristos    if (strncasecmp (str, "gotpc", 5) == 0)
265012573ebSchristos      {
266012573ebSchristos	str += 5;
267012573ebSchristos	cls = RCLASS_GOTPC;
268012573ebSchristos      }
269012573ebSchristos    else if (strncasecmp (str, "gotoff", 6) == 0)
270012573ebSchristos      {
271012573ebSchristos	str += 6;
272012573ebSchristos	cls = RCLASS_GOTOFF;
273012573ebSchristos      }
274012573ebSchristos    else if (strncasecmp (str, "tlsgd", 5) == 0)
275012573ebSchristos      {
276012573ebSchristos	str += 5;
277012573ebSchristos	cls = RCLASS_TLSGD;
278012573ebSchristos      }
279012573ebSchristos    else if (strncasecmp (str, "tlsldm", 6) == 0)
280012573ebSchristos      {
281012573ebSchristos	str += 6;
282012573ebSchristos	cls = RCLASS_TLSLDM;
283012573ebSchristos      }
284012573ebSchristos    else if (strncasecmp (str, "dtpoff", 6) == 0)
285012573ebSchristos      {
286012573ebSchristos	str += 6;
287012573ebSchristos	cls = RCLASS_DTPOFF;
288012573ebSchristos      }
289012573ebSchristos    else if (strncasecmp (str, "gottpoff", 8) == 0)
290012573ebSchristos      {
291012573ebSchristos	str += 8;
292012573ebSchristos	cls = RCLASS_GOTTPOFF;
293012573ebSchristos      }
294012573ebSchristos    else if (strncasecmp (str, "tpoff", 5) == 0)
295012573ebSchristos      {
296012573ebSchristos	str += 5;
297012573ebSchristos	cls = RCLASS_TPOFF;
298012573ebSchristos      }
299*e992f068Schristos    else if (strncasecmp (str, "got", 3) == 0)
300*e992f068Schristos      {
301*e992f068Schristos	str += 3;
302*e992f068Schristos	cls = RCLASS_GOT;
303*e992f068Schristos      }
304012573ebSchristos
305012573ebSchristos    if (strncasecmp (str, "hi(", 3) == 0)
306012573ebSchristos      {
307012573ebSchristos	str += 3;
308012573ebSchristos	typ = RTYPE_HI;
309012573ebSchristos      }
310012573ebSchristos    else if (strncasecmp (str, "lo(", 3) == 0)
311012573ebSchristos      {
312012573ebSchristos	str += 3;
313012573ebSchristos	typ = RTYPE_LO;
314012573ebSchristos      }
315012573ebSchristos    else if (strncasecmp (str, "ha(", 3) == 0)
316012573ebSchristos      {
317012573ebSchristos	str += 3;
318012573ebSchristos	typ = RTYPE_AHI;
319012573ebSchristos      }
320012573ebSchristos    else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
321012573ebSchristos      {
322012573ebSchristos	str += 3;
323012573ebSchristos	typ = RTYPE_PO;
324012573ebSchristos      }
325012573ebSchristos    else
326012573ebSchristos      return -1;
327012573ebSchristos
328012573ebSchristos    *strp = str;
329012573ebSchristos    return (cls << RCLASS_SHIFT) | typ;
330012573ebSchristos}
331012573ebSchristos
332012573ebSchristosstatic const char *
333012573ebSchristosparse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
334012573ebSchristos	     long *valuep, int splitp)
33516dce513Schristos{
33616dce513Schristos  const char *errmsg;
33716dce513Schristos  enum cgen_parse_operand_result result_type;
338012573ebSchristos  bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
339012573ebSchristos  enum or1k_rtype reloc_type;
340012573ebSchristos  int reloc_code;
341012573ebSchristos  bfd_vma ret;
34216dce513Schristos
34316dce513Schristos  if (**strp == '#')
34416dce513Schristos    ++*strp;
34516dce513Schristos
346012573ebSchristos  reloc_code = parse_reloc (strp);
347012573ebSchristos  reloc_type = reloc_code & RTYPE_MASK;
348012573ebSchristos  if (reloc_code >= 0)
349012573ebSchristos    {
350012573ebSchristos      enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
351012573ebSchristos      if (splitp)
352012573ebSchristos	{
353012573ebSchristos	  if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
354012573ebSchristos	      && reloc_class != RCLASS_GOT)
355012573ebSchristos	    /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
356012573ebSchristos	    reloc_type |= 1;
357012573ebSchristos	  else
358012573ebSchristos	    return INVALID_STORE_RELOC;
359012573ebSchristos	}
360012573ebSchristos      reloc = or1k_imm16_relocs[reloc_class][reloc_type];
361012573ebSchristos    }
362012573ebSchristos
363012573ebSchristos  if (reloc != BFD_RELOC_UNUSED)
36416dce513Schristos    {
36516dce513Schristos      bfd_vma value;
36616dce513Schristos
367012573ebSchristos      errmsg = cgen_parse_address (cd, strp, opindex, reloc,
36816dce513Schristos				   &result_type, &value);
36916dce513Schristos      if (**strp != ')')
37016dce513Schristos	errmsg = MISSING_CLOSING_PARENTHESIS;
37116dce513Schristos      ++*strp;
37216dce513Schristos
37316dce513Schristos      ret = value;
37416dce513Schristos
375012573ebSchristos      if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
376012573ebSchristos	switch (reloc_type)
37716dce513Schristos	  {
378012573ebSchristos	  case RTYPE_AHI:
379012573ebSchristos	    ret += 0x8000;
380012573ebSchristos	    /* FALLTHRU */
381012573ebSchristos	  case RTYPE_HI:
38216dce513Schristos	    ret >>= 16;
383012573ebSchristos	    /* FALLTHRU */
384012573ebSchristos	  case RTYPE_LO:
385012573ebSchristos	  case RTYPE_SLO:
38616dce513Schristos	    ret &= 0xffff;
38716dce513Schristos	    ret = (ret ^ 0x8000) - 0x8000;
388012573ebSchristos	    break;
389012573ebSchristos	  case RTYPE_PO:
390012573ebSchristos	  case RTYPE_SPO:
391012573ebSchristos	    ret &= 0x1fff;
392012573ebSchristos	    break;
393012573ebSchristos	  default:
394012573ebSchristos	    errmsg = INVALID_RELOC_TYPE;
39516dce513Schristos	  }
39616dce513Schristos    }
39716dce513Schristos  else
39816dce513Schristos    {
39916dce513Schristos      long value;
40016dce513Schristos      errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
40116dce513Schristos      ret = value;
40216dce513Schristos    }
40316dce513Schristos
40416dce513Schristos  if (errmsg == NULL)
40516dce513Schristos    *valuep = ret;
40616dce513Schristos
40716dce513Schristos  return errmsg;
40816dce513Schristos}
40916dce513Schristos
41016dce513Schristosstatic const char *
411012573ebSchristosparse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
41216dce513Schristos{
413012573ebSchristos  return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
414012573ebSchristos}
41516dce513Schristos
416012573ebSchristosstatic const char *
417012573ebSchristosparse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
418012573ebSchristos		    long *valuep)
419012573ebSchristos{
420012573ebSchristos  return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
421012573ebSchristos}
422012573ebSchristos
423012573ebSchristosstatic const char *
424012573ebSchristosparse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
425012573ebSchristos	      unsigned long *valuep)
426012573ebSchristos{
427012573ebSchristos  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
42816dce513Schristos  if (errmsg == NULL)
42916dce513Schristos    *valuep &= 0xffff;
43016dce513Schristos  return errmsg;
43116dce513Schristos}
43216dce513Schristos
433012573ebSchristosstatic const char *
434012573ebSchristosparse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
435012573ebSchristos		    unsigned long *valuep)
436012573ebSchristos{
437012573ebSchristos  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
438012573ebSchristos  if (errmsg == NULL)
439012573ebSchristos    *valuep &= 0xffff;
440012573ebSchristos  return errmsg;
441012573ebSchristos}
442012573ebSchristos
443012573ebSchristos/* Parse register pairs with syntax rA,rB to a flag + rA value.  */
444012573ebSchristos
445012573ebSchristosstatic const char *
446012573ebSchristosparse_regpair (CGEN_CPU_DESC cd, const char **strp,
447012573ebSchristos	       int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
448012573ebSchristos{
449012573ebSchristos  long reg1_index;
450012573ebSchristos  long reg2_index;
451012573ebSchristos  const char *errmsg;
452012573ebSchristos
453012573ebSchristos  /* The first part should just be a register.  */
454012573ebSchristos  errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
455012573ebSchristos			       &reg1_index);
456012573ebSchristos
457012573ebSchristos  /* If that worked skip the comma separator.  */
458012573ebSchristos  if (errmsg == NULL)
459012573ebSchristos    {
460012573ebSchristos      if (**strp == ',')
461012573ebSchristos	++*strp;
462012573ebSchristos      else
463012573ebSchristos	errmsg = "Unexpected character, expected ','";
464012573ebSchristos    }
465012573ebSchristos
466012573ebSchristos  /* If that worked the next part is just another register.  */
467012573ebSchristos  if (errmsg == NULL)
468012573ebSchristos    errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
469012573ebSchristos				 &reg2_index);
470012573ebSchristos
471012573ebSchristos  /* Validate the register pair is valid and create the output value.  */
472012573ebSchristos  if (errmsg == NULL)
473012573ebSchristos    {
474012573ebSchristos      int regoffset = reg2_index - reg1_index;
475012573ebSchristos
476012573ebSchristos      if (regoffset == 1 || regoffset == 2)
477012573ebSchristos	{
478012573ebSchristos	  unsigned short offsetmask;
479012573ebSchristos	  unsigned short value;
480012573ebSchristos
481012573ebSchristos	  offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
482012573ebSchristos	  value = offsetmask | reg1_index;
483012573ebSchristos
484012573ebSchristos	  *valuep = value;
485012573ebSchristos	}
486012573ebSchristos      else
487012573ebSchristos	errmsg = "Invalid register pair, offset not 1 or 2.";
488012573ebSchristos    }
489012573ebSchristos
490012573ebSchristos  return errmsg;
491012573ebSchristos}
492012573ebSchristos
493012573ebSchristos/* -- */
494012573ebSchristos
495012573ebSchristos/* -- dis.c */
496012573ebSchristos
497012573ebSchristosstatic void
498012573ebSchristosprint_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
499012573ebSchristos	       void * dis_info,
500012573ebSchristos	       long value,
501012573ebSchristos	       unsigned int attrs ATTRIBUTE_UNUSED,
502012573ebSchristos	       bfd_vma pc ATTRIBUTE_UNUSED,
503012573ebSchristos	       int length ATTRIBUTE_UNUSED)
504012573ebSchristos{
505012573ebSchristos  disassemble_info *info = dis_info;
506012573ebSchristos  char reg1_index;
507012573ebSchristos  char reg2_index;
508012573ebSchristos
509012573ebSchristos  reg1_index = value & 0x1f;
510012573ebSchristos  reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
511012573ebSchristos
512012573ebSchristos  (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
513012573ebSchristos}
514012573ebSchristos
51516dce513Schristos/* -- */
51616dce513Schristos
51716dce513Schristos/* -- ibd.h */
51816dce513Schristos
51916dce513Schristos/* -- */
520