
1: /* Assembler interface for targets using CGEN. -*- C -*- 2: CGEN: Cpu tools GENerator 3: 4: THIS FILE IS MACHINE GENERATED WITH CGEN. 5: - the resultant file is machine generated, cgen-asm.in isn't 6: 7: Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005, 2007 8: Free Software Foundation, Inc. 9: 10: This file is part of libopcodes. 11: 12: This library is free software; you can redistribute it and/or modify 13: it under the terms of the GNU General Public License as published by 14: the Free Software Foundation; either version 3, or (at your option) 15: any later version. 16: 17: It is distributed in the hope that it will be useful, but WITHOUT 18: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 19: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 20: License for more details. 21: 22: You should have received a copy of the GNU General Public License 23: along with this program; if not, write to the Free Software Foundation, Inc., 24: 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 25: 26: 27: /* ??? Eventually more and more of this stuff can go to cpu-independent files. 28: Keep that in mind. */ 29: 30: #include "sysdep.h" 31: #include <stdio.h> 32: #include "ansidecl.h" 33: #include "bfd.h" 34: #include "symcat.h" 35: #include "@prefix@-desc.h" 36: #include "@prefix@-opc.h" 37: #include "opintl.h" 38: #include "xregex.h" 39: #include "libiberty.h" 40: #include "safe-ctype.h" 41: 42: #undef min 43: #define min(a,b) ((a) < (b) ? (a) : (b)) 44: #undef max 45: #define max(a,b) ((a) > (b) ? (a) : (b)) 46: 47: static const char * parse_insn_normal 48: (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *); 49: ^L 50: /* -- assembler routines inserted here. */ 51: ^L 52: 53: /* Regex construction routine. 54: 55: This translates an opcode syntax string into a regex string, 56: by replacing any non-character syntax element (such as an 57: opcode) with the pattern '.*' 58: 59: It then compiles the regex and stores it in the opcode, for 60: later use by @arch@_cgen_assemble_insn 61: 62: Returns NULL for success, an error message for failure. */ 63: 64: char * 65: @arch@_cgen_build_insn_regex (CGEN_INSN *insn) 66: { 67: CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn); 68: const char *mnem = CGEN_INSN_MNEMONIC (insn); 69: char rxbuf[CGEN_MAX_RX_ELEMENTS]; 70: char *rx = rxbuf; 71: const CGEN_SYNTAX_CHAR_TYPE *syn; 72: int reg_err; 73: 74: syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc)); 75: 76: /* Mnemonics come first in the syntax string. */ 77: if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 78: return _("missing mnemonic in syntax string"); 79: ++syn; 80: 81: /* Generate a case sensitive regular expression that emulates case 82: insensitive matching in the "C" locale. We cannot generate a case 83: insensitive regular expression because in Turkish locales, 'i' and 'I' 84: are not equal modulo case conversion. */ 85: 86: /* Copy the literal mnemonic out of the insn. */ 87: for (; *mnem; mnem++) 88: { 89: char c = *mnem; 90: 91: if (ISALPHA (c)) 92: { 93: *rx++ = '['; 94: *rx++ = TOLOWER (c); 95: *rx++ = TOUPPER (c); 96: *rx++ = ']'; 97: } 98: else 99: *rx++ = c; 100: } 101: 102: /* Copy any remaining literals from the syntax string into the rx. */ 103: for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn) 104: { 105: if (CGEN_SYNTAX_CHAR_P (* syn)) 106: { 107: char c = CGEN_SYNTAX_CHAR (* syn); 108: 109: switch (c) 110: { 111: /* Escape any regex metacharacters in the syntax. */ 112: case '.': case '[': case '\\': 113: case '*': case '^': case '$': 114: 115: #ifdef CGEN_ESCAPE_EXTENDED_REGEX 116: case '?': case '{': case '}': 117: case '(': case ')': case '*': 118: case '|': case '+': case ']': 119: #endif 120: *rx++ = '\\'; 121: *rx++ = c; 122: break; 123: 124: default: 125: if (ISALPHA (c)) 126: { 127: *rx++ = '['; 128: *rx++ = TOLOWER (c); 129: *rx++ = TOUPPER (c); 130: *rx++ = ']'; 131: } 132: else 133: *rx++ = c; 134: break; 135: } 136: } 137: else 138: { 139: /* Replace non-syntax fields with globs. */ 140: *rx++ = '.'; 141: *rx++ = '*'; 142: } 143: } 144: 145: /* Trailing whitespace ok. */ 146: * rx++ = '['; 147: * rx++ = ' '; 148: * rx++ = '\t'; 149: * rx++ = ']'; 150: * rx++ = '*'; 151: 152: /* But anchor it after that. */ 153: * rx++ = '$'; 154: * rx = '\0'; 155: 156: CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t)); 157: reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB); 158: 159: if (reg_err == 0) 160: return NULL; 161: else 162: { 163: static char msg[80]; 164: 165: regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80); 166: regfree ((regex_t *) CGEN_INSN_RX (insn)); 167: free (CGEN_INSN_RX (insn)); 168: (CGEN_INSN_RX (insn)) = NULL; 169: return msg; 170: } 171: } 172: 173: ^L 174: /* Default insn parser. 175: 176: The syntax string is scanned and operands are parsed and stored in FIELDS. 177: Relocs are queued as we go via other callbacks. 178: 179: ??? Note that this is currently an all-or-nothing parser. If we fail to 180: parse the instruction, we return 0 and the caller will start over from 181: the beginning. Backtracking will be necessary in parsing subexpressions, 182: but that can be handled there. Not handling backtracking here may get 183: expensive in the case of the m68k. Deal with later. 184: 185: Returns NULL for success, an error message for failure. */ 186: 187: static const char * 188: parse_insn_normal (CGEN_CPU_DESC cd, 189: const CGEN_INSN *insn, 190: const char **strp, 191: CGEN_FIELDS *fields) 192: { 193: /* ??? Runtime added insns not handled yet. */ 194: const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 195: const char *str = *strp; 196: const char *errmsg; 197: const char *p; 198: const CGEN_SYNTAX_CHAR_TYPE * syn; 199: #ifdef CGEN_MNEMONIC_OPERANDS 200: /* FIXME: wip */ 201: int past_opcode_p; 202: #endif 203: 204: /* For now we assume the mnemonic is first (there are no leading operands). 205: We can parse it without needing to set up operand parsing. 206: GAS's input scrubber will ensure mnemonics are lowercase, but we may 207: not be called from GAS. */ 208: p = CGEN_INSN_MNEMONIC (insn); 209: while (*p && TOLOWER (*p) == TOLOWER (*str)) 210: ++p, ++str; 211: 212: if (* p) 213: return _("unrecognized instruction"); 214: 215: #ifndef CGEN_MNEMONIC_OPERANDS 216: if (* str && ! ISSPACE (* str)) 217: return _("unrecognized instruction"); 218: #endif 219: 220: CGEN_INIT_PARSE (cd); 221: cgen_init_parse_operand (cd); 222: #ifdef CGEN_MNEMONIC_OPERANDS 223: past_opcode_p = 0; 224: #endif 225: 226: /* We don't check for (*str != '\0') here because we want to parse 227: any trailing fake arguments in the syntax string. */ 228: syn = CGEN_SYNTAX_STRING (syntax); 229: 230: /* Mnemonics come first for now, ensure valid string. */ 231: if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 232: abort (); 233: 234: ++syn; 235: 236: while (* syn != 0) 237: { 238: /* Non operand chars must match exactly. */ 239: if (CGEN_SYNTAX_CHAR_P (* syn)) 240: { 241: /* FIXME: While we allow for non-GAS callers above, we assume the 242: first char after the mnemonic part is a space. */ 243: /* FIXME: We also take inappropriate advantage of the fact that 244: GAS's input scrubber will remove extraneous blanks. */ 245: if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn))) 246: { 247: #ifdef CGEN_MNEMONIC_OPERANDS 248: if (CGEN_SYNTAX_CHAR(* syn) == ' ') 249: past_opcode_p = 1; 250: #endif 251: ++ syn; 252: ++ str; 253: } 254: else if (*str) 255: { 256: /* Syntax char didn't match. Can't be this insn. */ 257: static char msg [80]; 258: 259: /* xgettext:c-format */ 260: sprintf (msg, _("syntax error (expected char `%c', found `%c')"), 261: CGEN_SYNTAX_CHAR(*syn), *str); 262: return msg; 263: } 264: else 265: { 266: /* Ran out of input. */ 267: static char msg [80]; 268: 269: /* xgettext:c-format */ 270: sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"), 271: CGEN_SYNTAX_CHAR(*syn)); 272: return msg; 273: } 274: continue; 275: } 276: 277: /* We have an operand of some sort. */ 278: errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), 279: &str, fields); 280: if (errmsg) 281: return errmsg; 282: 283: /* Done with this operand, continue with next one. */ 284: ++ syn; 285: } 286: 287: /* If we're at the end of the syntax string, we're done. */ 288: if (* syn == 0) 289: { 290: /* FIXME: For the moment we assume a valid `str' can only contain 291: blanks now. IE: We needn't try again with a longer version of 292: the insn and it is assumed that longer versions of insns appear 293: before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ 294: while (ISSPACE (* str)) 295: ++ str; 296: 297: if (* str != '\0') 298: return _("junk at end of line"); /* FIXME: would like to include `str' */ 299: 300: return NULL; 301: } 302: 303: /* We couldn't parse it. */ 304: return _("unrecognized instruction"); 305: } 306: ^L 307: /* Main entry point. 308: This routine is called for each instruction to be assembled. 309: STR points to the insn to be assembled. 310: We assume all necessary tables have been initialized. 311: The assembled instruction, less any fixups, is stored in BUF. 312: Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value 313: still needs to be converted to target byte order, otherwise BUF is an array 314: of bytes in target byte order. 315: The result is a pointer to the insn's entry in the opcode table, 316: or NULL if an error occured (an error message will have already been 317: printed). 318: 319: Note that when processing (non-alias) macro-insns, 320: this function recurses. 321: 322: ??? It's possible to make this cpu-independent. 323: One would have to deal with a few minor things. 324: At this point in time doing so would be more of a curiosity than useful 325: [for example this file isn't _that_ big], but keeping the possibility in 326: mind helps keep the design clean. */ 327: 328: const CGEN_INSN * 329: @arch@_cgen_assemble_insn (CGEN_CPU_DESC cd, 330: const char *str, 331: CGEN_FIELDS *fields, 332: CGEN_INSN_BYTES_PTR buf, 333: char **errmsg) 334: { 335: const char *start; 336: CGEN_INSN_LIST *ilist; 337: const char *parse_errmsg = NULL; 338: const char *insert_errmsg = NULL; 339: int recognized_mnemonic = 0; 340: 341: /* Skip leading white space. */ 342: while (ISSPACE (* str)) 343: ++ str; 344: 345: /* The instructions are stored in hashed lists. 346: Get the first in the list. */ 347: ilist = CGEN_ASM_LOOKUP_INSN (cd, str); 348: 349: /* Keep looking until we find a match. */ 350: start = str; 351: for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) 352: { 353: const CGEN_INSN *insn = ilist->insn; 354: recognized_mnemonic = 1; 355: 356: #ifdef CGEN_VALIDATE_INSN_SUPPORTED 357: /* Not usually needed as unsupported opcodes 358: shouldn't be in the hash lists. */ 359: /* Is this insn supported by the selected cpu? */ 360: if (! @arch@_cgen_insn_supported (cd, insn)) 361: continue; 362: #endif 363: /* If the RELAXED attribute is set, this is an insn that shouldn't be 364: chosen immediately. Instead, it is used during assembler/linker 365: relaxation if possible. */ 366: if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0) 367: continue; 368: 369: str = start; 370: 371: /* Skip this insn if str doesn't look right lexically. */ 372: if (CGEN_INSN_RX (insn) != NULL && 373: regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) 374: continue; 375: 376: /* Allow parse/insert handlers to obtain length of insn. */ 377: CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); 378: 379: parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields); 380: if (parse_errmsg != NULL) 381: continue; 382: 383: /* ??? 0 is passed for `pc'. */ 384: insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf, 385: (bfd_vma) 0); 386: if (insert_errmsg != NULL) 387: continue; 388: 389: /* It is up to the caller to actually output the insn and any 390: queued relocs. */ 391: return insn; 392: } 393: 394: { 395: static char errbuf[150]; 396: #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS 397: const char *tmp_errmsg; 398: 399: /* If requesting verbose error messages, use insert_errmsg. 400: Failing that, use parse_errmsg. */ 401: tmp_errmsg = (insert_errmsg ? insert_errmsg : 402: parse_errmsg ? parse_errmsg : 403: recognized_mnemonic ? 404: _("unrecognized form of instruction") : 405: _("unrecognized instruction")); 406: 407: if (strlen (start) > 50) 408: /* xgettext:c-format */ 409: sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start); 410: else 411: /* xgettext:c-format */ 412: sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start); 413: #else 414: if (strlen (start) > 50) 415: /* xgettext:c-format */ 416: sprintf (errbuf, _("bad instruction `%.50s...'"), start); 417: else 418: /* xgettext:c-format */ 419: sprintf (errbuf, _("bad instruction `%.50s'"), start); 420: #endif 421: 422: *errmsg = errbuf; 423: return NULL; 424: } 425: }