xref: /netbsd-src/external/gpl3/binutils/dist/cpu/or1k.opc (revision 03f5171a7b36cbd3eb2581be737439f912b7121f)
1a45653d1Smatt/* OpenRISC 1000 opcode support.  -*- C -*-
2a45653d1Smatt   Copyright 2000-2014 Free Software Foundation, Inc.
3a45653d1Smatt
4a45653d1Smatt   Originally ontributed for OR32 by Red Hat Inc;
5a45653d1Smatt
6a45653d1Smatt   This file is part of the GNU Binutils.
7a45653d1Smatt
8a45653d1Smatt   This program is free software; you can redistribute it and/or modify
9a45653d1Smatt   it under the terms of the GNU General Public License as published by
10a45653d1Smatt   the Free Software Foundation; either version 3 of the License, or
11a45653d1Smatt   (at your option) any later version.
12a45653d1Smatt
13a45653d1Smatt   This program is distributed in the hope that it will be useful,
14a45653d1Smatt   but WITHOUT ANY WARRANTY; without even the implied warranty of
15a45653d1Smatt   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16a45653d1Smatt   GNU General Public License for more details.
17a45653d1Smatt
18a45653d1Smatt   You should have received a copy of the GNU General Public License
19a45653d1Smatt   along with this program; if not, see <http://www.gnu.org/licenses/>. */
20a45653d1Smatt
21a45653d1Smatt/* This file is an addendum to or1k.cpu.  Heavy use of C code isn't
22a45653d1Smatt   appropriate in .cpu files, so it resides here.  This especially applies
23a45653d1Smatt   to assembly/disassembly where parsing/printing can be quite involved.
24a45653d1Smatt   Such things aren't really part of the specification of the cpu, per se,
25a45653d1Smatt   so .cpu files provide the general framework and .opc files handle the
26a45653d1Smatt   nitty-gritty details as necessary.
27a45653d1Smatt
28a45653d1Smatt   Each section is delimited with start and end markers.
29a45653d1Smatt
30a45653d1Smatt   <arch>-opc.h additions use: "-- opc.h"
31a45653d1Smatt   <arch>-opc.c additions use: "-- opc.c"
32a45653d1Smatt   <arch>-asm.c additions use: "-- asm.c"
33a45653d1Smatt   <arch>-dis.c additions use: "-- dis.c"
34a45653d1Smatt   <arch>-ibd.h additions use: "-- ibd.h"  */
35a45653d1Smatt
36a45653d1Smatt/* -- opc.h */
37a45653d1Smatt
38a45653d1Smatt#undef  CGEN_DIS_HASH_SIZE
39a45653d1Smatt#define CGEN_DIS_HASH_SIZE 256
40a45653d1Smatt#undef  CGEN_DIS_HASH
41a45653d1Smatt#define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
42a45653d1Smatt
436f4ced0bSchristos/* Check applicability of instructions against machines.  */
446f4ced0bSchristos#define CGEN_VALIDATE_INSN_SUPPORTED
456f4ced0bSchristos
466f4ced0bSchristosextern int or1k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
476f4ced0bSchristos
48a45653d1Smatt/* -- */
49a45653d1Smatt
50a45653d1Smatt/* -- opc.c */
516f4ced0bSchristos
526f4ced0bSchristos/* Special check to ensure that instruction exists for given machine.  */
536f4ced0bSchristos
546f4ced0bSchristosint
556f4ced0bSchristosor1k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
566f4ced0bSchristos{
576f4ced0bSchristos  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
586f4ced0bSchristos
596f4ced0bSchristos  /* No mach attribute?  Assume it's supported for all machs.  */
606f4ced0bSchristos  if (machs == 0)
616f4ced0bSchristos    return 1;
626f4ced0bSchristos
636f4ced0bSchristos  return ((machs & cd->machs) != 0);
646f4ced0bSchristos}
656f4ced0bSchristos
66a45653d1Smatt/* -- */
67a45653d1Smatt
68a45653d1Smatt/* -- asm.c */
69a45653d1Smatt
70a45653d1Smattstatic const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
716f4ced0bSchristosstatic const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
726f4ced0bSchristosstatic const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
73a45653d1Smatt
74a45653d1Smatt#define CGEN_VERBOSE_ASSEMBLER_ERRORS
75a45653d1Smatt
76a45653d1Smattstatic const char *
77a45653d1Smattparse_disp26 (CGEN_CPU_DESC cd,
78a45653d1Smatt	      const char ** strp,
79a45653d1Smatt	      int opindex,
806f4ced0bSchristos	      int opinfo ATTRIBUTE_UNUSED,
81a45653d1Smatt	      enum cgen_parse_operand_result * resultp,
82a45653d1Smatt	      bfd_vma * valuep)
83a45653d1Smatt{
846f4ced0bSchristos  const char *str = *strp;
85a45653d1Smatt  const char *errmsg = NULL;
866f4ced0bSchristos  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
87a45653d1Smatt
886f4ced0bSchristos  if (strncasecmp (str, "plta(", 5) == 0)
89a45653d1Smatt    {
906f4ced0bSchristos      *strp = str + 5;
916f4ced0bSchristos      reloc = BFD_RELOC_OR1K_PLTA26;
92a45653d1Smatt    }
936f4ced0bSchristos  else if (strncasecmp (str, "plt(", 4) == 0)
946f4ced0bSchristos    {
956f4ced0bSchristos      *strp = str + 4;
966f4ced0bSchristos      reloc = BFD_RELOC_OR1K_PLT26;
976f4ced0bSchristos    }
986f4ced0bSchristos
996f4ced0bSchristos  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
1006f4ced0bSchristos
1016f4ced0bSchristos  if (reloc != BFD_RELOC_OR1K_REL_26)
1026f4ced0bSchristos    {
1036f4ced0bSchristos      if (**strp != ')')
1046f4ced0bSchristos	errmsg = MISSING_CLOSING_PARENTHESIS;
1056f4ced0bSchristos      else
1066f4ced0bSchristos	++*strp;
1076f4ced0bSchristos    }
1086f4ced0bSchristos
1096f4ced0bSchristos  return errmsg;
110a45653d1Smatt}
111a45653d1Smatt
112a45653d1Smattstatic const char *
1136f4ced0bSchristosparse_disp21 (CGEN_CPU_DESC cd,
1146f4ced0bSchristos	      const char ** strp,
1156f4ced0bSchristos	      int opindex,
1166f4ced0bSchristos	      int opinfo ATTRIBUTE_UNUSED,
1176f4ced0bSchristos	      enum cgen_parse_operand_result * resultp,
1186f4ced0bSchristos	      bfd_vma * valuep)
1196f4ced0bSchristos{
1206f4ced0bSchristos  const char *str = *strp;
1216f4ced0bSchristos  const char *errmsg = NULL;
1226f4ced0bSchristos  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
1236f4ced0bSchristos
1246f4ced0bSchristos  if (strncasecmp (str, "got(", 4) == 0)
1256f4ced0bSchristos    {
1266f4ced0bSchristos      *strp = str + 4;
1276f4ced0bSchristos      reloc = BFD_RELOC_OR1K_GOT_PG21;
1286f4ced0bSchristos    }
1296f4ced0bSchristos  else if (strncasecmp (str, "tlsgd(", 6) == 0)
1306f4ced0bSchristos    {
1316f4ced0bSchristos      *strp = str + 6;
1326f4ced0bSchristos      reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
1336f4ced0bSchristos    }
1346f4ced0bSchristos  else if (strncasecmp (str, "tlsldm(", 7) == 0)
1356f4ced0bSchristos    {
1366f4ced0bSchristos      *strp = str + 7;
1376f4ced0bSchristos      reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
1386f4ced0bSchristos    }
1396f4ced0bSchristos  else if (strncasecmp (str, "gottp(", 6) == 0)
1406f4ced0bSchristos    {
1416f4ced0bSchristos      *strp = str + 6;
1426f4ced0bSchristos      reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
1436f4ced0bSchristos    }
1446f4ced0bSchristos
1456f4ced0bSchristos  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
1466f4ced0bSchristos
1476f4ced0bSchristos  if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
1486f4ced0bSchristos    {
1496f4ced0bSchristos      if (**strp != ')')
1506f4ced0bSchristos	errmsg = MISSING_CLOSING_PARENTHESIS;
1516f4ced0bSchristos      else
1526f4ced0bSchristos	++*strp;
1536f4ced0bSchristos    }
1546f4ced0bSchristos
1556f4ced0bSchristos  return errmsg;
1566f4ced0bSchristos}
1576f4ced0bSchristos
1586f4ced0bSchristosenum or1k_rclass
1596f4ced0bSchristos{
1606f4ced0bSchristos  RCLASS_DIRECT   = 0,
1616f4ced0bSchristos  RCLASS_GOT      = 1,
1626f4ced0bSchristos  RCLASS_GOTPC    = 2,
1636f4ced0bSchristos  RCLASS_GOTOFF   = 3,
1646f4ced0bSchristos  RCLASS_TLSGD    = 4,
1656f4ced0bSchristos  RCLASS_TLSLDM   = 5,
1666f4ced0bSchristos  RCLASS_DTPOFF   = 6,
1676f4ced0bSchristos  RCLASS_GOTTPOFF = 7,
1686f4ced0bSchristos  RCLASS_TPOFF    = 8,
1696f4ced0bSchristos};
1706f4ced0bSchristos
1716f4ced0bSchristosenum or1k_rtype
1726f4ced0bSchristos{
1736f4ced0bSchristos  RTYPE_LO = 0,
1746f4ced0bSchristos  RTYPE_SLO = 1,
1756f4ced0bSchristos  RTYPE_PO = 2,
1766f4ced0bSchristos  RTYPE_SPO = 3,
1776f4ced0bSchristos  RTYPE_HI = 4,
1786f4ced0bSchristos  RTYPE_AHI = 5,
1796f4ced0bSchristos};
1806f4ced0bSchristos
1816f4ced0bSchristos#define RCLASS_SHIFT 3
1826f4ced0bSchristos#define RTYPE_MASK   7
1836f4ced0bSchristos
1846f4ced0bSchristosstatic const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
1856f4ced0bSchristos  { BFD_RELOC_LO16,
1866f4ced0bSchristos    BFD_RELOC_OR1K_SLO16,
1876f4ced0bSchristos    BFD_RELOC_OR1K_LO13,
1886f4ced0bSchristos    BFD_RELOC_OR1K_SLO13,
1896f4ced0bSchristos    BFD_RELOC_HI16,
1906f4ced0bSchristos    BFD_RELOC_HI16_S, },
1916f4ced0bSchristos  { BFD_RELOC_OR1K_GOT16,
1926f4ced0bSchristos    BFD_RELOC_UNUSED,
1936f4ced0bSchristos    BFD_RELOC_OR1K_GOT_LO13,
1946f4ced0bSchristos    BFD_RELOC_UNUSED,
1956f4ced0bSchristos    BFD_RELOC_UNUSED,
196*03f5171aSchristos    BFD_RELOC_OR1K_GOT_AHI16 },
1976f4ced0bSchristos  { BFD_RELOC_OR1K_GOTPC_LO16,
1986f4ced0bSchristos    BFD_RELOC_UNUSED,
1996f4ced0bSchristos    BFD_RELOC_UNUSED,
2006f4ced0bSchristos    BFD_RELOC_UNUSED,
2016f4ced0bSchristos    BFD_RELOC_OR1K_GOTPC_HI16,
2026f4ced0bSchristos    BFD_RELOC_UNUSED },
2036f4ced0bSchristos  { BFD_RELOC_LO16_GOTOFF,
2046f4ced0bSchristos    BFD_RELOC_OR1K_GOTOFF_SLO16,
2056f4ced0bSchristos    BFD_RELOC_UNUSED,
2066f4ced0bSchristos    BFD_RELOC_UNUSED,
2076f4ced0bSchristos    BFD_RELOC_HI16_GOTOFF,
2086f4ced0bSchristos    BFD_RELOC_HI16_S_GOTOFF },
2096f4ced0bSchristos  { BFD_RELOC_OR1K_TLS_GD_LO16,
2106f4ced0bSchristos    BFD_RELOC_UNUSED,
2116f4ced0bSchristos    BFD_RELOC_OR1K_TLS_GD_LO13,
2126f4ced0bSchristos    BFD_RELOC_UNUSED,
2136f4ced0bSchristos    BFD_RELOC_OR1K_TLS_GD_HI16,
2146f4ced0bSchristos    BFD_RELOC_UNUSED },
2156f4ced0bSchristos  { BFD_RELOC_OR1K_TLS_LDM_LO16,
2166f4ced0bSchristos    BFD_RELOC_UNUSED,
2176f4ced0bSchristos    BFD_RELOC_OR1K_TLS_LDM_LO13,
2186f4ced0bSchristos    BFD_RELOC_UNUSED,
2196f4ced0bSchristos    BFD_RELOC_OR1K_TLS_LDM_HI16,
2206f4ced0bSchristos    BFD_RELOC_UNUSED },
2216f4ced0bSchristos  { BFD_RELOC_OR1K_TLS_LDO_LO16,
2226f4ced0bSchristos    BFD_RELOC_UNUSED,
2236f4ced0bSchristos    BFD_RELOC_UNUSED,
2246f4ced0bSchristos    BFD_RELOC_UNUSED,
2256f4ced0bSchristos    BFD_RELOC_OR1K_TLS_LDO_HI16,
2266f4ced0bSchristos    BFD_RELOC_UNUSED },
2276f4ced0bSchristos  { BFD_RELOC_OR1K_TLS_IE_LO16,
2286f4ced0bSchristos    BFD_RELOC_UNUSED,
2296f4ced0bSchristos    BFD_RELOC_OR1K_TLS_IE_LO13,
2306f4ced0bSchristos    BFD_RELOC_UNUSED,
2316f4ced0bSchristos    BFD_RELOC_OR1K_TLS_IE_HI16,
2326f4ced0bSchristos    BFD_RELOC_OR1K_TLS_IE_AHI16 },
2336f4ced0bSchristos  { BFD_RELOC_OR1K_TLS_LE_LO16,
2346f4ced0bSchristos    BFD_RELOC_OR1K_TLS_LE_SLO16,
2356f4ced0bSchristos    BFD_RELOC_UNUSED,
2366f4ced0bSchristos    BFD_RELOC_UNUSED,
2376f4ced0bSchristos    BFD_RELOC_OR1K_TLS_LE_HI16,
2386f4ced0bSchristos    BFD_RELOC_OR1K_TLS_LE_AHI16 },
2396f4ced0bSchristos};
2406f4ced0bSchristos
2416f4ced0bSchristosstatic int
2426f4ced0bSchristosparse_reloc (const char **strp)
2436f4ced0bSchristos{
2446f4ced0bSchristos    const char *str = *strp;
2456f4ced0bSchristos    enum or1k_rclass cls = RCLASS_DIRECT;
2466f4ced0bSchristos    enum or1k_rtype typ;
2476f4ced0bSchristos
2486f4ced0bSchristos    if (strncasecmp (str, "got(", 4) == 0)
2496f4ced0bSchristos      {
2506f4ced0bSchristos	*strp = str + 4;
2516f4ced0bSchristos	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
2526f4ced0bSchristos      }
2536f4ced0bSchristos    if (strncasecmp (str, "gotpo(", 6) == 0)
2546f4ced0bSchristos      {
2556f4ced0bSchristos	*strp = str + 6;
2566f4ced0bSchristos	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
2576f4ced0bSchristos      }
2586f4ced0bSchristos    if (strncasecmp (str, "gottppo(", 8) == 0)
2596f4ced0bSchristos      {
2606f4ced0bSchristos	*strp = str + 8;
2616f4ced0bSchristos	return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
2626f4ced0bSchristos      }
2636f4ced0bSchristos
2646f4ced0bSchristos    if (strncasecmp (str, "gotpc", 5) == 0)
2656f4ced0bSchristos      {
2666f4ced0bSchristos	str += 5;
2676f4ced0bSchristos	cls = RCLASS_GOTPC;
2686f4ced0bSchristos      }
2696f4ced0bSchristos    else if (strncasecmp (str, "gotoff", 6) == 0)
2706f4ced0bSchristos      {
2716f4ced0bSchristos	str += 6;
2726f4ced0bSchristos	cls = RCLASS_GOTOFF;
2736f4ced0bSchristos      }
2746f4ced0bSchristos    else if (strncasecmp (str, "tlsgd", 5) == 0)
2756f4ced0bSchristos      {
2766f4ced0bSchristos	str += 5;
2776f4ced0bSchristos	cls = RCLASS_TLSGD;
2786f4ced0bSchristos      }
2796f4ced0bSchristos    else if (strncasecmp (str, "tlsldm", 6) == 0)
2806f4ced0bSchristos      {
2816f4ced0bSchristos	str += 6;
2826f4ced0bSchristos	cls = RCLASS_TLSLDM;
2836f4ced0bSchristos      }
2846f4ced0bSchristos    else if (strncasecmp (str, "dtpoff", 6) == 0)
2856f4ced0bSchristos      {
2866f4ced0bSchristos	str += 6;
2876f4ced0bSchristos	cls = RCLASS_DTPOFF;
2886f4ced0bSchristos      }
2896f4ced0bSchristos    else if (strncasecmp (str, "gottpoff", 8) == 0)
2906f4ced0bSchristos      {
2916f4ced0bSchristos	str += 8;
2926f4ced0bSchristos	cls = RCLASS_GOTTPOFF;
2936f4ced0bSchristos      }
2946f4ced0bSchristos    else if (strncasecmp (str, "tpoff", 5) == 0)
2956f4ced0bSchristos      {
2966f4ced0bSchristos	str += 5;
2976f4ced0bSchristos	cls = RCLASS_TPOFF;
2986f4ced0bSchristos      }
299*03f5171aSchristos    else if (strncasecmp (str, "got", 3) == 0)
300*03f5171aSchristos      {
301*03f5171aSchristos	str += 3;
302*03f5171aSchristos	cls = RCLASS_GOT;
303*03f5171aSchristos      }
3046f4ced0bSchristos
3056f4ced0bSchristos    if (strncasecmp (str, "hi(", 3) == 0)
3066f4ced0bSchristos      {
3076f4ced0bSchristos	str += 3;
3086f4ced0bSchristos	typ = RTYPE_HI;
3096f4ced0bSchristos      }
3106f4ced0bSchristos    else if (strncasecmp (str, "lo(", 3) == 0)
3116f4ced0bSchristos      {
3126f4ced0bSchristos	str += 3;
3136f4ced0bSchristos	typ = RTYPE_LO;
3146f4ced0bSchristos      }
3156f4ced0bSchristos    else if (strncasecmp (str, "ha(", 3) == 0)
3166f4ced0bSchristos      {
3176f4ced0bSchristos	str += 3;
3186f4ced0bSchristos	typ = RTYPE_AHI;
3196f4ced0bSchristos      }
3206f4ced0bSchristos    else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
3216f4ced0bSchristos      {
3226f4ced0bSchristos	str += 3;
3236f4ced0bSchristos	typ = RTYPE_PO;
3246f4ced0bSchristos      }
3256f4ced0bSchristos    else
3266f4ced0bSchristos      return -1;
3276f4ced0bSchristos
3286f4ced0bSchristos    *strp = str;
3296f4ced0bSchristos    return (cls << RCLASS_SHIFT) | typ;
3306f4ced0bSchristos}
3316f4ced0bSchristos
3326f4ced0bSchristosstatic const char *
3336f4ced0bSchristosparse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
3346f4ced0bSchristos	     long *valuep, int splitp)
335a45653d1Smatt{
336a45653d1Smatt  const char *errmsg;
337a45653d1Smatt  enum cgen_parse_operand_result result_type;
3386f4ced0bSchristos  bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
3396f4ced0bSchristos  enum or1k_rtype reloc_type;
3406f4ced0bSchristos  int reloc_code;
3416f4ced0bSchristos  bfd_vma ret;
342a45653d1Smatt
343a45653d1Smatt  if (**strp == '#')
344a45653d1Smatt    ++*strp;
345a45653d1Smatt
3466f4ced0bSchristos  reloc_code = parse_reloc (strp);
3476f4ced0bSchristos  reloc_type = reloc_code & RTYPE_MASK;
3486f4ced0bSchristos  if (reloc_code >= 0)
3496f4ced0bSchristos    {
3506f4ced0bSchristos      enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
3516f4ced0bSchristos      if (splitp)
3526f4ced0bSchristos	{
3536f4ced0bSchristos	  if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
3546f4ced0bSchristos	      && reloc_class != RCLASS_GOT)
3556f4ced0bSchristos	    /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
3566f4ced0bSchristos	    reloc_type |= 1;
3576f4ced0bSchristos	  else
3586f4ced0bSchristos	    return INVALID_STORE_RELOC;
3596f4ced0bSchristos	}
3606f4ced0bSchristos      reloc = or1k_imm16_relocs[reloc_class][reloc_type];
3616f4ced0bSchristos    }
3626f4ced0bSchristos
3636f4ced0bSchristos  if (reloc != BFD_RELOC_UNUSED)
364a45653d1Smatt    {
365a45653d1Smatt      bfd_vma value;
366a45653d1Smatt
3676f4ced0bSchristos      errmsg = cgen_parse_address (cd, strp, opindex, reloc,
368a45653d1Smatt				   &result_type, &value);
369a45653d1Smatt      if (**strp != ')')
370a45653d1Smatt	errmsg = MISSING_CLOSING_PARENTHESIS;
371a45653d1Smatt      ++*strp;
372a45653d1Smatt
373a45653d1Smatt      ret = value;
374a45653d1Smatt
3756f4ced0bSchristos      if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
3766f4ced0bSchristos	switch (reloc_type)
377a45653d1Smatt	  {
3786f4ced0bSchristos	  case RTYPE_AHI:
3796f4ced0bSchristos	    ret += 0x8000;
3806f4ced0bSchristos	    /* FALLTHRU */
3816f4ced0bSchristos	  case RTYPE_HI:
382a45653d1Smatt	    ret >>= 16;
3836f4ced0bSchristos	    /* FALLTHRU */
3846f4ced0bSchristos	  case RTYPE_LO:
3856f4ced0bSchristos	  case RTYPE_SLO:
386a45653d1Smatt	    ret &= 0xffff;
387a45653d1Smatt	    ret = (ret ^ 0x8000) - 0x8000;
3886f4ced0bSchristos	    break;
3896f4ced0bSchristos	  case RTYPE_PO:
3906f4ced0bSchristos	  case RTYPE_SPO:
3916f4ced0bSchristos	    ret &= 0x1fff;
3926f4ced0bSchristos	    break;
3936f4ced0bSchristos	  default:
3946f4ced0bSchristos	    errmsg = INVALID_RELOC_TYPE;
395a45653d1Smatt	  }
396a45653d1Smatt    }
397a45653d1Smatt  else
398a45653d1Smatt    {
399a45653d1Smatt      long value;
400a45653d1Smatt      errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
401a45653d1Smatt      ret = value;
402a45653d1Smatt    }
403a45653d1Smatt
404a45653d1Smatt  if (errmsg == NULL)
405a45653d1Smatt    *valuep = ret;
406a45653d1Smatt
407a45653d1Smatt  return errmsg;
408a45653d1Smatt}
409a45653d1Smatt
410a45653d1Smattstatic const char *
4116f4ced0bSchristosparse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
412a45653d1Smatt{
4136f4ced0bSchristos  return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
4146f4ced0bSchristos}
415a45653d1Smatt
4166f4ced0bSchristosstatic const char *
4176f4ced0bSchristosparse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
4186f4ced0bSchristos		    long *valuep)
4196f4ced0bSchristos{
4206f4ced0bSchristos  return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
4216f4ced0bSchristos}
4226f4ced0bSchristos
4236f4ced0bSchristosstatic const char *
4246f4ced0bSchristosparse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
4256f4ced0bSchristos	      unsigned long *valuep)
4266f4ced0bSchristos{
4276f4ced0bSchristos  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
428a45653d1Smatt  if (errmsg == NULL)
429a45653d1Smatt    *valuep &= 0xffff;
430a45653d1Smatt  return errmsg;
431a45653d1Smatt}
432a45653d1Smatt
4336f4ced0bSchristosstatic const char *
4346f4ced0bSchristosparse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
4356f4ced0bSchristos		    unsigned long *valuep)
4366f4ced0bSchristos{
4376f4ced0bSchristos  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
4386f4ced0bSchristos  if (errmsg == NULL)
4396f4ced0bSchristos    *valuep &= 0xffff;
4406f4ced0bSchristos  return errmsg;
4416f4ced0bSchristos}
4426f4ced0bSchristos
4436f4ced0bSchristos/* Parse register pairs with syntax rA,rB to a flag + rA value.  */
4446f4ced0bSchristos
4456f4ced0bSchristosstatic const char *
4466f4ced0bSchristosparse_regpair (CGEN_CPU_DESC cd, const char **strp,
4476f4ced0bSchristos	       int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
4486f4ced0bSchristos{
4496f4ced0bSchristos  long reg1_index;
4506f4ced0bSchristos  long reg2_index;
4516f4ced0bSchristos  const char *errmsg;
4526f4ced0bSchristos
4536f4ced0bSchristos  /* The first part should just be a register.  */
4546f4ced0bSchristos  errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
4556f4ced0bSchristos			       &reg1_index);
4566f4ced0bSchristos
4576f4ced0bSchristos  /* If that worked skip the comma separator.  */
4586f4ced0bSchristos  if (errmsg == NULL)
4596f4ced0bSchristos    {
4606f4ced0bSchristos      if (**strp == ',')
4616f4ced0bSchristos	++*strp;
4626f4ced0bSchristos      else
4636f4ced0bSchristos	errmsg = "Unexpected character, expected ','";
4646f4ced0bSchristos    }
4656f4ced0bSchristos
4666f4ced0bSchristos  /* If that worked the next part is just another register.  */
4676f4ced0bSchristos  if (errmsg == NULL)
4686f4ced0bSchristos    errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
4696f4ced0bSchristos				 &reg2_index);
4706f4ced0bSchristos
4716f4ced0bSchristos  /* Validate the register pair is valid and create the output value.  */
4726f4ced0bSchristos  if (errmsg == NULL)
4736f4ced0bSchristos    {
4746f4ced0bSchristos      int regoffset = reg2_index - reg1_index;
4756f4ced0bSchristos
4766f4ced0bSchristos      if (regoffset == 1 || regoffset == 2)
4776f4ced0bSchristos	{
4786f4ced0bSchristos	  unsigned short offsetmask;
4796f4ced0bSchristos	  unsigned short value;
4806f4ced0bSchristos
4816f4ced0bSchristos	  offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
4826f4ced0bSchristos	  value = offsetmask | reg1_index;
4836f4ced0bSchristos
4846f4ced0bSchristos	  *valuep = value;
4856f4ced0bSchristos	}
4866f4ced0bSchristos      else
4876f4ced0bSchristos	errmsg = "Invalid register pair, offset not 1 or 2.";
4886f4ced0bSchristos    }
4896f4ced0bSchristos
4906f4ced0bSchristos  return errmsg;
4916f4ced0bSchristos}
4926f4ced0bSchristos
4936f4ced0bSchristos/* -- */
4946f4ced0bSchristos
4956f4ced0bSchristos/* -- dis.c */
4966f4ced0bSchristos
4976f4ced0bSchristosstatic void
4986f4ced0bSchristosprint_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
4996f4ced0bSchristos	       void * dis_info,
5006f4ced0bSchristos	       long value,
5016f4ced0bSchristos	       unsigned int attrs ATTRIBUTE_UNUSED,
5026f4ced0bSchristos	       bfd_vma pc ATTRIBUTE_UNUSED,
5036f4ced0bSchristos	       int length ATTRIBUTE_UNUSED)
5046f4ced0bSchristos{
5056f4ced0bSchristos  disassemble_info *info = dis_info;
5066f4ced0bSchristos  char reg1_index;
5076f4ced0bSchristos  char reg2_index;
5086f4ced0bSchristos
5096f4ced0bSchristos  reg1_index = value & 0x1f;
5106f4ced0bSchristos  reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
5116f4ced0bSchristos
5126f4ced0bSchristos  (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
5136f4ced0bSchristos}
5146f4ced0bSchristos
515a45653d1Smatt/* -- */
516a45653d1Smatt
517a45653d1Smatt/* -- ibd.h */
518a45653d1Smatt
519a45653d1Smatt/* -- */
520