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 (C) 1996-2017 Free Software Foundation, Inc. 8 9 This file is part of libopcodes. 10 11 This library is free software; you can redistribute it and/or modify 12 it under the terms of the GNU General Public License as published by 13 the Free Software Foundation; either version 3, or (at your option) 14 any later version. 15 16 It is distributed in the hope that it will be useful, but WITHOUT 17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 18 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 19 License for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with this program; if not, write to the Free Software Foundation, Inc., 23 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 24 25 26/* ??? Eventually more and more of this stuff can go to cpu-independent files. 27 Keep that in mind. */ 28 29#include "sysdep.h" 30#include <stdio.h> 31#include "ansidecl.h" 32#include "bfd.h" 33#include "symcat.h" 34#include "or1k-desc.h" 35#include "or1k-opc.h" 36#include "opintl.h" 37#include "xregex.h" 38#include "libiberty.h" 39#include "safe-ctype.h" 40 41#undef min 42#define min(a,b) ((a) < (b) ? (a) : (b)) 43#undef max 44#define max(a,b) ((a) > (b) ? (a) : (b)) 45 46static const char * parse_insn_normal 47 (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *); 48 49/* -- assembler routines inserted here. */ 50 51/* -- asm.c */ 52 53static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'"); 54 55#define CGEN_VERBOSE_ASSEMBLER_ERRORS 56 57static const char * 58parse_disp26 (CGEN_CPU_DESC cd, 59 const char ** strp, 60 int opindex, 61 int opinfo, 62 enum cgen_parse_operand_result * resultp, 63 bfd_vma * valuep) 64{ 65 const char *errmsg = NULL; 66 enum cgen_parse_operand_result result_type; 67 68 if (strncasecmp (*strp, "plt(", 4) == 0) 69 { 70 bfd_vma value; 71 72 *strp += 4; 73 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26, 74 & result_type, & value); 75 if (**strp != ')') 76 return MISSING_CLOSING_PARENTHESIS; 77 ++*strp; 78 if (errmsg == NULL 79 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 80 value = (value >> 2) & 0xffff; 81 *valuep = value; 82 return errmsg; 83 } 84 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep); 85} 86 87static const char * 88parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep) 89{ 90 const char *errmsg; 91 enum cgen_parse_operand_result result_type; 92 long ret; 93 94 if (**strp == '#') 95 ++*strp; 96 97 if (strncasecmp (*strp, "hi(", 3) == 0) 98 { 99 bfd_vma value; 100 101 *strp += 3; 102 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16, 103 & result_type, & value); 104 if (**strp != ')') 105 errmsg = MISSING_CLOSING_PARENTHESIS; 106 ++*strp; 107 108 ret = value; 109 110 if (errmsg == NULL 111 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 112 { 113 ret >>= 16; 114 ret &= 0xffff; 115 ret = (ret ^ 0x8000) - 0x8000; 116 } 117 } 118 else if (strncasecmp (*strp, "lo(", 3) == 0) 119 { 120 bfd_vma value; 121 122 *strp += 3; 123 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16, 124 & result_type, & value); 125 if (**strp != ')') 126 return MISSING_CLOSING_PARENTHESIS; 127 ++*strp; 128 129 ret = value; 130 131 if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 132 { 133 ret &= 0xffff; 134 ret = (ret ^ 0x8000) - 0x8000; 135 } 136 } 137 else if (strncasecmp (*strp, "got(", 4) == 0) 138 { 139 bfd_vma value; 140 141 *strp += 4; 142 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_GOT16, 143 & result_type, & value); 144 if (**strp != ')') 145 return MISSING_CLOSING_PARENTHESIS; 146 ++*strp; 147 if (errmsg == NULL 148 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 149 value &= 0xffff; 150 *valuep = value; 151 return errmsg; 152 } 153 else if (strncasecmp (*strp, "gotpchi(", 8) == 0) 154 { 155 bfd_vma value; 156 157 *strp += 8; 158 errmsg = cgen_parse_address (cd, strp, opindex, 159 BFD_RELOC_OR1K_GOTPC_HI16, 160 & result_type, & value); 161 if (**strp != ')') 162 return MISSING_CLOSING_PARENTHESIS; 163 ++*strp; 164 if (errmsg == NULL 165 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 166 value = (value >> 16) & 0xffff; 167 *valuep = value; 168 return errmsg; 169 } 170 else if (strncasecmp (*strp, "gotpclo(", 8) == 0) 171 { 172 bfd_vma value; 173 174 *strp += 8; 175 errmsg = cgen_parse_address (cd, strp, opindex, 176 BFD_RELOC_OR1K_GOTPC_LO16, 177 &result_type, &value); 178 if (**strp != ')') 179 return MISSING_CLOSING_PARENTHESIS; 180 ++*strp; 181 if (errmsg == NULL 182 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 183 value &= 0xffff; 184 *valuep = value; 185 return errmsg; 186 } 187 else if (strncasecmp (*strp, "gotoffhi(", 9) == 0) 188 { 189 bfd_vma value; 190 191 *strp += 9; 192 errmsg = cgen_parse_address (cd, strp, opindex, 193 BFD_RELOC_OR1K_GOTOFF_HI16, 194 & result_type, & value); 195 196 if (**strp != ')') 197 return MISSING_CLOSING_PARENTHESIS; 198 ++*strp; 199 if (errmsg == NULL 200 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 201 value = (value >> 16) & 0xffff; 202 *valuep = value; 203 return errmsg; 204 } 205 else if (strncasecmp (*strp, "gotofflo(", 9) == 0) 206 { 207 bfd_vma value; 208 209 *strp += 9; 210 errmsg = cgen_parse_address (cd, strp, opindex, 211 BFD_RELOC_OR1K_GOTOFF_LO16, 212 &result_type, &value); 213 if (**strp != ')') 214 return MISSING_CLOSING_PARENTHESIS; 215 ++*strp; 216 if (errmsg == NULL 217 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 218 value &= 0xffff; 219 *valuep = value; 220 return errmsg; 221 } 222 else if (strncasecmp (*strp, "tlsgdhi(", 8) == 0) 223 { 224 bfd_vma value; 225 226 *strp += 8; 227 errmsg = cgen_parse_address (cd, strp, opindex, 228 BFD_RELOC_OR1K_TLS_GD_HI16, 229 & result_type, & value); 230 231 if (**strp != ')') 232 return MISSING_CLOSING_PARENTHESIS; 233 ++*strp; 234 if (errmsg == NULL 235 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 236 value = (value >> 16) & 0xffff; 237 *valuep = value; 238 return errmsg; 239 } 240 else if (strncasecmp (*strp, "tlsgdlo(", 8) == 0) 241 { 242 bfd_vma value; 243 244 *strp += 8; 245 errmsg = cgen_parse_address (cd, strp, opindex, 246 BFD_RELOC_OR1K_TLS_GD_LO16, 247 &result_type, &value); 248 if (**strp != ')') 249 return MISSING_CLOSING_PARENTHESIS; 250 ++*strp; 251 if (errmsg == NULL 252 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 253 value &= 0xffff; 254 *valuep = value; 255 return errmsg; 256 } 257 else if (strncasecmp (*strp, "tlsldmhi(", 9) == 0) 258 { 259 bfd_vma value; 260 261 *strp += 9; 262 errmsg = cgen_parse_address (cd, strp, opindex, 263 BFD_RELOC_OR1K_TLS_LDM_HI16, 264 & result_type, & value); 265 266 if (**strp != ')') 267 return MISSING_CLOSING_PARENTHESIS; 268 ++*strp; 269 if (errmsg == NULL 270 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 271 value = (value >> 16) & 0xffff; 272 *valuep = value; 273 return errmsg; 274 } 275 else if (strncasecmp (*strp, "tlsldmlo(", 9) == 0) 276 { 277 bfd_vma value; 278 279 *strp += 9; 280 errmsg = cgen_parse_address (cd, strp, opindex, 281 BFD_RELOC_OR1K_TLS_LDM_LO16, 282 &result_type, &value); 283 if (**strp != ')') 284 return MISSING_CLOSING_PARENTHESIS; 285 ++*strp; 286 if (errmsg == NULL 287 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 288 value &= 0xffff; 289 *valuep = value; 290 return errmsg; 291 } 292 else if (strncasecmp (*strp, "dtpoffhi(", 9) == 0) 293 { 294 bfd_vma value; 295 296 *strp += 9; 297 errmsg = cgen_parse_address (cd, strp, opindex, 298 BFD_RELOC_OR1K_TLS_LDO_HI16, 299 & result_type, & value); 300 301 if (**strp != ')') 302 return MISSING_CLOSING_PARENTHESIS; 303 ++*strp; 304 if (errmsg == NULL 305 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 306 value = (value >> 16) & 0xffff; 307 *valuep = value; 308 return errmsg; 309 } 310 else if (strncasecmp (*strp, "dtpofflo(", 9) == 0) 311 { 312 bfd_vma value; 313 314 *strp += 9; 315 errmsg = cgen_parse_address (cd, strp, opindex, 316 BFD_RELOC_OR1K_TLS_LDO_LO16, 317 &result_type, &value); 318 if (**strp != ')') 319 return MISSING_CLOSING_PARENTHESIS; 320 ++*strp; 321 if (errmsg == NULL 322 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 323 value &= 0xffff; 324 *valuep = value; 325 return errmsg; 326 } 327 else if (strncasecmp (*strp, "gottpoffhi(", 11) == 0) 328 { 329 bfd_vma value; 330 331 *strp += 11; 332 errmsg = cgen_parse_address (cd, strp, opindex, 333 BFD_RELOC_OR1K_TLS_IE_HI16, 334 & result_type, & value); 335 336 if (**strp != ')') 337 return MISSING_CLOSING_PARENTHESIS; 338 ++*strp; 339 if (errmsg == NULL 340 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 341 value = (value >> 16) & 0xffff; 342 *valuep = value; 343 return errmsg; 344 } 345 else if (strncasecmp (*strp, "gottpofflo(", 11) == 0) 346 { 347 bfd_vma value; 348 349 *strp += 11; 350 errmsg = cgen_parse_address (cd, strp, opindex, 351 BFD_RELOC_OR1K_TLS_IE_LO16, 352 &result_type, &value); 353 if (**strp != ')') 354 return MISSING_CLOSING_PARENTHESIS; 355 ++*strp; 356 if (errmsg == NULL 357 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 358 value &= 0xffff; 359 *valuep = value; 360 return errmsg; 361 } 362 else if (strncasecmp (*strp, "tpoffhi(", 8) == 0) 363 { 364 bfd_vma value; 365 366 *strp += 8; 367 errmsg = cgen_parse_address (cd, strp, opindex, 368 BFD_RELOC_OR1K_TLS_LE_HI16, 369 & result_type, & value); 370 371 if (**strp != ')') 372 return MISSING_CLOSING_PARENTHESIS; 373 ++*strp; 374 if (errmsg == NULL 375 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 376 value = (value >> 16) & 0xffff; 377 *valuep = value; 378 return errmsg; 379 } 380 else if (strncasecmp (*strp, "tpofflo(", 8) == 0) 381 { 382 bfd_vma value; 383 384 *strp += 8; 385 errmsg = cgen_parse_address (cd, strp, opindex, 386 BFD_RELOC_OR1K_TLS_LE_LO16, 387 &result_type, &value); 388 if (**strp != ')') 389 return MISSING_CLOSING_PARENTHESIS; 390 ++*strp; 391 if (errmsg == NULL 392 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 393 value &= 0xffff; 394 *valuep = value; 395 return errmsg; 396 } 397 else 398 { 399 long value; 400 errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value); 401 ret = value; 402 } 403 404 if (errmsg == NULL) 405 *valuep = ret; 406 407 return errmsg; 408} 409 410static const char * 411parse_uimm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, unsigned long * valuep) 412{ 413 const char *errmsg = parse_simm16(cd, strp, opindex, (long *) valuep); 414 415 if (errmsg == NULL) 416 *valuep &= 0xffff; 417 return errmsg; 418} 419 420/* -- */ 421 422const char * or1k_cgen_parse_operand 423 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 424 425/* Main entry point for operand parsing. 426 427 This function is basically just a big switch statement. Earlier versions 428 used tables to look up the function to use, but 429 - if the table contains both assembler and disassembler functions then 430 the disassembler contains much of the assembler and vice-versa, 431 - there's a lot of inlining possibilities as things grow, 432 - using a switch statement avoids the function call overhead. 433 434 This function could be moved into `parse_insn_normal', but keeping it 435 separate makes clear the interface between `parse_insn_normal' and each of 436 the handlers. */ 437 438const char * 439or1k_cgen_parse_operand (CGEN_CPU_DESC cd, 440 int opindex, 441 const char ** strp, 442 CGEN_FIELDS * fields) 443{ 444 const char * errmsg = NULL; 445 /* Used by scalar operands that still need to be parsed. */ 446 long junk ATTRIBUTE_UNUSED; 447 448 switch (opindex) 449 { 450 case OR1K_OPERAND_DISP26 : 451 { 452 bfd_vma value = 0; 453 errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL, & value); 454 fields->f_disp26 = value; 455 } 456 break; 457 case OR1K_OPERAND_RA : 458 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2); 459 break; 460 case OR1K_OPERAND_RADF : 461 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1); 462 break; 463 case OR1K_OPERAND_RASF : 464 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2); 465 break; 466 case OR1K_OPERAND_RB : 467 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3); 468 break; 469 case OR1K_OPERAND_RBDF : 470 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1); 471 break; 472 case OR1K_OPERAND_RBSF : 473 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3); 474 break; 475 case OR1K_OPERAND_RD : 476 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1); 477 break; 478 case OR1K_OPERAND_RDDF : 479 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1); 480 break; 481 case OR1K_OPERAND_RDSF : 482 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1); 483 break; 484 case OR1K_OPERAND_SIMM16 : 485 errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16)); 486 break; 487 case OR1K_OPERAND_SIMM16_SPLIT : 488 errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split)); 489 break; 490 case OR1K_OPERAND_UIMM16 : 491 errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16)); 492 break; 493 case OR1K_OPERAND_UIMM16_SPLIT : 494 errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split)); 495 break; 496 case OR1K_OPERAND_UIMM6 : 497 errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6)); 498 break; 499 500 default : 501 /* xgettext:c-format */ 502 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex); 503 abort (); 504 } 505 506 return errmsg; 507} 508 509cgen_parse_fn * const or1k_cgen_parse_handlers[] = 510{ 511 parse_insn_normal, 512}; 513 514void 515or1k_cgen_init_asm (CGEN_CPU_DESC cd) 516{ 517 or1k_cgen_init_opcode_table (cd); 518 or1k_cgen_init_ibld_table (cd); 519 cd->parse_handlers = & or1k_cgen_parse_handlers[0]; 520 cd->parse_operand = or1k_cgen_parse_operand; 521#ifdef CGEN_ASM_INIT_HOOK 522CGEN_ASM_INIT_HOOK 523#endif 524} 525 526 527 528/* Regex construction routine. 529 530 This translates an opcode syntax string into a regex string, 531 by replacing any non-character syntax element (such as an 532 opcode) with the pattern '.*' 533 534 It then compiles the regex and stores it in the opcode, for 535 later use by or1k_cgen_assemble_insn 536 537 Returns NULL for success, an error message for failure. */ 538 539char * 540or1k_cgen_build_insn_regex (CGEN_INSN *insn) 541{ 542 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn); 543 const char *mnem = CGEN_INSN_MNEMONIC (insn); 544 char rxbuf[CGEN_MAX_RX_ELEMENTS]; 545 char *rx = rxbuf; 546 const CGEN_SYNTAX_CHAR_TYPE *syn; 547 int reg_err; 548 549 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc)); 550 551 /* Mnemonics come first in the syntax string. */ 552 if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 553 return _("missing mnemonic in syntax string"); 554 ++syn; 555 556 /* Generate a case sensitive regular expression that emulates case 557 insensitive matching in the "C" locale. We cannot generate a case 558 insensitive regular expression because in Turkish locales, 'i' and 'I' 559 are not equal modulo case conversion. */ 560 561 /* Copy the literal mnemonic out of the insn. */ 562 for (; *mnem; mnem++) 563 { 564 char c = *mnem; 565 566 if (ISALPHA (c)) 567 { 568 *rx++ = '['; 569 *rx++ = TOLOWER (c); 570 *rx++ = TOUPPER (c); 571 *rx++ = ']'; 572 } 573 else 574 *rx++ = c; 575 } 576 577 /* Copy any remaining literals from the syntax string into the rx. */ 578 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn) 579 { 580 if (CGEN_SYNTAX_CHAR_P (* syn)) 581 { 582 char c = CGEN_SYNTAX_CHAR (* syn); 583 584 switch (c) 585 { 586 /* Escape any regex metacharacters in the syntax. */ 587 case '.': case '[': case '\\': 588 case '*': case '^': case '$': 589 590#ifdef CGEN_ESCAPE_EXTENDED_REGEX 591 case '?': case '{': case '}': 592 case '(': case ')': case '*': 593 case '|': case '+': case ']': 594#endif 595 *rx++ = '\\'; 596 *rx++ = c; 597 break; 598 599 default: 600 if (ISALPHA (c)) 601 { 602 *rx++ = '['; 603 *rx++ = TOLOWER (c); 604 *rx++ = TOUPPER (c); 605 *rx++ = ']'; 606 } 607 else 608 *rx++ = c; 609 break; 610 } 611 } 612 else 613 { 614 /* Replace non-syntax fields with globs. */ 615 *rx++ = '.'; 616 *rx++ = '*'; 617 } 618 } 619 620 /* Trailing whitespace ok. */ 621 * rx++ = '['; 622 * rx++ = ' '; 623 * rx++ = '\t'; 624 * rx++ = ']'; 625 * rx++ = '*'; 626 627 /* But anchor it after that. */ 628 * rx++ = '$'; 629 * rx = '\0'; 630 631 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t)); 632 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB); 633 634 if (reg_err == 0) 635 return NULL; 636 else 637 { 638 static char msg[80]; 639 640 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80); 641 regfree ((regex_t *) CGEN_INSN_RX (insn)); 642 free (CGEN_INSN_RX (insn)); 643 (CGEN_INSN_RX (insn)) = NULL; 644 return msg; 645 } 646} 647 648 649/* Default insn parser. 650 651 The syntax string is scanned and operands are parsed and stored in FIELDS. 652 Relocs are queued as we go via other callbacks. 653 654 ??? Note that this is currently an all-or-nothing parser. If we fail to 655 parse the instruction, we return 0 and the caller will start over from 656 the beginning. Backtracking will be necessary in parsing subexpressions, 657 but that can be handled there. Not handling backtracking here may get 658 expensive in the case of the m68k. Deal with later. 659 660 Returns NULL for success, an error message for failure. */ 661 662static const char * 663parse_insn_normal (CGEN_CPU_DESC cd, 664 const CGEN_INSN *insn, 665 const char **strp, 666 CGEN_FIELDS *fields) 667{ 668 /* ??? Runtime added insns not handled yet. */ 669 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 670 const char *str = *strp; 671 const char *errmsg; 672 const char *p; 673 const CGEN_SYNTAX_CHAR_TYPE * syn; 674#ifdef CGEN_MNEMONIC_OPERANDS 675 /* FIXME: wip */ 676 int past_opcode_p; 677#endif 678 679 /* For now we assume the mnemonic is first (there are no leading operands). 680 We can parse it without needing to set up operand parsing. 681 GAS's input scrubber will ensure mnemonics are lowercase, but we may 682 not be called from GAS. */ 683 p = CGEN_INSN_MNEMONIC (insn); 684 while (*p && TOLOWER (*p) == TOLOWER (*str)) 685 ++p, ++str; 686 687 if (* p) 688 return _("unrecognized instruction"); 689 690#ifndef CGEN_MNEMONIC_OPERANDS 691 if (* str && ! ISSPACE (* str)) 692 return _("unrecognized instruction"); 693#endif 694 695 CGEN_INIT_PARSE (cd); 696 cgen_init_parse_operand (cd); 697#ifdef CGEN_MNEMONIC_OPERANDS 698 past_opcode_p = 0; 699#endif 700 701 /* We don't check for (*str != '\0') here because we want to parse 702 any trailing fake arguments in the syntax string. */ 703 syn = CGEN_SYNTAX_STRING (syntax); 704 705 /* Mnemonics come first for now, ensure valid string. */ 706 if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 707 abort (); 708 709 ++syn; 710 711 while (* syn != 0) 712 { 713 /* Non operand chars must match exactly. */ 714 if (CGEN_SYNTAX_CHAR_P (* syn)) 715 { 716 /* FIXME: While we allow for non-GAS callers above, we assume the 717 first char after the mnemonic part is a space. */ 718 /* FIXME: We also take inappropriate advantage of the fact that 719 GAS's input scrubber will remove extraneous blanks. */ 720 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn))) 721 { 722#ifdef CGEN_MNEMONIC_OPERANDS 723 if (CGEN_SYNTAX_CHAR(* syn) == ' ') 724 past_opcode_p = 1; 725#endif 726 ++ syn; 727 ++ str; 728 } 729 else if (*str) 730 { 731 /* Syntax char didn't match. Can't be this insn. */ 732 static char msg [80]; 733 734 /* xgettext:c-format */ 735 sprintf (msg, _("syntax error (expected char `%c', found `%c')"), 736 CGEN_SYNTAX_CHAR(*syn), *str); 737 return msg; 738 } 739 else 740 { 741 /* Ran out of input. */ 742 static char msg [80]; 743 744 /* xgettext:c-format */ 745 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"), 746 CGEN_SYNTAX_CHAR(*syn)); 747 return msg; 748 } 749 continue; 750 } 751 752#ifdef CGEN_MNEMONIC_OPERANDS 753 (void) past_opcode_p; 754#endif 755 /* We have an operand of some sort. */ 756 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields); 757 if (errmsg) 758 return errmsg; 759 760 /* Done with this operand, continue with next one. */ 761 ++ syn; 762 } 763 764 /* If we're at the end of the syntax string, we're done. */ 765 if (* syn == 0) 766 { 767 /* FIXME: For the moment we assume a valid `str' can only contain 768 blanks now. IE: We needn't try again with a longer version of 769 the insn and it is assumed that longer versions of insns appear 770 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ 771 while (ISSPACE (* str)) 772 ++ str; 773 774 if (* str != '\0') 775 return _("junk at end of line"); /* FIXME: would like to include `str' */ 776 777 return NULL; 778 } 779 780 /* We couldn't parse it. */ 781 return _("unrecognized instruction"); 782} 783 784/* Main entry point. 785 This routine is called for each instruction to be assembled. 786 STR points to the insn to be assembled. 787 We assume all necessary tables have been initialized. 788 The assembled instruction, less any fixups, is stored in BUF. 789 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value 790 still needs to be converted to target byte order, otherwise BUF is an array 791 of bytes in target byte order. 792 The result is a pointer to the insn's entry in the opcode table, 793 or NULL if an error occured (an error message will have already been 794 printed). 795 796 Note that when processing (non-alias) macro-insns, 797 this function recurses. 798 799 ??? It's possible to make this cpu-independent. 800 One would have to deal with a few minor things. 801 At this point in time doing so would be more of a curiosity than useful 802 [for example this file isn't _that_ big], but keeping the possibility in 803 mind helps keep the design clean. */ 804 805const CGEN_INSN * 806or1k_cgen_assemble_insn (CGEN_CPU_DESC cd, 807 const char *str, 808 CGEN_FIELDS *fields, 809 CGEN_INSN_BYTES_PTR buf, 810 char **errmsg) 811{ 812 const char *start; 813 CGEN_INSN_LIST *ilist; 814 const char *parse_errmsg = NULL; 815 const char *insert_errmsg = NULL; 816 int recognized_mnemonic = 0; 817 818 /* Skip leading white space. */ 819 while (ISSPACE (* str)) 820 ++ str; 821 822 /* The instructions are stored in hashed lists. 823 Get the first in the list. */ 824 ilist = CGEN_ASM_LOOKUP_INSN (cd, str); 825 826 /* Keep looking until we find a match. */ 827 start = str; 828 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) 829 { 830 const CGEN_INSN *insn = ilist->insn; 831 recognized_mnemonic = 1; 832 833#ifdef CGEN_VALIDATE_INSN_SUPPORTED 834 /* Not usually needed as unsupported opcodes 835 shouldn't be in the hash lists. */ 836 /* Is this insn supported by the selected cpu? */ 837 if (! or1k_cgen_insn_supported (cd, insn)) 838 continue; 839#endif 840 /* If the RELAXED attribute is set, this is an insn that shouldn't be 841 chosen immediately. Instead, it is used during assembler/linker 842 relaxation if possible. */ 843 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0) 844 continue; 845 846 str = start; 847 848 /* Skip this insn if str doesn't look right lexically. */ 849 if (CGEN_INSN_RX (insn) != NULL && 850 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) 851 continue; 852 853 /* Allow parse/insert handlers to obtain length of insn. */ 854 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); 855 856 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields); 857 if (parse_errmsg != NULL) 858 continue; 859 860 /* ??? 0 is passed for `pc'. */ 861 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf, 862 (bfd_vma) 0); 863 if (insert_errmsg != NULL) 864 continue; 865 866 /* It is up to the caller to actually output the insn and any 867 queued relocs. */ 868 return insn; 869 } 870 871 { 872 static char errbuf[150]; 873 const char *tmp_errmsg; 874#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS 875#define be_verbose 1 876#else 877#define be_verbose 0 878#endif 879 880 if (be_verbose) 881 { 882 /* If requesting verbose error messages, use insert_errmsg. 883 Failing that, use parse_errmsg. */ 884 tmp_errmsg = (insert_errmsg ? insert_errmsg : 885 parse_errmsg ? parse_errmsg : 886 recognized_mnemonic ? 887 _("unrecognized form of instruction") : 888 _("unrecognized instruction")); 889 890 if (strlen (start) > 50) 891 /* xgettext:c-format */ 892 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start); 893 else 894 /* xgettext:c-format */ 895 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start); 896 } 897 else 898 { 899 if (strlen (start) > 50) 900 /* xgettext:c-format */ 901 sprintf (errbuf, _("bad instruction `%.50s...'"), start); 902 else 903 /* xgettext:c-format */ 904 sprintf (errbuf, _("bad instruction `%.50s'"), start); 905 } 906 907 *errmsg = errbuf; 908 return NULL; 909 } 910} 911