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