1*07163879Schristos /* DO NOT EDIT! -*- buffer-read-only: t -*- vi:set ro: */ 2c5dff60aSchristos /* Assembler interface for targets using CGEN. -*- C -*- 3c5dff60aSchristos CGEN: Cpu tools GENerator 4c5dff60aSchristos 5c5dff60aSchristos THIS FILE IS MACHINE GENERATED WITH CGEN. 6c5dff60aSchristos - the resultant file is machine generated, cgen-asm.in isn't 7c5dff60aSchristos 8*07163879Schristos Copyright (C) 1996-2019 Free Software Foundation, Inc. 9c5dff60aSchristos 10c5dff60aSchristos This file is part of libopcodes. 11c5dff60aSchristos 12c5dff60aSchristos This library is free software; you can redistribute it and/or modify 13c5dff60aSchristos it under the terms of the GNU General Public License as published by 14c5dff60aSchristos the Free Software Foundation; either version 3, or (at your option) 15c5dff60aSchristos any later version. 16c5dff60aSchristos 17c5dff60aSchristos It is distributed in the hope that it will be useful, but WITHOUT 18c5dff60aSchristos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 19c5dff60aSchristos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 20c5dff60aSchristos License for more details. 21c5dff60aSchristos 22c5dff60aSchristos You should have received a copy of the GNU General Public License 23c5dff60aSchristos along with this program; if not, write to the Free Software Foundation, Inc., 24c5dff60aSchristos 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 25c5dff60aSchristos 26c5dff60aSchristos 27c5dff60aSchristos /* ??? Eventually more and more of this stuff can go to cpu-independent files. 28c5dff60aSchristos Keep that in mind. */ 29c5dff60aSchristos 30c5dff60aSchristos #include "sysdep.h" 31c5dff60aSchristos #include <stdio.h> 32c5dff60aSchristos #include "ansidecl.h" 33c5dff60aSchristos #include "bfd.h" 34c5dff60aSchristos #include "symcat.h" 35c5dff60aSchristos #include "xstormy16-desc.h" 36c5dff60aSchristos #include "xstormy16-opc.h" 37c5dff60aSchristos #include "opintl.h" 38c5dff60aSchristos #include "xregex.h" 39c5dff60aSchristos #include "libiberty.h" 40c5dff60aSchristos #include "safe-ctype.h" 41c5dff60aSchristos 42c5dff60aSchristos #undef min 43c5dff60aSchristos #define min(a,b) ((a) < (b) ? (a) : (b)) 44c5dff60aSchristos #undef max 45c5dff60aSchristos #define max(a,b) ((a) > (b) ? (a) : (b)) 46c5dff60aSchristos 47c5dff60aSchristos static const char * parse_insn_normal 48c5dff60aSchristos (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *); 49c5dff60aSchristos 50c5dff60aSchristos /* -- assembler routines inserted here. */ 51c5dff60aSchristos 52c5dff60aSchristos /* -- asm.c */ 53c5dff60aSchristos 54c5dff60aSchristos /* The machine-independent code doesn't know how to disambiguate 55c5dff60aSchristos mov (foo),r3 56c5dff60aSchristos and 57c5dff60aSchristos mov (r2),r3 58c5dff60aSchristos where 'foo' is a label. This helps it out. */ 59c5dff60aSchristos 60c5dff60aSchristos static const char * 61c5dff60aSchristos parse_mem8 (CGEN_CPU_DESC cd, 62c5dff60aSchristos const char **strp, 63c5dff60aSchristos int opindex, 64c5dff60aSchristos unsigned long *valuep) 65c5dff60aSchristos { 66c5dff60aSchristos if (**strp == '(') 67c5dff60aSchristos { 68c5dff60aSchristos const char *s = *strp; 69c5dff60aSchristos 70c5dff60aSchristos if (s[1] == '-' && s[2] == '-') 71c5dff60aSchristos return _("Bad register in preincrement"); 72c5dff60aSchristos 73c5dff60aSchristos while (ISALNUM (*++s)) 74c5dff60aSchristos ; 75c5dff60aSchristos if (s[0] == '+' && s[1] == '+' && (s[2] == ')' || s[2] == ',')) 76c5dff60aSchristos return _("Bad register in postincrement"); 77c5dff60aSchristos if (s[0] == ',' || s[0] == ')') 78c5dff60aSchristos return _("Bad register name"); 79c5dff60aSchristos } 80c5dff60aSchristos else if (cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, 81c5dff60aSchristos (long *) valuep) == NULL) 82c5dff60aSchristos return _("Label conflicts with register name"); 83c5dff60aSchristos else if (strncasecmp (*strp, "rx,", 3) == 0 84c5dff60aSchristos || strncasecmp (*strp, "rxl,", 3) == 0 85c5dff60aSchristos || strncasecmp (*strp, "rxh,", 3) == 0) 86c5dff60aSchristos return _("Label conflicts with `Rx'"); 87c5dff60aSchristos else if (**strp == '#') 88c5dff60aSchristos return _("Bad immediate expression"); 89c5dff60aSchristos 90c5dff60aSchristos return cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 91c5dff60aSchristos } 92c5dff60aSchristos 93c5dff60aSchristos /* For the add and subtract instructions, there are two immediate forms, 94c5dff60aSchristos one for small operands and one for large ones. We want to use 95c5dff60aSchristos the small one when possible, but we do not want to generate relocs 96c5dff60aSchristos of the small size. This is somewhat tricky. */ 97c5dff60aSchristos 98c5dff60aSchristos static const char * 99c5dff60aSchristos parse_small_immediate (CGEN_CPU_DESC cd, 100c5dff60aSchristos const char **strp, 101c5dff60aSchristos int opindex, 102c5dff60aSchristos unsigned long *valuep) 103c5dff60aSchristos { 104c5dff60aSchristos bfd_vma value; 105c5dff60aSchristos enum cgen_parse_operand_result result; 106c5dff60aSchristos const char *errmsg; 107c5dff60aSchristos 108c5dff60aSchristos if (**strp == '@') 109c5dff60aSchristos return _("No relocation for small immediate"); 110c5dff60aSchristos 111c5dff60aSchristos errmsg = (* cd->parse_operand_fn) 112c5dff60aSchristos (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE, 113c5dff60aSchristos & result, & value); 114c5dff60aSchristos 115c5dff60aSchristos if (errmsg) 116c5dff60aSchristos return errmsg; 117c5dff60aSchristos 118c5dff60aSchristos if (result != CGEN_PARSE_OPERAND_RESULT_NUMBER) 119c5dff60aSchristos return _("Small operand was not an immediate number"); 120c5dff60aSchristos 121c5dff60aSchristos *valuep = value; 122c5dff60aSchristos return NULL; 123c5dff60aSchristos } 124c5dff60aSchristos 125c5dff60aSchristos /* Literal scan be either a normal literal, a @hi() or @lo relocation. */ 126c5dff60aSchristos 127c5dff60aSchristos static const char * 128c5dff60aSchristos parse_immediate16 (CGEN_CPU_DESC cd, 129c5dff60aSchristos const char **strp, 130c5dff60aSchristos int opindex, 131c5dff60aSchristos unsigned long *valuep) 132c5dff60aSchristos { 133c5dff60aSchristos const char *errmsg; 134c5dff60aSchristos enum cgen_parse_operand_result result; 135c5dff60aSchristos bfd_reloc_code_real_type code = BFD_RELOC_NONE; 136c5dff60aSchristos bfd_vma value; 137c5dff60aSchristos 138c5dff60aSchristos if (strncmp (*strp, "@hi(", 4) == 0) 139c5dff60aSchristos { 140c5dff60aSchristos *strp += 4; 141c5dff60aSchristos code = BFD_RELOC_HI16; 142c5dff60aSchristos } 143c5dff60aSchristos else 144c5dff60aSchristos if (strncmp (*strp, "@lo(", 4) == 0) 145c5dff60aSchristos { 146c5dff60aSchristos *strp += 4; 147c5dff60aSchristos code = BFD_RELOC_LO16; 148c5dff60aSchristos } 149c5dff60aSchristos 150c5dff60aSchristos if (code == BFD_RELOC_NONE) 151c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 152c5dff60aSchristos else 153c5dff60aSchristos { 154c5dff60aSchristos errmsg = cgen_parse_address (cd, strp, opindex, code, &result, &value); 155c5dff60aSchristos if ((errmsg == NULL) && 156c5dff60aSchristos (result != CGEN_PARSE_OPERAND_RESULT_QUEUED)) 157c5dff60aSchristos errmsg = _("Operand is not a symbol"); 158c5dff60aSchristos 159c5dff60aSchristos *valuep = value; 160c5dff60aSchristos if ((code == BFD_RELOC_HI16 || code == BFD_RELOC_LO16) 161c5dff60aSchristos && **strp == ')') 162c5dff60aSchristos *strp += 1; 163c5dff60aSchristos else 164c5dff60aSchristos { 165c5dff60aSchristos errmsg = _("Syntax error: No trailing ')'"); 166c5dff60aSchristos return errmsg; 167c5dff60aSchristos } 168c5dff60aSchristos } 169c5dff60aSchristos return errmsg; 170c5dff60aSchristos } 171c5dff60aSchristos /* -- */ 172c5dff60aSchristos 173c5dff60aSchristos const char * xstormy16_cgen_parse_operand 174c5dff60aSchristos (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 175c5dff60aSchristos 176c5dff60aSchristos /* Main entry point for operand parsing. 177c5dff60aSchristos 178c5dff60aSchristos This function is basically just a big switch statement. Earlier versions 179c5dff60aSchristos used tables to look up the function to use, but 180c5dff60aSchristos - if the table contains both assembler and disassembler functions then 181c5dff60aSchristos the disassembler contains much of the assembler and vice-versa, 182c5dff60aSchristos - there's a lot of inlining possibilities as things grow, 183c5dff60aSchristos - using a switch statement avoids the function call overhead. 184c5dff60aSchristos 185c5dff60aSchristos This function could be moved into `parse_insn_normal', but keeping it 186c5dff60aSchristos separate makes clear the interface between `parse_insn_normal' and each of 187c5dff60aSchristos the handlers. */ 188c5dff60aSchristos 189c5dff60aSchristos const char * 190c5dff60aSchristos xstormy16_cgen_parse_operand (CGEN_CPU_DESC cd, 191c5dff60aSchristos int opindex, 192c5dff60aSchristos const char ** strp, 193c5dff60aSchristos CGEN_FIELDS * fields) 194c5dff60aSchristos { 195c5dff60aSchristos const char * errmsg = NULL; 196c5dff60aSchristos /* Used by scalar operands that still need to be parsed. */ 197c5dff60aSchristos long junk ATTRIBUTE_UNUSED; 198c5dff60aSchristos 199c5dff60aSchristos switch (opindex) 200c5dff60aSchristos { 201c5dff60aSchristos case XSTORMY16_OPERAND_RB : 202c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_Rb_names, & fields->f_Rb); 203c5dff60aSchristos break; 204c5dff60aSchristos case XSTORMY16_OPERAND_RBJ : 205c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_Rb_names, & fields->f_Rbj); 206c5dff60aSchristos break; 207c5dff60aSchristos case XSTORMY16_OPERAND_RD : 208c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rd); 209c5dff60aSchristos break; 210c5dff60aSchristos case XSTORMY16_OPERAND_RDM : 211c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rdm); 212c5dff60aSchristos break; 213c5dff60aSchristos case XSTORMY16_OPERAND_RM : 214c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rm); 215c5dff60aSchristos break; 216c5dff60aSchristos case XSTORMY16_OPERAND_RS : 217c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rs); 218c5dff60aSchristos break; 219c5dff60aSchristos case XSTORMY16_OPERAND_ABS24 : 220c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_ABS24, (unsigned long *) (& fields->f_abs24)); 221c5dff60aSchristos break; 222c5dff60aSchristos case XSTORMY16_OPERAND_BCOND2 : 223c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_branchcond, & fields->f_op2); 224c5dff60aSchristos break; 225c5dff60aSchristos case XSTORMY16_OPERAND_BCOND5 : 226c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_branchcond, & fields->f_op5); 227c5dff60aSchristos break; 228c5dff60aSchristos case XSTORMY16_OPERAND_HMEM8 : 229c5dff60aSchristos errmsg = parse_mem8 (cd, strp, XSTORMY16_OPERAND_HMEM8, (unsigned long *) (& fields->f_hmem8)); 230c5dff60aSchristos break; 231c5dff60aSchristos case XSTORMY16_OPERAND_IMM12 : 232c5dff60aSchristos errmsg = cgen_parse_signed_integer (cd, strp, XSTORMY16_OPERAND_IMM12, (long *) (& fields->f_imm12)); 233c5dff60aSchristos break; 234c5dff60aSchristos case XSTORMY16_OPERAND_IMM16 : 235c5dff60aSchristos errmsg = parse_immediate16 (cd, strp, XSTORMY16_OPERAND_IMM16, (unsigned long *) (& fields->f_imm16)); 236c5dff60aSchristos break; 237c5dff60aSchristos case XSTORMY16_OPERAND_IMM2 : 238c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM2, (unsigned long *) (& fields->f_imm2)); 239c5dff60aSchristos break; 240c5dff60aSchristos case XSTORMY16_OPERAND_IMM3 : 241c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM3, (unsigned long *) (& fields->f_imm3)); 242c5dff60aSchristos break; 243c5dff60aSchristos case XSTORMY16_OPERAND_IMM3B : 244c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM3B, (unsigned long *) (& fields->f_imm3b)); 245c5dff60aSchristos break; 246c5dff60aSchristos case XSTORMY16_OPERAND_IMM4 : 247c5dff60aSchristos errmsg = parse_small_immediate (cd, strp, XSTORMY16_OPERAND_IMM4, (unsigned long *) (& fields->f_imm4)); 248c5dff60aSchristos break; 249c5dff60aSchristos case XSTORMY16_OPERAND_IMM8 : 250c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM8, (unsigned long *) (& fields->f_imm8)); 251c5dff60aSchristos break; 252c5dff60aSchristos case XSTORMY16_OPERAND_IMM8SMALL : 253c5dff60aSchristos errmsg = parse_small_immediate (cd, strp, XSTORMY16_OPERAND_IMM8SMALL, (unsigned long *) (& fields->f_imm8)); 254c5dff60aSchristos break; 255c5dff60aSchristos case XSTORMY16_OPERAND_LMEM8 : 256c5dff60aSchristos errmsg = parse_mem8 (cd, strp, XSTORMY16_OPERAND_LMEM8, (unsigned long *) (& fields->f_lmem8)); 257c5dff60aSchristos break; 258c5dff60aSchristos case XSTORMY16_OPERAND_REL12 : 259c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL12, (unsigned long *) (& fields->f_rel12)); 260c5dff60aSchristos break; 261c5dff60aSchristos case XSTORMY16_OPERAND_REL12A : 262c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL12A, (unsigned long *) (& fields->f_rel12a)); 263c5dff60aSchristos break; 264c5dff60aSchristos case XSTORMY16_OPERAND_REL8_2 : 265c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL8_2, (unsigned long *) (& fields->f_rel8_2)); 266c5dff60aSchristos break; 267c5dff60aSchristos case XSTORMY16_OPERAND_REL8_4 : 268c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL8_4, (unsigned long *) (& fields->f_rel8_4)); 269c5dff60aSchristos break; 270c5dff60aSchristos case XSTORMY16_OPERAND_WS2 : 271c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_wordsize, & fields->f_op2m); 272c5dff60aSchristos break; 273c5dff60aSchristos 274c5dff60aSchristos default : 275c5dff60aSchristos /* xgettext:c-format */ 276*07163879Schristos opcodes_error_handler 277*07163879Schristos (_("internal error: unrecognized field %d while parsing"), 278*07163879Schristos opindex); 279c5dff60aSchristos abort (); 280c5dff60aSchristos } 281c5dff60aSchristos 282c5dff60aSchristos return errmsg; 283c5dff60aSchristos } 284c5dff60aSchristos 285c5dff60aSchristos cgen_parse_fn * const xstormy16_cgen_parse_handlers[] = 286c5dff60aSchristos { 287c5dff60aSchristos parse_insn_normal, 288c5dff60aSchristos }; 289c5dff60aSchristos 290c5dff60aSchristos void 291c5dff60aSchristos xstormy16_cgen_init_asm (CGEN_CPU_DESC cd) 292c5dff60aSchristos { 293c5dff60aSchristos xstormy16_cgen_init_opcode_table (cd); 294c5dff60aSchristos xstormy16_cgen_init_ibld_table (cd); 295c5dff60aSchristos cd->parse_handlers = & xstormy16_cgen_parse_handlers[0]; 296c5dff60aSchristos cd->parse_operand = xstormy16_cgen_parse_operand; 297c5dff60aSchristos #ifdef CGEN_ASM_INIT_HOOK 298c5dff60aSchristos CGEN_ASM_INIT_HOOK 299c5dff60aSchristos #endif 300c5dff60aSchristos } 301c5dff60aSchristos 302c5dff60aSchristos 303c5dff60aSchristos 304c5dff60aSchristos /* Regex construction routine. 305c5dff60aSchristos 306c5dff60aSchristos This translates an opcode syntax string into a regex string, 307c5dff60aSchristos by replacing any non-character syntax element (such as an 308c5dff60aSchristos opcode) with the pattern '.*' 309c5dff60aSchristos 310c5dff60aSchristos It then compiles the regex and stores it in the opcode, for 311c5dff60aSchristos later use by xstormy16_cgen_assemble_insn 312c5dff60aSchristos 313c5dff60aSchristos Returns NULL for success, an error message for failure. */ 314c5dff60aSchristos 315c5dff60aSchristos char * 316c5dff60aSchristos xstormy16_cgen_build_insn_regex (CGEN_INSN *insn) 317c5dff60aSchristos { 318c5dff60aSchristos CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn); 319c5dff60aSchristos const char *mnem = CGEN_INSN_MNEMONIC (insn); 320c5dff60aSchristos char rxbuf[CGEN_MAX_RX_ELEMENTS]; 321c5dff60aSchristos char *rx = rxbuf; 322c5dff60aSchristos const CGEN_SYNTAX_CHAR_TYPE *syn; 323c5dff60aSchristos int reg_err; 324c5dff60aSchristos 325c5dff60aSchristos syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc)); 326c5dff60aSchristos 327c5dff60aSchristos /* Mnemonics come first in the syntax string. */ 328c5dff60aSchristos if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 329c5dff60aSchristos return _("missing mnemonic in syntax string"); 330c5dff60aSchristos ++syn; 331c5dff60aSchristos 332c5dff60aSchristos /* Generate a case sensitive regular expression that emulates case 333c5dff60aSchristos insensitive matching in the "C" locale. We cannot generate a case 334c5dff60aSchristos insensitive regular expression because in Turkish locales, 'i' and 'I' 335c5dff60aSchristos are not equal modulo case conversion. */ 336c5dff60aSchristos 337c5dff60aSchristos /* Copy the literal mnemonic out of the insn. */ 338c5dff60aSchristos for (; *mnem; mnem++) 339c5dff60aSchristos { 340c5dff60aSchristos char c = *mnem; 341c5dff60aSchristos 342c5dff60aSchristos if (ISALPHA (c)) 343c5dff60aSchristos { 344c5dff60aSchristos *rx++ = '['; 345c5dff60aSchristos *rx++ = TOLOWER (c); 346c5dff60aSchristos *rx++ = TOUPPER (c); 347c5dff60aSchristos *rx++ = ']'; 348c5dff60aSchristos } 349c5dff60aSchristos else 350c5dff60aSchristos *rx++ = c; 351c5dff60aSchristos } 352c5dff60aSchristos 353c5dff60aSchristos /* Copy any remaining literals from the syntax string into the rx. */ 354c5dff60aSchristos for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn) 355c5dff60aSchristos { 356c5dff60aSchristos if (CGEN_SYNTAX_CHAR_P (* syn)) 357c5dff60aSchristos { 358c5dff60aSchristos char c = CGEN_SYNTAX_CHAR (* syn); 359c5dff60aSchristos 360c5dff60aSchristos switch (c) 361c5dff60aSchristos { 362c5dff60aSchristos /* Escape any regex metacharacters in the syntax. */ 363c5dff60aSchristos case '.': case '[': case '\\': 364c5dff60aSchristos case '*': case '^': case '$': 365c5dff60aSchristos 366c5dff60aSchristos #ifdef CGEN_ESCAPE_EXTENDED_REGEX 367c5dff60aSchristos case '?': case '{': case '}': 368c5dff60aSchristos case '(': case ')': case '*': 369c5dff60aSchristos case '|': case '+': case ']': 370c5dff60aSchristos #endif 371c5dff60aSchristos *rx++ = '\\'; 372c5dff60aSchristos *rx++ = c; 373c5dff60aSchristos break; 374c5dff60aSchristos 375c5dff60aSchristos default: 376c5dff60aSchristos if (ISALPHA (c)) 377c5dff60aSchristos { 378c5dff60aSchristos *rx++ = '['; 379c5dff60aSchristos *rx++ = TOLOWER (c); 380c5dff60aSchristos *rx++ = TOUPPER (c); 381c5dff60aSchristos *rx++ = ']'; 382c5dff60aSchristos } 383c5dff60aSchristos else 384c5dff60aSchristos *rx++ = c; 385c5dff60aSchristos break; 386c5dff60aSchristos } 387c5dff60aSchristos } 388c5dff60aSchristos else 389c5dff60aSchristos { 390c5dff60aSchristos /* Replace non-syntax fields with globs. */ 391c5dff60aSchristos *rx++ = '.'; 392c5dff60aSchristos *rx++ = '*'; 393c5dff60aSchristos } 394c5dff60aSchristos } 395c5dff60aSchristos 396c5dff60aSchristos /* Trailing whitespace ok. */ 397c5dff60aSchristos * rx++ = '['; 398c5dff60aSchristos * rx++ = ' '; 399c5dff60aSchristos * rx++ = '\t'; 400c5dff60aSchristos * rx++ = ']'; 401c5dff60aSchristos * rx++ = '*'; 402c5dff60aSchristos 403c5dff60aSchristos /* But anchor it after that. */ 404c5dff60aSchristos * rx++ = '$'; 405c5dff60aSchristos * rx = '\0'; 406c5dff60aSchristos 407c5dff60aSchristos CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t)); 408c5dff60aSchristos reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB); 409c5dff60aSchristos 410c5dff60aSchristos if (reg_err == 0) 411c5dff60aSchristos return NULL; 412c5dff60aSchristos else 413c5dff60aSchristos { 414c5dff60aSchristos static char msg[80]; 415c5dff60aSchristos 416c5dff60aSchristos regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80); 417c5dff60aSchristos regfree ((regex_t *) CGEN_INSN_RX (insn)); 418c5dff60aSchristos free (CGEN_INSN_RX (insn)); 419c5dff60aSchristos (CGEN_INSN_RX (insn)) = NULL; 420c5dff60aSchristos return msg; 421c5dff60aSchristos } 422c5dff60aSchristos } 423c5dff60aSchristos 424c5dff60aSchristos 425c5dff60aSchristos /* Default insn parser. 426c5dff60aSchristos 427c5dff60aSchristos The syntax string is scanned and operands are parsed and stored in FIELDS. 428c5dff60aSchristos Relocs are queued as we go via other callbacks. 429c5dff60aSchristos 430c5dff60aSchristos ??? Note that this is currently an all-or-nothing parser. If we fail to 431c5dff60aSchristos parse the instruction, we return 0 and the caller will start over from 432c5dff60aSchristos the beginning. Backtracking will be necessary in parsing subexpressions, 433c5dff60aSchristos but that can be handled there. Not handling backtracking here may get 434c5dff60aSchristos expensive in the case of the m68k. Deal with later. 435c5dff60aSchristos 436c5dff60aSchristos Returns NULL for success, an error message for failure. */ 437c5dff60aSchristos 438c5dff60aSchristos static const char * 439c5dff60aSchristos parse_insn_normal (CGEN_CPU_DESC cd, 440c5dff60aSchristos const CGEN_INSN *insn, 441c5dff60aSchristos const char **strp, 442c5dff60aSchristos CGEN_FIELDS *fields) 443c5dff60aSchristos { 444c5dff60aSchristos /* ??? Runtime added insns not handled yet. */ 445c5dff60aSchristos const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 446c5dff60aSchristos const char *str = *strp; 447c5dff60aSchristos const char *errmsg; 448c5dff60aSchristos const char *p; 449c5dff60aSchristos const CGEN_SYNTAX_CHAR_TYPE * syn; 450c5dff60aSchristos #ifdef CGEN_MNEMONIC_OPERANDS 451c5dff60aSchristos /* FIXME: wip */ 452c5dff60aSchristos int past_opcode_p; 453c5dff60aSchristos #endif 454c5dff60aSchristos 455c5dff60aSchristos /* For now we assume the mnemonic is first (there are no leading operands). 456c5dff60aSchristos We can parse it without needing to set up operand parsing. 457c5dff60aSchristos GAS's input scrubber will ensure mnemonics are lowercase, but we may 458c5dff60aSchristos not be called from GAS. */ 459c5dff60aSchristos p = CGEN_INSN_MNEMONIC (insn); 460c5dff60aSchristos while (*p && TOLOWER (*p) == TOLOWER (*str)) 461c5dff60aSchristos ++p, ++str; 462c5dff60aSchristos 463c5dff60aSchristos if (* p) 464c5dff60aSchristos return _("unrecognized instruction"); 465c5dff60aSchristos 466c5dff60aSchristos #ifndef CGEN_MNEMONIC_OPERANDS 467c5dff60aSchristos if (* str && ! ISSPACE (* str)) 468c5dff60aSchristos return _("unrecognized instruction"); 469c5dff60aSchristos #endif 470c5dff60aSchristos 471c5dff60aSchristos CGEN_INIT_PARSE (cd); 472c5dff60aSchristos cgen_init_parse_operand (cd); 473c5dff60aSchristos #ifdef CGEN_MNEMONIC_OPERANDS 474c5dff60aSchristos past_opcode_p = 0; 475c5dff60aSchristos #endif 476c5dff60aSchristos 477c5dff60aSchristos /* We don't check for (*str != '\0') here because we want to parse 478c5dff60aSchristos any trailing fake arguments in the syntax string. */ 479c5dff60aSchristos syn = CGEN_SYNTAX_STRING (syntax); 480c5dff60aSchristos 481c5dff60aSchristos /* Mnemonics come first for now, ensure valid string. */ 482c5dff60aSchristos if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 483c5dff60aSchristos abort (); 484c5dff60aSchristos 485c5dff60aSchristos ++syn; 486c5dff60aSchristos 487c5dff60aSchristos while (* syn != 0) 488c5dff60aSchristos { 489c5dff60aSchristos /* Non operand chars must match exactly. */ 490c5dff60aSchristos if (CGEN_SYNTAX_CHAR_P (* syn)) 491c5dff60aSchristos { 492c5dff60aSchristos /* FIXME: While we allow for non-GAS callers above, we assume the 493c5dff60aSchristos first char after the mnemonic part is a space. */ 494c5dff60aSchristos /* FIXME: We also take inappropriate advantage of the fact that 495c5dff60aSchristos GAS's input scrubber will remove extraneous blanks. */ 496c5dff60aSchristos if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn))) 497c5dff60aSchristos { 498c5dff60aSchristos #ifdef CGEN_MNEMONIC_OPERANDS 499c5dff60aSchristos if (CGEN_SYNTAX_CHAR(* syn) == ' ') 500c5dff60aSchristos past_opcode_p = 1; 501c5dff60aSchristos #endif 502c5dff60aSchristos ++ syn; 503c5dff60aSchristos ++ str; 504c5dff60aSchristos } 505c5dff60aSchristos else if (*str) 506c5dff60aSchristos { 507c5dff60aSchristos /* Syntax char didn't match. Can't be this insn. */ 508c5dff60aSchristos static char msg [80]; 509c5dff60aSchristos 510c5dff60aSchristos /* xgettext:c-format */ 511c5dff60aSchristos sprintf (msg, _("syntax error (expected char `%c', found `%c')"), 512c5dff60aSchristos CGEN_SYNTAX_CHAR(*syn), *str); 513c5dff60aSchristos return msg; 514c5dff60aSchristos } 515c5dff60aSchristos else 516c5dff60aSchristos { 517c5dff60aSchristos /* Ran out of input. */ 518c5dff60aSchristos static char msg [80]; 519c5dff60aSchristos 520c5dff60aSchristos /* xgettext:c-format */ 521c5dff60aSchristos sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"), 522c5dff60aSchristos CGEN_SYNTAX_CHAR(*syn)); 523c5dff60aSchristos return msg; 524c5dff60aSchristos } 525c5dff60aSchristos continue; 526c5dff60aSchristos } 527c5dff60aSchristos 528c5dff60aSchristos #ifdef CGEN_MNEMONIC_OPERANDS 529c5dff60aSchristos (void) past_opcode_p; 530c5dff60aSchristos #endif 531c5dff60aSchristos /* We have an operand of some sort. */ 532c5dff60aSchristos errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields); 533c5dff60aSchristos if (errmsg) 534c5dff60aSchristos return errmsg; 535c5dff60aSchristos 536c5dff60aSchristos /* Done with this operand, continue with next one. */ 537c5dff60aSchristos ++ syn; 538c5dff60aSchristos } 539c5dff60aSchristos 540c5dff60aSchristos /* If we're at the end of the syntax string, we're done. */ 541c5dff60aSchristos if (* syn == 0) 542c5dff60aSchristos { 543c5dff60aSchristos /* FIXME: For the moment we assume a valid `str' can only contain 544c5dff60aSchristos blanks now. IE: We needn't try again with a longer version of 545c5dff60aSchristos the insn and it is assumed that longer versions of insns appear 546c5dff60aSchristos before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ 547c5dff60aSchristos while (ISSPACE (* str)) 548c5dff60aSchristos ++ str; 549c5dff60aSchristos 550c5dff60aSchristos if (* str != '\0') 551c5dff60aSchristos return _("junk at end of line"); /* FIXME: would like to include `str' */ 552c5dff60aSchristos 553c5dff60aSchristos return NULL; 554c5dff60aSchristos } 555c5dff60aSchristos 556c5dff60aSchristos /* We couldn't parse it. */ 557c5dff60aSchristos return _("unrecognized instruction"); 558c5dff60aSchristos } 559c5dff60aSchristos 560c5dff60aSchristos /* Main entry point. 561c5dff60aSchristos This routine is called for each instruction to be assembled. 562c5dff60aSchristos STR points to the insn to be assembled. 563c5dff60aSchristos We assume all necessary tables have been initialized. 564c5dff60aSchristos The assembled instruction, less any fixups, is stored in BUF. 565c5dff60aSchristos Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value 566c5dff60aSchristos still needs to be converted to target byte order, otherwise BUF is an array 567c5dff60aSchristos of bytes in target byte order. 568c5dff60aSchristos The result is a pointer to the insn's entry in the opcode table, 569c5dff60aSchristos or NULL if an error occured (an error message will have already been 570c5dff60aSchristos printed). 571c5dff60aSchristos 572c5dff60aSchristos Note that when processing (non-alias) macro-insns, 573c5dff60aSchristos this function recurses. 574c5dff60aSchristos 575c5dff60aSchristos ??? It's possible to make this cpu-independent. 576c5dff60aSchristos One would have to deal with a few minor things. 577c5dff60aSchristos At this point in time doing so would be more of a curiosity than useful 578c5dff60aSchristos [for example this file isn't _that_ big], but keeping the possibility in 579c5dff60aSchristos mind helps keep the design clean. */ 580c5dff60aSchristos 581c5dff60aSchristos const CGEN_INSN * 582c5dff60aSchristos xstormy16_cgen_assemble_insn (CGEN_CPU_DESC cd, 583c5dff60aSchristos const char *str, 584c5dff60aSchristos CGEN_FIELDS *fields, 585c5dff60aSchristos CGEN_INSN_BYTES_PTR buf, 586c5dff60aSchristos char **errmsg) 587c5dff60aSchristos { 588c5dff60aSchristos const char *start; 589c5dff60aSchristos CGEN_INSN_LIST *ilist; 590c5dff60aSchristos const char *parse_errmsg = NULL; 591c5dff60aSchristos const char *insert_errmsg = NULL; 592c5dff60aSchristos int recognized_mnemonic = 0; 593c5dff60aSchristos 594c5dff60aSchristos /* Skip leading white space. */ 595c5dff60aSchristos while (ISSPACE (* str)) 596c5dff60aSchristos ++ str; 597c5dff60aSchristos 598c5dff60aSchristos /* The instructions are stored in hashed lists. 599c5dff60aSchristos Get the first in the list. */ 600c5dff60aSchristos ilist = CGEN_ASM_LOOKUP_INSN (cd, str); 601c5dff60aSchristos 602c5dff60aSchristos /* Keep looking until we find a match. */ 603c5dff60aSchristos start = str; 604c5dff60aSchristos for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) 605c5dff60aSchristos { 606c5dff60aSchristos const CGEN_INSN *insn = ilist->insn; 607c5dff60aSchristos recognized_mnemonic = 1; 608c5dff60aSchristos 609c5dff60aSchristos #ifdef CGEN_VALIDATE_INSN_SUPPORTED 610c5dff60aSchristos /* Not usually needed as unsupported opcodes 611c5dff60aSchristos shouldn't be in the hash lists. */ 612c5dff60aSchristos /* Is this insn supported by the selected cpu? */ 613c5dff60aSchristos if (! xstormy16_cgen_insn_supported (cd, insn)) 614c5dff60aSchristos continue; 615c5dff60aSchristos #endif 616c5dff60aSchristos /* If the RELAXED attribute is set, this is an insn that shouldn't be 617c5dff60aSchristos chosen immediately. Instead, it is used during assembler/linker 618c5dff60aSchristos relaxation if possible. */ 619c5dff60aSchristos if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0) 620c5dff60aSchristos continue; 621c5dff60aSchristos 622c5dff60aSchristos str = start; 623c5dff60aSchristos 624c5dff60aSchristos /* Skip this insn if str doesn't look right lexically. */ 625c5dff60aSchristos if (CGEN_INSN_RX (insn) != NULL && 626c5dff60aSchristos regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) 627c5dff60aSchristos continue; 628c5dff60aSchristos 629c5dff60aSchristos /* Allow parse/insert handlers to obtain length of insn. */ 630c5dff60aSchristos CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); 631c5dff60aSchristos 632c5dff60aSchristos parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields); 633c5dff60aSchristos if (parse_errmsg != NULL) 634c5dff60aSchristos continue; 635c5dff60aSchristos 636c5dff60aSchristos /* ??? 0 is passed for `pc'. */ 637c5dff60aSchristos insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf, 638c5dff60aSchristos (bfd_vma) 0); 639c5dff60aSchristos if (insert_errmsg != NULL) 640c5dff60aSchristos continue; 641c5dff60aSchristos 642c5dff60aSchristos /* It is up to the caller to actually output the insn and any 643c5dff60aSchristos queued relocs. */ 644c5dff60aSchristos return insn; 645c5dff60aSchristos } 646c5dff60aSchristos 647c5dff60aSchristos { 648c5dff60aSchristos static char errbuf[150]; 649c5dff60aSchristos const char *tmp_errmsg; 650c5dff60aSchristos #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS 651c5dff60aSchristos #define be_verbose 1 652c5dff60aSchristos #else 653c5dff60aSchristos #define be_verbose 0 654c5dff60aSchristos #endif 655c5dff60aSchristos 656c5dff60aSchristos if (be_verbose) 657c5dff60aSchristos { 658c5dff60aSchristos /* If requesting verbose error messages, use insert_errmsg. 659c5dff60aSchristos Failing that, use parse_errmsg. */ 660c5dff60aSchristos tmp_errmsg = (insert_errmsg ? insert_errmsg : 661c5dff60aSchristos parse_errmsg ? parse_errmsg : 662c5dff60aSchristos recognized_mnemonic ? 663c5dff60aSchristos _("unrecognized form of instruction") : 664c5dff60aSchristos _("unrecognized instruction")); 665c5dff60aSchristos 666c5dff60aSchristos if (strlen (start) > 50) 667c5dff60aSchristos /* xgettext:c-format */ 668c5dff60aSchristos sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start); 669c5dff60aSchristos else 670c5dff60aSchristos /* xgettext:c-format */ 671c5dff60aSchristos sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start); 672c5dff60aSchristos } 673c5dff60aSchristos else 674c5dff60aSchristos { 675c5dff60aSchristos if (strlen (start) > 50) 676c5dff60aSchristos /* xgettext:c-format */ 677c5dff60aSchristos sprintf (errbuf, _("bad instruction `%.50s...'"), start); 678c5dff60aSchristos else 679c5dff60aSchristos /* xgettext:c-format */ 680c5dff60aSchristos sprintf (errbuf, _("bad instruction `%.50s'"), start); 681c5dff60aSchristos } 682c5dff60aSchristos 683c5dff60aSchristos *errmsg = errbuf; 684c5dff60aSchristos return NULL; 685c5dff60aSchristos } 686c5dff60aSchristos } 687