12a6b7db3Sskrll/* IQ2000 opcode support. -*- C -*- 22a6b7db3Sskrll 3*be12b8bcSchristos Copyright 2000, 2001, 2002, 2005, 2007, 2009 Free Software Foundation, Inc. 42a6b7db3Sskrll 52a6b7db3Sskrll Contributed by Red Hat Inc; developed under contract from Fujitsu. 62a6b7db3Sskrll 72a6b7db3Sskrll This file is part of the GNU Binutils. 82a6b7db3Sskrll 92a6b7db3Sskrll This program is free software; you can redistribute it and/or modify 102a6b7db3Sskrll it under the terms of the GNU General Public License as published by 112a6b7db3Sskrll the Free Software Foundation; either version 3 of the License, or 122a6b7db3Sskrll (at your option) any later version. 132a6b7db3Sskrll 142a6b7db3Sskrll This program is distributed in the hope that it will be useful, 152a6b7db3Sskrll but WITHOUT ANY WARRANTY; without even the implied warranty of 162a6b7db3Sskrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 172a6b7db3Sskrll GNU General Public License for more details. 182a6b7db3Sskrll 192a6b7db3Sskrll You should have received a copy of the GNU General Public License 202a6b7db3Sskrll along with this program; if not, write to the Free Software 212a6b7db3Sskrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 222a6b7db3Sskrll MA 02110-1301, USA. */ 232a6b7db3Sskrll 242a6b7db3Sskrll/* This file is an addendum to iq2000.cpu. Heavy use of C code isn't 252a6b7db3Sskrll appropriate in .cpu files, so it resides here. This especially applies 262a6b7db3Sskrll to assembly/disassembly where parsing/printing can be quite involved. 272a6b7db3Sskrll Such things aren't really part of the specification of the cpu, per se, 282a6b7db3Sskrll so .cpu files provide the general framework and .opc files handle the 292a6b7db3Sskrll nitty-gritty details as necessary. 302a6b7db3Sskrll 312a6b7db3Sskrll Each section is delimited with start and end markers. 322a6b7db3Sskrll 332a6b7db3Sskrll <arch>-opc.h additions use: "-- opc.h" 342a6b7db3Sskrll <arch>-opc.c additions use: "-- opc.c" 352a6b7db3Sskrll <arch>-asm.c additions use: "-- asm.c" 362a6b7db3Sskrll <arch>-dis.c additions use: "-- dis.c" 372a6b7db3Sskrll <arch>-ibd.h additions use: "-- ibd.h". */ 382a6b7db3Sskrll 392a6b7db3Sskrll/* -- opc.h */ 402a6b7db3Sskrll 412a6b7db3Sskrll/* Allows reason codes to be output when assembler errors occur. */ 422a6b7db3Sskrll#define CGEN_VERBOSE_ASSEMBLER_ERRORS 432a6b7db3Sskrll 442a6b7db3Sskrll/* Override disassembly hashing - there are variable bits in the top 452a6b7db3Sskrll byte of these instructions. */ 462a6b7db3Sskrll#define CGEN_DIS_HASH_SIZE 8 472a6b7db3Sskrll#define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 6) % CGEN_DIS_HASH_SIZE) 482a6b7db3Sskrll 492a6b7db3Sskrll/* following activates check beyond hashing since some iq2000 and iq10 502a6b7db3Sskrll instructions have same mnemonics but different functionality. */ 512a6b7db3Sskrll#define CGEN_VALIDATE_INSN_SUPPORTED 522a6b7db3Sskrll 532a6b7db3Sskrllextern int iq2000_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *); 542a6b7db3Sskrll 552a6b7db3Sskrll/* -- asm.c */ 562a6b7db3Sskrll 572a6b7db3Sskrll#include "safe-ctype.h" 582a6b7db3Sskrll 592a6b7db3Sskrllstatic const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'"); 602a6b7db3Sskrll 612a6b7db3Sskrll/* Special check to ensure that instruction exists for given machine. */ 622a6b7db3Sskrll 632a6b7db3Sskrllint 642a6b7db3Sskrlliq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 652a6b7db3Sskrll{ 662a6b7db3Sskrll int machs = cd->machs; 672a6b7db3Sskrll 682a6b7db3Sskrll return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0; 692a6b7db3Sskrll} 702a6b7db3Sskrll 712a6b7db3Sskrllstatic int 722a6b7db3Sskrlliq2000_cgen_isa_register (const char **strp) 732a6b7db3Sskrll{ 742a6b7db3Sskrll int len; 752a6b7db3Sskrll int ch1, ch2; 762a6b7db3Sskrll 772a6b7db3Sskrll if (**strp == 'r' || **strp == 'R') 782a6b7db3Sskrll { 792a6b7db3Sskrll len = strlen (*strp); 802a6b7db3Sskrll if (len == 2) 812a6b7db3Sskrll { 822a6b7db3Sskrll ch1 = (*strp)[1]; 832a6b7db3Sskrll if ('0' <= ch1 && ch1 <= '9') 842a6b7db3Sskrll return 1; 852a6b7db3Sskrll } 862a6b7db3Sskrll else if (len == 3) 872a6b7db3Sskrll { 882a6b7db3Sskrll ch1 = (*strp)[1]; 892a6b7db3Sskrll ch2 = (*strp)[2]; 902a6b7db3Sskrll if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9')) 912a6b7db3Sskrll return 1; 922a6b7db3Sskrll if ('3' == ch1 && (ch2 == '0' || ch2 == '1')) 932a6b7db3Sskrll return 1; 942a6b7db3Sskrll } 952a6b7db3Sskrll } 962a6b7db3Sskrll if (**strp == '%' 972a6b7db3Sskrll && TOLOWER ((*strp)[1]) != 'l' 982a6b7db3Sskrll && TOLOWER ((*strp)[1]) != 'h') 992a6b7db3Sskrll return 1; 1002a6b7db3Sskrll return 0; 1012a6b7db3Sskrll} 1022a6b7db3Sskrll 1032a6b7db3Sskrll/* Handle negated literal. */ 1042a6b7db3Sskrll 1052a6b7db3Sskrllstatic const char * 1062a6b7db3Sskrllparse_mimm (CGEN_CPU_DESC cd, 1072a6b7db3Sskrll const char **strp, 1082a6b7db3Sskrll int opindex, 1092a6b7db3Sskrll unsigned long *valuep) 1102a6b7db3Sskrll{ 1112a6b7db3Sskrll const char *errmsg; 1122a6b7db3Sskrll 1132a6b7db3Sskrll /* Verify this isn't a register. */ 1142a6b7db3Sskrll if (iq2000_cgen_isa_register (strp)) 1152a6b7db3Sskrll errmsg = _("immediate value cannot be register"); 1162a6b7db3Sskrll else 1172a6b7db3Sskrll { 1182a6b7db3Sskrll long value; 1192a6b7db3Sskrll 1202a6b7db3Sskrll errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 1212a6b7db3Sskrll if (errmsg == NULL) 1222a6b7db3Sskrll { 1232a6b7db3Sskrll long x = (-value) & 0xFFFF0000; 1242a6b7db3Sskrll 1252a6b7db3Sskrll if (x != 0 && x != (long) 0xFFFF0000) 1262a6b7db3Sskrll errmsg = _("immediate value out of range"); 1272a6b7db3Sskrll else 1282a6b7db3Sskrll *valuep = (-value & 0xFFFF); 1292a6b7db3Sskrll } 1302a6b7db3Sskrll } 1312a6b7db3Sskrll return errmsg; 1322a6b7db3Sskrll} 1332a6b7db3Sskrll 1342a6b7db3Sskrll/* Handle signed/unsigned literal. */ 1352a6b7db3Sskrll 1362a6b7db3Sskrllstatic const char * 1372a6b7db3Sskrllparse_imm (CGEN_CPU_DESC cd, 1382a6b7db3Sskrll const char **strp, 1392a6b7db3Sskrll int opindex, 1402a6b7db3Sskrll unsigned long *valuep) 1412a6b7db3Sskrll{ 1422a6b7db3Sskrll const char *errmsg; 1432a6b7db3Sskrll 1442a6b7db3Sskrll if (iq2000_cgen_isa_register (strp)) 1452a6b7db3Sskrll errmsg = _("immediate value cannot be register"); 1462a6b7db3Sskrll else 1472a6b7db3Sskrll { 1482a6b7db3Sskrll long value; 1492a6b7db3Sskrll 1502a6b7db3Sskrll errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 1512a6b7db3Sskrll if (errmsg == NULL) 1522a6b7db3Sskrll { 1532a6b7db3Sskrll long x = value & 0xFFFF0000; 1542a6b7db3Sskrll 1552a6b7db3Sskrll if (x != 0 && x != (long) 0xFFFF0000) 1562a6b7db3Sskrll errmsg = _("immediate value out of range"); 1572a6b7db3Sskrll else 1582a6b7db3Sskrll *valuep = (value & 0xFFFF); 1592a6b7db3Sskrll } 1602a6b7db3Sskrll } 1612a6b7db3Sskrll return errmsg; 1622a6b7db3Sskrll} 1632a6b7db3Sskrll 1642a6b7db3Sskrll/* Handle iq10 21-bit jmp offset. */ 1652a6b7db3Sskrll 1662a6b7db3Sskrllstatic const char * 1672a6b7db3Sskrllparse_jtargq10 (CGEN_CPU_DESC cd, 1682a6b7db3Sskrll const char **strp, 1692a6b7db3Sskrll int opindex, 1702a6b7db3Sskrll int reloc ATTRIBUTE_UNUSED, 1712a6b7db3Sskrll enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED, 1722a6b7db3Sskrll bfd_vma *valuep) 1732a6b7db3Sskrll{ 1742a6b7db3Sskrll const char *errmsg; 1752a6b7db3Sskrll bfd_vma value; 1762a6b7db3Sskrll enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER; 1772a6b7db3Sskrll 1782a6b7db3Sskrll errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21, 1792a6b7db3Sskrll & result_type, & value); 1802a6b7db3Sskrll if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 1812a6b7db3Sskrll { 1822a6b7db3Sskrll /* Check value is within 23-bits 1832a6b7db3Sskrll (remembering that 2-bit shift right will occur). */ 1842a6b7db3Sskrll if (value > 0x7fffff) 1852a6b7db3Sskrll return _("21-bit offset out of range"); 1862a6b7db3Sskrll } 1872a6b7db3Sskrll *valuep = (value & 0x7FFFFF); 1882a6b7db3Sskrll return errmsg; 1892a6b7db3Sskrll} 1902a6b7db3Sskrll 1912a6b7db3Sskrll/* Handle high(). */ 1922a6b7db3Sskrll 1932a6b7db3Sskrllstatic const char * 1942a6b7db3Sskrllparse_hi16 (CGEN_CPU_DESC cd, 1952a6b7db3Sskrll const char **strp, 1962a6b7db3Sskrll int opindex, 1972a6b7db3Sskrll unsigned long *valuep) 1982a6b7db3Sskrll{ 1992a6b7db3Sskrll if (strncasecmp (*strp, "%hi(", 4) == 0) 2002a6b7db3Sskrll { 2012a6b7db3Sskrll enum cgen_parse_operand_result result_type; 2022a6b7db3Sskrll bfd_vma value; 2032a6b7db3Sskrll const char *errmsg; 2042a6b7db3Sskrll 2052a6b7db3Sskrll *strp += 4; 2062a6b7db3Sskrll errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16, 2072a6b7db3Sskrll & result_type, & value); 2082a6b7db3Sskrll if (**strp != ')') 2092a6b7db3Sskrll return MISSING_CLOSING_PARENTHESIS; 2102a6b7db3Sskrll 2112a6b7db3Sskrll ++*strp; 2122a6b7db3Sskrll if (errmsg == NULL 2132a6b7db3Sskrll && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 2142a6b7db3Sskrll { 2152a6b7db3Sskrll /* If value has top-bit of %lo on, then it will 2162a6b7db3Sskrll sign-propagate and so we compensate by adding 2172a6b7db3Sskrll 1 to the resultant %hi value. */ 2182a6b7db3Sskrll if (value & 0x8000) 2192a6b7db3Sskrll value += 0x10000; 2202a6b7db3Sskrll value >>= 16; 2212a6b7db3Sskrll value &= 0xffff; 2222a6b7db3Sskrll } 2232a6b7db3Sskrll *valuep = value; 2242a6b7db3Sskrll 2252a6b7db3Sskrll return errmsg; 2262a6b7db3Sskrll } 2272a6b7db3Sskrll 2282a6b7db3Sskrll /* We add %uhi in case a user just wants the high 16-bits or is using 2292a6b7db3Sskrll an insn like ori for %lo which does not sign-propagate. */ 2302a6b7db3Sskrll if (strncasecmp (*strp, "%uhi(", 5) == 0) 2312a6b7db3Sskrll { 2322a6b7db3Sskrll enum cgen_parse_operand_result result_type; 2332a6b7db3Sskrll bfd_vma value; 2342a6b7db3Sskrll const char *errmsg; 2352a6b7db3Sskrll 2362a6b7db3Sskrll *strp += 5; 2372a6b7db3Sskrll errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16, 2382a6b7db3Sskrll & result_type, & value); 2392a6b7db3Sskrll if (**strp != ')') 2402a6b7db3Sskrll return MISSING_CLOSING_PARENTHESIS; 2412a6b7db3Sskrll 2422a6b7db3Sskrll ++*strp; 2432a6b7db3Sskrll if (errmsg == NULL 2442a6b7db3Sskrll && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 2452a6b7db3Sskrll value >>= 16; 2462a6b7db3Sskrll 2472a6b7db3Sskrll value &= 0xffff; 2482a6b7db3Sskrll *valuep = value; 2492a6b7db3Sskrll 2502a6b7db3Sskrll return errmsg; 2512a6b7db3Sskrll } 2522a6b7db3Sskrll 2532a6b7db3Sskrll return parse_imm (cd, strp, opindex, valuep); 2542a6b7db3Sskrll} 2552a6b7db3Sskrll 2562a6b7db3Sskrll/* Handle %lo in a signed context. 2572a6b7db3Sskrll The signedness of the value doesn't matter to %lo(), but this also 2582a6b7db3Sskrll handles the case where %lo() isn't present. */ 2592a6b7db3Sskrll 2602a6b7db3Sskrllstatic const char * 2612a6b7db3Sskrllparse_lo16 (CGEN_CPU_DESC cd, 2622a6b7db3Sskrll const char **strp, 2632a6b7db3Sskrll int opindex, 2642a6b7db3Sskrll unsigned long *valuep) 2652a6b7db3Sskrll{ 2662a6b7db3Sskrll if (strncasecmp (*strp, "%lo(", 4) == 0) 2672a6b7db3Sskrll { 2682a6b7db3Sskrll const char *errmsg; 2692a6b7db3Sskrll enum cgen_parse_operand_result result_type; 2702a6b7db3Sskrll bfd_vma value; 2712a6b7db3Sskrll 2722a6b7db3Sskrll *strp += 4; 2732a6b7db3Sskrll errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16, 2742a6b7db3Sskrll & result_type, & value); 2752a6b7db3Sskrll if (**strp != ')') 2762a6b7db3Sskrll return MISSING_CLOSING_PARENTHESIS; 2772a6b7db3Sskrll ++*strp; 2782a6b7db3Sskrll if (errmsg == NULL 2792a6b7db3Sskrll && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 2802a6b7db3Sskrll value &= 0xffff; 2812a6b7db3Sskrll *valuep = value; 2822a6b7db3Sskrll return errmsg; 2832a6b7db3Sskrll } 2842a6b7db3Sskrll 2852a6b7db3Sskrll return parse_imm (cd, strp, opindex, valuep); 2862a6b7db3Sskrll} 2872a6b7db3Sskrll 2882a6b7db3Sskrll/* Handle %lo in a negated signed context. 2892a6b7db3Sskrll The signedness of the value doesn't matter to %lo(), but this also 2902a6b7db3Sskrll handles the case where %lo() isn't present. */ 2912a6b7db3Sskrll 2922a6b7db3Sskrllstatic const char * 2932a6b7db3Sskrllparse_mlo16 (CGEN_CPU_DESC cd, 2942a6b7db3Sskrll const char **strp, 2952a6b7db3Sskrll int opindex, 2962a6b7db3Sskrll unsigned long *valuep) 2972a6b7db3Sskrll{ 2982a6b7db3Sskrll if (strncasecmp (*strp, "%lo(", 4) == 0) 2992a6b7db3Sskrll { 3002a6b7db3Sskrll const char *errmsg; 3012a6b7db3Sskrll enum cgen_parse_operand_result result_type; 3022a6b7db3Sskrll bfd_vma value; 3032a6b7db3Sskrll 3042a6b7db3Sskrll *strp += 4; 3052a6b7db3Sskrll errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16, 3062a6b7db3Sskrll & result_type, & value); 3072a6b7db3Sskrll if (**strp != ')') 3082a6b7db3Sskrll return MISSING_CLOSING_PARENTHESIS; 3092a6b7db3Sskrll ++*strp; 3102a6b7db3Sskrll if (errmsg == NULL 3112a6b7db3Sskrll && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 3122a6b7db3Sskrll value = (-value) & 0xffff; 3132a6b7db3Sskrll *valuep = value; 3142a6b7db3Sskrll return errmsg; 3152a6b7db3Sskrll } 3162a6b7db3Sskrll 3172a6b7db3Sskrll return parse_mimm (cd, strp, opindex, valuep); 3182a6b7db3Sskrll} 3192a6b7db3Sskrll 3202a6b7db3Sskrll/* -- */ 321