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 ®1_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 ®2_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