xref: /netbsd-src/external/gpl3/gdb/dist/cpu/or1k.opc (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
1837edd6bSchristos/* OpenRISC 1000 opcode support.  -*- C -*-
2837edd6bSchristos   Copyright 2000-2014 Free Software Foundation, Inc.
3837edd6bSchristos
4837edd6bSchristos   Originally ontributed for OR32 by Red Hat Inc;
5837edd6bSchristos
6837edd6bSchristos   This file is part of the GNU Binutils.
7837edd6bSchristos
8837edd6bSchristos   This program is free software; you can redistribute it and/or modify
9837edd6bSchristos   it under the terms of the GNU General Public License as published by
10837edd6bSchristos   the Free Software Foundation; either version 3 of the License, or
11837edd6bSchristos   (at your option) any later version.
12837edd6bSchristos
13837edd6bSchristos   This program is distributed in the hope that it will be useful,
14837edd6bSchristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
15837edd6bSchristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16837edd6bSchristos   GNU General Public License for more details.
17837edd6bSchristos
18837edd6bSchristos   You should have received a copy of the GNU General Public License
19837edd6bSchristos   along with this program; if not, see <http://www.gnu.org/licenses/>. */
20837edd6bSchristos
21837edd6bSchristos/* This file is an addendum to or1k.cpu.  Heavy use of C code isn't
22837edd6bSchristos   appropriate in .cpu files, so it resides here.  This especially applies
23837edd6bSchristos   to assembly/disassembly where parsing/printing can be quite involved.
24837edd6bSchristos   Such things aren't really part of the specification of the cpu, per se,
25837edd6bSchristos   so .cpu files provide the general framework and .opc files handle the
26837edd6bSchristos   nitty-gritty details as necessary.
27837edd6bSchristos
28837edd6bSchristos   Each section is delimited with start and end markers.
29837edd6bSchristos
30837edd6bSchristos   <arch>-opc.h additions use: "-- opc.h"
31837edd6bSchristos   <arch>-opc.c additions use: "-- opc.c"
32837edd6bSchristos   <arch>-asm.c additions use: "-- asm.c"
33837edd6bSchristos   <arch>-dis.c additions use: "-- dis.c"
34837edd6bSchristos   <arch>-ibd.h additions use: "-- ibd.h"  */
35837edd6bSchristos
36837edd6bSchristos/* -- opc.h */
37837edd6bSchristos
38837edd6bSchristos#undef  CGEN_DIS_HASH_SIZE
39837edd6bSchristos#define CGEN_DIS_HASH_SIZE 256
40837edd6bSchristos#undef  CGEN_DIS_HASH
41837edd6bSchristos#define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
42837edd6bSchristos
438dffb485Schristos/* Check applicability of instructions against machines.  */
448dffb485Schristos#define CGEN_VALIDATE_INSN_SUPPORTED
458dffb485Schristos
468dffb485Schristosextern int or1k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
478dffb485Schristos
48837edd6bSchristos/* -- */
49837edd6bSchristos
50837edd6bSchristos/* -- opc.c */
518dffb485Schristos
528dffb485Schristos/* Special check to ensure that instruction exists for given machine.  */
538dffb485Schristos
548dffb485Schristosint
558dffb485Schristosor1k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
568dffb485Schristos{
578dffb485Schristos  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
588dffb485Schristos
598dffb485Schristos  /* No mach attribute?  Assume it's supported for all machs.  */
608dffb485Schristos  if (machs == 0)
618dffb485Schristos    return 1;
628dffb485Schristos
638dffb485Schristos  return ((machs & cd->machs) != 0);
648dffb485Schristos}
658dffb485Schristos
66837edd6bSchristos/* -- */
67837edd6bSchristos
68837edd6bSchristos/* -- asm.c */
69837edd6bSchristos
70837edd6bSchristosstatic const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
714559860eSchristosstatic const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
724559860eSchristosstatic const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
73837edd6bSchristos
74837edd6bSchristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS
75837edd6bSchristos
76837edd6bSchristosstatic const char *
77837edd6bSchristosparse_disp26 (CGEN_CPU_DESC cd,
78837edd6bSchristos	      const char ** strp,
79837edd6bSchristos	      int opindex,
804559860eSchristos	      int opinfo ATTRIBUTE_UNUSED,
81837edd6bSchristos	      enum cgen_parse_operand_result * resultp,
82837edd6bSchristos	      bfd_vma * valuep)
83837edd6bSchristos{
844559860eSchristos  const char *str = *strp;
85837edd6bSchristos  const char *errmsg = NULL;
864559860eSchristos  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
87837edd6bSchristos
884559860eSchristos  if (strncasecmp (str, "plta(", 5) == 0)
89837edd6bSchristos    {
904559860eSchristos      *strp = str + 5;
914559860eSchristos      reloc = BFD_RELOC_OR1K_PLTA26;
92837edd6bSchristos    }
934559860eSchristos  else if (strncasecmp (str, "plt(", 4) == 0)
944559860eSchristos    {
954559860eSchristos      *strp = str + 4;
964559860eSchristos      reloc = BFD_RELOC_OR1K_PLT26;
974559860eSchristos    }
984559860eSchristos
994559860eSchristos  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
1004559860eSchristos
1014559860eSchristos  if (reloc != BFD_RELOC_OR1K_REL_26)
1024559860eSchristos    {
1034559860eSchristos      if (**strp != ')')
1044559860eSchristos	errmsg = MISSING_CLOSING_PARENTHESIS;
1054559860eSchristos      else
1064559860eSchristos	++*strp;
1074559860eSchristos    }
1084559860eSchristos
1094559860eSchristos  return errmsg;
110837edd6bSchristos}
111837edd6bSchristos
112837edd6bSchristosstatic const char *
1134559860eSchristosparse_disp21 (CGEN_CPU_DESC cd,
1144559860eSchristos	      const char ** strp,
1154559860eSchristos	      int opindex,
1164559860eSchristos	      int opinfo ATTRIBUTE_UNUSED,
1174559860eSchristos	      enum cgen_parse_operand_result * resultp,
1184559860eSchristos	      bfd_vma * valuep)
1194559860eSchristos{
1204559860eSchristos  const char *str = *strp;
1214559860eSchristos  const char *errmsg = NULL;
1224559860eSchristos  bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
1234559860eSchristos
1244559860eSchristos  if (strncasecmp (str, "got(", 4) == 0)
1254559860eSchristos    {
1264559860eSchristos      *strp = str + 4;
1274559860eSchristos      reloc = BFD_RELOC_OR1K_GOT_PG21;
1284559860eSchristos    }
1294559860eSchristos  else if (strncasecmp (str, "tlsgd(", 6) == 0)
1304559860eSchristos    {
1314559860eSchristos      *strp = str + 6;
1324559860eSchristos      reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
1334559860eSchristos    }
1344559860eSchristos  else if (strncasecmp (str, "tlsldm(", 7) == 0)
1354559860eSchristos    {
1364559860eSchristos      *strp = str + 7;
1374559860eSchristos      reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
1384559860eSchristos    }
1394559860eSchristos  else if (strncasecmp (str, "gottp(", 6) == 0)
1404559860eSchristos    {
1414559860eSchristos      *strp = str + 6;
1424559860eSchristos      reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
1434559860eSchristos    }
1444559860eSchristos
1454559860eSchristos  errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
1464559860eSchristos
1474559860eSchristos  if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
1484559860eSchristos    {
1494559860eSchristos      if (**strp != ')')
1504559860eSchristos	errmsg = MISSING_CLOSING_PARENTHESIS;
1514559860eSchristos      else
1524559860eSchristos	++*strp;
1534559860eSchristos    }
1544559860eSchristos
1554559860eSchristos  return errmsg;
1564559860eSchristos}
1574559860eSchristos
1584559860eSchristosenum or1k_rclass
1594559860eSchristos{
1604559860eSchristos  RCLASS_DIRECT   = 0,
1614559860eSchristos  RCLASS_GOT      = 1,
1624559860eSchristos  RCLASS_GOTPC    = 2,
1634559860eSchristos  RCLASS_GOTOFF   = 3,
1644559860eSchristos  RCLASS_TLSGD    = 4,
1654559860eSchristos  RCLASS_TLSLDM   = 5,
1664559860eSchristos  RCLASS_DTPOFF   = 6,
1674559860eSchristos  RCLASS_GOTTPOFF = 7,
1684559860eSchristos  RCLASS_TPOFF    = 8,
1694559860eSchristos};
1704559860eSchristos
1714559860eSchristosenum or1k_rtype
1724559860eSchristos{
1734559860eSchristos  RTYPE_LO = 0,
1744559860eSchristos  RTYPE_SLO = 1,
1754559860eSchristos  RTYPE_PO = 2,
1764559860eSchristos  RTYPE_SPO = 3,
1774559860eSchristos  RTYPE_HI = 4,
1784559860eSchristos  RTYPE_AHI = 5,
1794559860eSchristos};
1804559860eSchristos
1814559860eSchristos#define RCLASS_SHIFT 3
1824559860eSchristos#define RTYPE_MASK   7
1834559860eSchristos
1844559860eSchristosstatic const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
1854559860eSchristos  { BFD_RELOC_LO16,
1864559860eSchristos    BFD_RELOC_OR1K_SLO16,
1874559860eSchristos    BFD_RELOC_OR1K_LO13,
1884559860eSchristos    BFD_RELOC_OR1K_SLO13,
1894559860eSchristos    BFD_RELOC_HI16,
1904559860eSchristos    BFD_RELOC_HI16_S, },
1914559860eSchristos  { BFD_RELOC_OR1K_GOT16,
1924559860eSchristos    BFD_RELOC_UNUSED,
1934559860eSchristos    BFD_RELOC_OR1K_GOT_LO13,
1944559860eSchristos    BFD_RELOC_UNUSED,
1954559860eSchristos    BFD_RELOC_UNUSED,
196*4b169a6bSchristos    BFD_RELOC_OR1K_GOT_AHI16 },
1974559860eSchristos  { BFD_RELOC_OR1K_GOTPC_LO16,
1984559860eSchristos    BFD_RELOC_UNUSED,
1994559860eSchristos    BFD_RELOC_UNUSED,
2004559860eSchristos    BFD_RELOC_UNUSED,
2014559860eSchristos    BFD_RELOC_OR1K_GOTPC_HI16,
2024559860eSchristos    BFD_RELOC_UNUSED },
2034559860eSchristos  { BFD_RELOC_LO16_GOTOFF,
2044559860eSchristos    BFD_RELOC_OR1K_GOTOFF_SLO16,
2054559860eSchristos    BFD_RELOC_UNUSED,
2064559860eSchristos    BFD_RELOC_UNUSED,
2074559860eSchristos    BFD_RELOC_HI16_GOTOFF,
2084559860eSchristos    BFD_RELOC_HI16_S_GOTOFF },
2094559860eSchristos  { BFD_RELOC_OR1K_TLS_GD_LO16,
2104559860eSchristos    BFD_RELOC_UNUSED,
2114559860eSchristos    BFD_RELOC_OR1K_TLS_GD_LO13,
2124559860eSchristos    BFD_RELOC_UNUSED,
2134559860eSchristos    BFD_RELOC_OR1K_TLS_GD_HI16,
2144559860eSchristos    BFD_RELOC_UNUSED },
2154559860eSchristos  { BFD_RELOC_OR1K_TLS_LDM_LO16,
2164559860eSchristos    BFD_RELOC_UNUSED,
2174559860eSchristos    BFD_RELOC_OR1K_TLS_LDM_LO13,
2184559860eSchristos    BFD_RELOC_UNUSED,
2194559860eSchristos    BFD_RELOC_OR1K_TLS_LDM_HI16,
2204559860eSchristos    BFD_RELOC_UNUSED },
2214559860eSchristos  { BFD_RELOC_OR1K_TLS_LDO_LO16,
2224559860eSchristos    BFD_RELOC_UNUSED,
2234559860eSchristos    BFD_RELOC_UNUSED,
2244559860eSchristos    BFD_RELOC_UNUSED,
2254559860eSchristos    BFD_RELOC_OR1K_TLS_LDO_HI16,
2264559860eSchristos    BFD_RELOC_UNUSED },
2274559860eSchristos  { BFD_RELOC_OR1K_TLS_IE_LO16,
2284559860eSchristos    BFD_RELOC_UNUSED,
2294559860eSchristos    BFD_RELOC_OR1K_TLS_IE_LO13,
2304559860eSchristos    BFD_RELOC_UNUSED,
2314559860eSchristos    BFD_RELOC_OR1K_TLS_IE_HI16,
2324559860eSchristos    BFD_RELOC_OR1K_TLS_IE_AHI16 },
2334559860eSchristos  { BFD_RELOC_OR1K_TLS_LE_LO16,
2344559860eSchristos    BFD_RELOC_OR1K_TLS_LE_SLO16,
2354559860eSchristos    BFD_RELOC_UNUSED,
2364559860eSchristos    BFD_RELOC_UNUSED,
2374559860eSchristos    BFD_RELOC_OR1K_TLS_LE_HI16,
2384559860eSchristos    BFD_RELOC_OR1K_TLS_LE_AHI16 },
2394559860eSchristos};
2404559860eSchristos
2414559860eSchristosstatic int
2424559860eSchristosparse_reloc (const char **strp)
2434559860eSchristos{
2444559860eSchristos    const char *str = *strp;
2454559860eSchristos    enum or1k_rclass cls = RCLASS_DIRECT;
2464559860eSchristos    enum or1k_rtype typ;
2474559860eSchristos
2484559860eSchristos    if (strncasecmp (str, "got(", 4) == 0)
2494559860eSchristos      {
2504559860eSchristos	*strp = str + 4;
2514559860eSchristos	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
2524559860eSchristos      }
2534559860eSchristos    if (strncasecmp (str, "gotpo(", 6) == 0)
2544559860eSchristos      {
2554559860eSchristos	*strp = str + 6;
2564559860eSchristos	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
2574559860eSchristos      }
2584559860eSchristos    if (strncasecmp (str, "gottppo(", 8) == 0)
2594559860eSchristos      {
2604559860eSchristos	*strp = str + 8;
2614559860eSchristos	return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
2624559860eSchristos      }
2634559860eSchristos
2644559860eSchristos    if (strncasecmp (str, "gotpc", 5) == 0)
2654559860eSchristos      {
2664559860eSchristos	str += 5;
2674559860eSchristos	cls = RCLASS_GOTPC;
2684559860eSchristos      }
2694559860eSchristos    else if (strncasecmp (str, "gotoff", 6) == 0)
2704559860eSchristos      {
2714559860eSchristos	str += 6;
2724559860eSchristos	cls = RCLASS_GOTOFF;
2734559860eSchristos      }
2744559860eSchristos    else if (strncasecmp (str, "tlsgd", 5) == 0)
2754559860eSchristos      {
2764559860eSchristos	str += 5;
2774559860eSchristos	cls = RCLASS_TLSGD;
2784559860eSchristos      }
2794559860eSchristos    else if (strncasecmp (str, "tlsldm", 6) == 0)
2804559860eSchristos      {
2814559860eSchristos	str += 6;
2824559860eSchristos	cls = RCLASS_TLSLDM;
2834559860eSchristos      }
2844559860eSchristos    else if (strncasecmp (str, "dtpoff", 6) == 0)
2854559860eSchristos      {
2864559860eSchristos	str += 6;
2874559860eSchristos	cls = RCLASS_DTPOFF;
2884559860eSchristos      }
2894559860eSchristos    else if (strncasecmp (str, "gottpoff", 8) == 0)
2904559860eSchristos      {
2914559860eSchristos	str += 8;
2924559860eSchristos	cls = RCLASS_GOTTPOFF;
2934559860eSchristos      }
2944559860eSchristos    else if (strncasecmp (str, "tpoff", 5) == 0)
2954559860eSchristos      {
2964559860eSchristos	str += 5;
2974559860eSchristos	cls = RCLASS_TPOFF;
2984559860eSchristos      }
299*4b169a6bSchristos    else if (strncasecmp (str, "got", 3) == 0)
300*4b169a6bSchristos      {
301*4b169a6bSchristos	str += 3;
302*4b169a6bSchristos	cls = RCLASS_GOT;
303*4b169a6bSchristos      }
3044559860eSchristos
3054559860eSchristos    if (strncasecmp (str, "hi(", 3) == 0)
3064559860eSchristos      {
3074559860eSchristos	str += 3;
3084559860eSchristos	typ = RTYPE_HI;
3094559860eSchristos      }
3104559860eSchristos    else if (strncasecmp (str, "lo(", 3) == 0)
3114559860eSchristos      {
3124559860eSchristos	str += 3;
3134559860eSchristos	typ = RTYPE_LO;
3144559860eSchristos      }
3154559860eSchristos    else if (strncasecmp (str, "ha(", 3) == 0)
3164559860eSchristos      {
3174559860eSchristos	str += 3;
3184559860eSchristos	typ = RTYPE_AHI;
3194559860eSchristos      }
3204559860eSchristos    else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
3214559860eSchristos      {
3224559860eSchristos	str += 3;
3234559860eSchristos	typ = RTYPE_PO;
3244559860eSchristos      }
3254559860eSchristos    else
3264559860eSchristos      return -1;
3274559860eSchristos
3284559860eSchristos    *strp = str;
3294559860eSchristos    return (cls << RCLASS_SHIFT) | typ;
3304559860eSchristos}
3314559860eSchristos
3324559860eSchristosstatic const char *
3334559860eSchristosparse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
3344559860eSchristos	     long *valuep, int splitp)
335837edd6bSchristos{
336837edd6bSchristos  const char *errmsg;
337837edd6bSchristos  enum cgen_parse_operand_result result_type;
3384559860eSchristos  bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
3394559860eSchristos  enum or1k_rtype reloc_type;
3404559860eSchristos  int reloc_code;
3414559860eSchristos  bfd_vma ret;
342837edd6bSchristos
343837edd6bSchristos  if (**strp == '#')
344837edd6bSchristos    ++*strp;
345837edd6bSchristos
3464559860eSchristos  reloc_code = parse_reloc (strp);
3474559860eSchristos  reloc_type = reloc_code & RTYPE_MASK;
3484559860eSchristos  if (reloc_code >= 0)
3494559860eSchristos    {
3504559860eSchristos      enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
3514559860eSchristos      if (splitp)
3524559860eSchristos	{
3534559860eSchristos	  if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
3544559860eSchristos	      && reloc_class != RCLASS_GOT)
3554559860eSchristos	    /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
3564559860eSchristos	    reloc_type |= 1;
3574559860eSchristos	  else
3584559860eSchristos	    return INVALID_STORE_RELOC;
3594559860eSchristos	}
3604559860eSchristos      reloc = or1k_imm16_relocs[reloc_class][reloc_type];
3614559860eSchristos    }
3624559860eSchristos
3634559860eSchristos  if (reloc != BFD_RELOC_UNUSED)
364837edd6bSchristos    {
365837edd6bSchristos      bfd_vma value;
366837edd6bSchristos
3674559860eSchristos      errmsg = cgen_parse_address (cd, strp, opindex, reloc,
368837edd6bSchristos				   &result_type, &value);
369837edd6bSchristos      if (**strp != ')')
370837edd6bSchristos	errmsg = MISSING_CLOSING_PARENTHESIS;
371837edd6bSchristos      ++*strp;
372837edd6bSchristos
373837edd6bSchristos      ret = value;
374837edd6bSchristos
3754559860eSchristos      if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
3764559860eSchristos	switch (reloc_type)
377837edd6bSchristos	  {
3784559860eSchristos	  case RTYPE_AHI:
3794559860eSchristos	    ret += 0x8000;
3804559860eSchristos	    /* FALLTHRU */
3814559860eSchristos	  case RTYPE_HI:
382837edd6bSchristos	    ret >>= 16;
3834559860eSchristos	    /* FALLTHRU */
3844559860eSchristos	  case RTYPE_LO:
3854559860eSchristos	  case RTYPE_SLO:
386837edd6bSchristos	    ret &= 0xffff;
387837edd6bSchristos	    ret = (ret ^ 0x8000) - 0x8000;
3884559860eSchristos	    break;
3894559860eSchristos	  case RTYPE_PO:
3904559860eSchristos	  case RTYPE_SPO:
3914559860eSchristos	    ret &= 0x1fff;
3924559860eSchristos	    break;
3934559860eSchristos	  default:
3944559860eSchristos	    errmsg = INVALID_RELOC_TYPE;
395837edd6bSchristos	  }
396837edd6bSchristos    }
397837edd6bSchristos  else
398837edd6bSchristos    {
399837edd6bSchristos      long value;
400837edd6bSchristos      errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
401837edd6bSchristos      ret = value;
402837edd6bSchristos    }
403837edd6bSchristos
404837edd6bSchristos  if (errmsg == NULL)
405837edd6bSchristos    *valuep = ret;
406837edd6bSchristos
407837edd6bSchristos  return errmsg;
408837edd6bSchristos}
409837edd6bSchristos
410837edd6bSchristosstatic const char *
4114559860eSchristosparse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
412837edd6bSchristos{
4134559860eSchristos  return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
4144559860eSchristos}
415837edd6bSchristos
4164559860eSchristosstatic const char *
4174559860eSchristosparse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
4184559860eSchristos		    long *valuep)
4194559860eSchristos{
4204559860eSchristos  return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
4214559860eSchristos}
4224559860eSchristos
4234559860eSchristosstatic const char *
4244559860eSchristosparse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
4254559860eSchristos	      unsigned long *valuep)
4264559860eSchristos{
4274559860eSchristos  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
4284559860eSchristos  if (errmsg == NULL)
4294559860eSchristos    *valuep &= 0xffff;
4304559860eSchristos  return errmsg;
4314559860eSchristos}
4324559860eSchristos
4334559860eSchristosstatic const char *
4344559860eSchristosparse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
4354559860eSchristos		    unsigned long *valuep)
4364559860eSchristos{
4374559860eSchristos  const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
438837edd6bSchristos  if (errmsg == NULL)
439837edd6bSchristos    *valuep &= 0xffff;
440837edd6bSchristos  return errmsg;
441837edd6bSchristos}
442837edd6bSchristos
4438dffb485Schristos/* Parse register pairs with syntax rA,rB to a flag + rA value.  */
4448dffb485Schristos
4458dffb485Schristosstatic const char *
4468dffb485Schristosparse_regpair (CGEN_CPU_DESC cd, const char **strp,
4478dffb485Schristos	       int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
4488dffb485Schristos{
4498dffb485Schristos  long reg1_index;
4508dffb485Schristos  long reg2_index;
4518dffb485Schristos  const char *errmsg;
4528dffb485Schristos
4538dffb485Schristos  /* The first part should just be a register.  */
4548dffb485Schristos  errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
4558dffb485Schristos			       &reg1_index);
4568dffb485Schristos
4578dffb485Schristos  /* If that worked skip the comma separator.  */
4588dffb485Schristos  if (errmsg == NULL)
4598dffb485Schristos    {
4608dffb485Schristos      if (**strp == ',')
4618dffb485Schristos	++*strp;
4628dffb485Schristos      else
4638dffb485Schristos	errmsg = "Unexpected character, expected ','";
4648dffb485Schristos    }
4658dffb485Schristos
4668dffb485Schristos  /* If that worked the next part is just another register.  */
4678dffb485Schristos  if (errmsg == NULL)
4688dffb485Schristos    errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
4698dffb485Schristos				 &reg2_index);
4708dffb485Schristos
4718dffb485Schristos  /* Validate the register pair is valid and create the output value.  */
4728dffb485Schristos  if (errmsg == NULL)
4738dffb485Schristos    {
4748dffb485Schristos      int regoffset = reg2_index - reg1_index;
4758dffb485Schristos
4768dffb485Schristos      if (regoffset == 1 || regoffset == 2)
4778dffb485Schristos	{
4788dffb485Schristos	  unsigned short offsetmask;
4798dffb485Schristos	  unsigned short value;
4808dffb485Schristos
4818dffb485Schristos	  offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
4828dffb485Schristos	  value = offsetmask | reg1_index;
4838dffb485Schristos
4848dffb485Schristos	  *valuep = value;
4858dffb485Schristos	}
4868dffb485Schristos      else
4878dffb485Schristos	errmsg = "Invalid register pair, offset not 1 or 2.";
4888dffb485Schristos    }
4898dffb485Schristos
4908dffb485Schristos  return errmsg;
4918dffb485Schristos}
4928dffb485Schristos
4938dffb485Schristos/* -- */
4948dffb485Schristos
4958dffb485Schristos/* -- dis.c */
4968dffb485Schristos
4978dffb485Schristosstatic void
4988dffb485Schristosprint_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
4998dffb485Schristos	       void * dis_info,
5008dffb485Schristos	       long value,
5018dffb485Schristos	       unsigned int attrs ATTRIBUTE_UNUSED,
5028dffb485Schristos	       bfd_vma pc ATTRIBUTE_UNUSED,
5038dffb485Schristos	       int length ATTRIBUTE_UNUSED)
5048dffb485Schristos{
5058dffb485Schristos  disassemble_info *info = dis_info;
5068dffb485Schristos  char reg1_index;
5078dffb485Schristos  char reg2_index;
5088dffb485Schristos
5098dffb485Schristos  reg1_index = value & 0x1f;
5108dffb485Schristos  reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
5118dffb485Schristos
5128dffb485Schristos  (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
5138dffb485Schristos}
5148dffb485Schristos
515837edd6bSchristos/* -- */
516837edd6bSchristos
517837edd6bSchristos/* -- ibd.h */
518837edd6bSchristos
519837edd6bSchristos/* -- */
520