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