1*440a403fSchristos/* XSTORMY16 opcode support. -*- C -*- 2*440a403fSchristos Copyright 2011 Free Software Foundation, Inc. 3*440a403fSchristos 4*440a403fSchristos Contributed by Red Hat Inc; 5*440a403fSchristos 6*440a403fSchristos This file is part of the GNU Binutils. 7*440a403fSchristos 8*440a403fSchristos This program is free software; you can redistribute it and/or modify 9*440a403fSchristos it under the terms of the GNU General Public License as published by 10*440a403fSchristos the Free Software Foundation; either version 3 of the License, or 11*440a403fSchristos (at your option) any later version. 12*440a403fSchristos 13*440a403fSchristos This program is distributed in the hope that it will be useful, 14*440a403fSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 15*440a403fSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*440a403fSchristos GNU General Public License for more details. 17*440a403fSchristos 18*440a403fSchristos You should have received a copy of the GNU General Public License 19*440a403fSchristos along with this program; if not, write to the Free Software 20*440a403fSchristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21*440a403fSchristos MA 02110-1301, USA. */ 22*440a403fSchristos 23*440a403fSchristos/* This file is an addendum to xstormy16.cpu. Heavy use of C code isn't 24*440a403fSchristos appropriate in .cpu files, so it resides here. This especially applies 25*440a403fSchristos to assembly/disassembly where parsing/printing can be quite involved. 26*440a403fSchristos Such things aren't really part of the specification of the cpu, per se, 27*440a403fSchristos so .cpu files provide the general framework and .opc files handle the 28*440a403fSchristos nitty-gritty details as necessary. 29*440a403fSchristos 30*440a403fSchristos Each section is delimited with start and end markers. 31*440a403fSchristos 32*440a403fSchristos <arch>-opc.h additions use: "-- opc.h" 33*440a403fSchristos <arch>-opc.c additions use: "-- opc.c" 34*440a403fSchristos <arch>-asm.c additions use: "-- asm.c" 35*440a403fSchristos <arch>-dis.c additions use: "-- dis.c" 36*440a403fSchristos <arch>-ibd.h additions use: "-- ibd.h". */ 37*440a403fSchristos 38*440a403fSchristos/* -- opc.h */ 39*440a403fSchristos 40*440a403fSchristos/* Allows reason codes to be output when assembler errors occur. */ 41*440a403fSchristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS 42*440a403fSchristos 43*440a403fSchristos/* We can't use the default hash size because many bits are used by 44*440a403fSchristos operands. */ 45*440a403fSchristos#define CGEN_DIS_HASH_SIZE 1 46*440a403fSchristos#define CGEN_DIS_HASH(buf, value) 0 47*440a403fSchristos/* -- */ 48*440a403fSchristos 49*440a403fSchristos/* -- asm.c */ 50*440a403fSchristos 51*440a403fSchristos/* The machine-independent code doesn't know how to disambiguate 52*440a403fSchristos mov (foo),r3 53*440a403fSchristos and 54*440a403fSchristos mov (r2),r3 55*440a403fSchristos where 'foo' is a label. This helps it out. */ 56*440a403fSchristos 57*440a403fSchristosstatic const char * 58*440a403fSchristosparse_mem8 (CGEN_CPU_DESC cd, 59*440a403fSchristos const char **strp, 60*440a403fSchristos int opindex, 61*440a403fSchristos unsigned long *valuep) 62*440a403fSchristos{ 63*440a403fSchristos if (**strp == '(') 64*440a403fSchristos { 65*440a403fSchristos const char *s = *strp; 66*440a403fSchristos 67*440a403fSchristos if (s[1] == '-' && s[2] == '-') 68*440a403fSchristos return _("Bad register in preincrement"); 69*440a403fSchristos 70*440a403fSchristos while (ISALNUM (*++s)) 71*440a403fSchristos ; 72*440a403fSchristos if (s[0] == '+' && s[1] == '+' && (s[2] == ')' || s[2] == ',')) 73*440a403fSchristos return _("Bad register in postincrement"); 74*440a403fSchristos if (s[0] == ',' || s[0] == ')') 75*440a403fSchristos return _("Bad register name"); 76*440a403fSchristos } 77*440a403fSchristos else if (cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, 78*440a403fSchristos (long *) valuep) == NULL) 79*440a403fSchristos return _("Label conflicts with register name"); 80*440a403fSchristos else if (strncasecmp (*strp, "rx,", 3) == 0 81*440a403fSchristos || strncasecmp (*strp, "rxl,", 3) == 0 82*440a403fSchristos || strncasecmp (*strp, "rxh,", 3) == 0) 83*440a403fSchristos return _("Label conflicts with `Rx'"); 84*440a403fSchristos else if (**strp == '#') 85*440a403fSchristos return _("Bad immediate expression"); 86*440a403fSchristos 87*440a403fSchristos return cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 88*440a403fSchristos} 89*440a403fSchristos 90*440a403fSchristos/* For the add and subtract instructions, there are two immediate forms, 91*440a403fSchristos one for small operands and one for large ones. We want to use 92*440a403fSchristos the small one when possible, but we do not want to generate relocs 93*440a403fSchristos of the small size. This is somewhat tricky. */ 94*440a403fSchristos 95*440a403fSchristosstatic const char * 96*440a403fSchristosparse_small_immediate (CGEN_CPU_DESC cd, 97*440a403fSchristos const char **strp, 98*440a403fSchristos int opindex, 99*440a403fSchristos unsigned long *valuep) 100*440a403fSchristos{ 101*440a403fSchristos bfd_vma value; 102*440a403fSchristos enum cgen_parse_operand_result result; 103*440a403fSchristos const char *errmsg; 104*440a403fSchristos 105*440a403fSchristos if (**strp == '@') 106*440a403fSchristos return _("No relocation for small immediate"); 107*440a403fSchristos 108*440a403fSchristos errmsg = (* cd->parse_operand_fn) 109*440a403fSchristos (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE, 110*440a403fSchristos & result, & value); 111*440a403fSchristos 112*440a403fSchristos if (errmsg) 113*440a403fSchristos return errmsg; 114*440a403fSchristos 115*440a403fSchristos if (result != CGEN_PARSE_OPERAND_RESULT_NUMBER) 116*440a403fSchristos return _("Small operand was not an immediate number"); 117*440a403fSchristos 118*440a403fSchristos *valuep = value; 119*440a403fSchristos return NULL; 120*440a403fSchristos} 121*440a403fSchristos 122*440a403fSchristos/* Literal scan be either a normal literal, a @hi() or @lo relocation. */ 123*440a403fSchristos 124*440a403fSchristosstatic const char * 125*440a403fSchristosparse_immediate16 (CGEN_CPU_DESC cd, 126*440a403fSchristos const char **strp, 127*440a403fSchristos int opindex, 128*440a403fSchristos unsigned long *valuep) 129*440a403fSchristos{ 130*440a403fSchristos const char *errmsg; 131*440a403fSchristos enum cgen_parse_operand_result result; 132*440a403fSchristos bfd_reloc_code_real_type code = BFD_RELOC_NONE; 133*440a403fSchristos bfd_vma value; 134*440a403fSchristos 135*440a403fSchristos if (strncmp (*strp, "@hi(", 4) == 0) 136*440a403fSchristos { 137*440a403fSchristos *strp += 4; 138*440a403fSchristos code = BFD_RELOC_HI16; 139*440a403fSchristos } 140*440a403fSchristos else 141*440a403fSchristos if (strncmp (*strp, "@lo(", 4) == 0) 142*440a403fSchristos { 143*440a403fSchristos *strp += 4; 144*440a403fSchristos code = BFD_RELOC_LO16; 145*440a403fSchristos } 146*440a403fSchristos 147*440a403fSchristos if (code == BFD_RELOC_NONE) 148*440a403fSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 149*440a403fSchristos else 150*440a403fSchristos { 151*440a403fSchristos errmsg = cgen_parse_address (cd, strp, opindex, code, &result, &value); 152*440a403fSchristos if ((errmsg == NULL) && 153*440a403fSchristos (result != CGEN_PARSE_OPERAND_RESULT_QUEUED)) 154*440a403fSchristos errmsg = _("Operand is not a symbol"); 155*440a403fSchristos 156*440a403fSchristos *valuep = value; 157*440a403fSchristos if ((code == BFD_RELOC_HI16 || code == BFD_RELOC_LO16) 158*440a403fSchristos && **strp == ')') 159*440a403fSchristos *strp += 1; 160*440a403fSchristos else 161*440a403fSchristos { 162*440a403fSchristos errmsg = _("Syntax error: No trailing ')'"); 163*440a403fSchristos return errmsg; 164*440a403fSchristos } 165*440a403fSchristos } 166*440a403fSchristos return errmsg; 167*440a403fSchristos} 168*440a403fSchristos/* -- */ 169