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 "lm32-desc.h" 35#include "lm32-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 53/* Handle signed/unsigned literal. */ 54 55static const char * 56parse_imm (CGEN_CPU_DESC cd, 57 const char **strp, 58 int opindex, 59 unsigned long *valuep) 60{ 61 const char *errmsg; 62 signed long value; 63 64 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 65 if (errmsg == NULL) 66 { 67 unsigned long x = value & 0xFFFF0000; 68 if (x != 0 && x != 0xFFFF0000) 69 errmsg = _("immediate value out of range"); 70 else 71 *valuep = (value & 0xFFFF); 72 } 73 return errmsg; 74} 75 76/* Handle hi() */ 77 78static const char * 79parse_hi16 (CGEN_CPU_DESC cd, 80 const char **strp, 81 int opindex, 82 unsigned long *valuep) 83{ 84 if (strncasecmp (*strp, "hi(", 3) == 0) 85 { 86 enum cgen_parse_operand_result result_type; 87 bfd_vma value; 88 const char *errmsg; 89 90 *strp += 3; 91 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16, 92 &result_type, &value); 93 if (**strp != ')') 94 return _("missing `)'"); 95 96 ++*strp; 97 if (errmsg == NULL 98 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 99 value = (value >> 16) & 0xffff; 100 *valuep = value; 101 102 return errmsg; 103 } 104 105 return parse_imm (cd, strp, opindex, valuep); 106} 107 108/* Handle lo() */ 109 110static const char * 111parse_lo16 (CGEN_CPU_DESC cd, 112 const char **strp, 113 int opindex, 114 unsigned long *valuep) 115{ 116 if (strncasecmp (*strp, "lo(", 3) == 0) 117 { 118 const char *errmsg; 119 enum cgen_parse_operand_result result_type; 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 `)'"); 127 ++*strp; 128 if (errmsg == NULL 129 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 130 value &= 0xffff; 131 *valuep = value; 132 return errmsg; 133 } 134 135 return parse_imm (cd, strp, opindex, valuep); 136} 137 138/* Handle gp() */ 139 140static const char * 141parse_gp16 (CGEN_CPU_DESC cd, 142 const char **strp, 143 int opindex, 144 long *valuep) 145{ 146 if (strncasecmp (*strp, "gp(", 3) == 0) 147 { 148 const char *errmsg; 149 enum cgen_parse_operand_result result_type; 150 bfd_vma value; 151 152 *strp += 3; 153 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_GPREL16, 154 & result_type, & value); 155 if (**strp != ')') 156 return _("missing `)'"); 157 ++*strp; 158 if (errmsg == NULL 159 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 160 value &= 0xffff; 161 *valuep = value; 162 return errmsg; 163 } 164 165 return _("expecting gp relative address: gp(symbol)"); 166} 167 168/* Handle got() */ 169 170static const char * 171parse_got16 (CGEN_CPU_DESC cd, 172 const char **strp, 173 int opindex, 174 long *valuep) 175{ 176 if (strncasecmp (*strp, "got(", 4) == 0) 177 { 178 const char *errmsg; 179 enum cgen_parse_operand_result result_type; 180 bfd_vma value; 181 182 *strp += 4; 183 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LM32_16_GOT, 184 & result_type, & value); 185 if (**strp != ')') 186 return _("missing `)'"); 187 ++*strp; 188 if (errmsg == NULL 189 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 190 value &= 0xffff; 191 *valuep = value; 192 return errmsg; 193 } 194 195 return _("expecting got relative address: got(symbol)"); 196} 197 198/* Handle gotoffhi16() */ 199 200static const char * 201parse_gotoff_hi16 (CGEN_CPU_DESC cd, 202 const char **strp, 203 int opindex, 204 long *valuep) 205{ 206 if (strncasecmp (*strp, "gotoffhi16(", 11) == 0) 207 { 208 const char *errmsg; 209 enum cgen_parse_operand_result result_type; 210 bfd_vma value; 211 212 *strp += 11; 213 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LM32_GOTOFF_HI16, 214 & result_type, & value); 215 if (**strp != ')') 216 return _("missing `)'"); 217 ++*strp; 218 if (errmsg == NULL 219 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 220 value &= 0xffff; 221 *valuep = value; 222 return errmsg; 223 } 224 225 return _("expecting got relative address: gotoffhi16(symbol)"); 226} 227 228/* Handle gotofflo16() */ 229 230static const char * 231parse_gotoff_lo16 (CGEN_CPU_DESC cd, 232 const char **strp, 233 int opindex, 234 long *valuep) 235{ 236 if (strncasecmp (*strp, "gotofflo16(", 11) == 0) 237 { 238 const char *errmsg; 239 enum cgen_parse_operand_result result_type; 240 bfd_vma value; 241 242 *strp += 11; 243 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LM32_GOTOFF_LO16, 244 &result_type, &value); 245 if (**strp != ')') 246 return _("missing `)'"); 247 ++*strp; 248 if (errmsg == NULL 249 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 250 value &= 0xffff; 251 *valuep = value; 252 return errmsg; 253 } 254 255 return _("expecting got relative address: gotofflo16(symbol)"); 256} 257 258const char * lm32_cgen_parse_operand 259 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 260 261/* Main entry point for operand parsing. 262 263 This function is basically just a big switch statement. Earlier versions 264 used tables to look up the function to use, but 265 - if the table contains both assembler and disassembler functions then 266 the disassembler contains much of the assembler and vice-versa, 267 - there's a lot of inlining possibilities as things grow, 268 - using a switch statement avoids the function call overhead. 269 270 This function could be moved into `parse_insn_normal', but keeping it 271 separate makes clear the interface between `parse_insn_normal' and each of 272 the handlers. */ 273 274const char * 275lm32_cgen_parse_operand (CGEN_CPU_DESC cd, 276 int opindex, 277 const char ** strp, 278 CGEN_FIELDS * fields) 279{ 280 const char * errmsg = NULL; 281 /* Used by scalar operands that still need to be parsed. */ 282 long junk ATTRIBUTE_UNUSED; 283 284 switch (opindex) 285 { 286 case LM32_OPERAND_BRANCH : 287 { 288 bfd_vma value = 0; 289 errmsg = cgen_parse_address (cd, strp, LM32_OPERAND_BRANCH, 0, NULL, & value); 290 fields->f_branch = value; 291 } 292 break; 293 case LM32_OPERAND_CALL : 294 { 295 bfd_vma value = 0; 296 errmsg = cgen_parse_address (cd, strp, LM32_OPERAND_CALL, 0, NULL, & value); 297 fields->f_call = value; 298 } 299 break; 300 case LM32_OPERAND_CSR : 301 errmsg = cgen_parse_keyword (cd, strp, & lm32_cgen_opval_h_csr, & fields->f_csr); 302 break; 303 case LM32_OPERAND_EXCEPTION : 304 errmsg = cgen_parse_unsigned_integer (cd, strp, LM32_OPERAND_EXCEPTION, (unsigned long *) (& fields->f_exception)); 305 break; 306 case LM32_OPERAND_GOT16 : 307 errmsg = parse_got16 (cd, strp, LM32_OPERAND_GOT16, (long *) (& fields->f_imm)); 308 break; 309 case LM32_OPERAND_GOTOFFHI16 : 310 errmsg = parse_gotoff_hi16 (cd, strp, LM32_OPERAND_GOTOFFHI16, (long *) (& fields->f_imm)); 311 break; 312 case LM32_OPERAND_GOTOFFLO16 : 313 errmsg = parse_gotoff_lo16 (cd, strp, LM32_OPERAND_GOTOFFLO16, (long *) (& fields->f_imm)); 314 break; 315 case LM32_OPERAND_GP16 : 316 errmsg = parse_gp16 (cd, strp, LM32_OPERAND_GP16, (long *) (& fields->f_imm)); 317 break; 318 case LM32_OPERAND_HI16 : 319 errmsg = parse_hi16 (cd, strp, LM32_OPERAND_HI16, (unsigned long *) (& fields->f_uimm)); 320 break; 321 case LM32_OPERAND_IMM : 322 errmsg = cgen_parse_signed_integer (cd, strp, LM32_OPERAND_IMM, (long *) (& fields->f_imm)); 323 break; 324 case LM32_OPERAND_LO16 : 325 errmsg = parse_lo16 (cd, strp, LM32_OPERAND_LO16, (unsigned long *) (& fields->f_uimm)); 326 break; 327 case LM32_OPERAND_R0 : 328 errmsg = cgen_parse_keyword (cd, strp, & lm32_cgen_opval_h_gr, & fields->f_r0); 329 break; 330 case LM32_OPERAND_R1 : 331 errmsg = cgen_parse_keyword (cd, strp, & lm32_cgen_opval_h_gr, & fields->f_r1); 332 break; 333 case LM32_OPERAND_R2 : 334 errmsg = cgen_parse_keyword (cd, strp, & lm32_cgen_opval_h_gr, & fields->f_r2); 335 break; 336 case LM32_OPERAND_SHIFT : 337 errmsg = cgen_parse_unsigned_integer (cd, strp, LM32_OPERAND_SHIFT, (unsigned long *) (& fields->f_shift)); 338 break; 339 case LM32_OPERAND_UIMM : 340 errmsg = cgen_parse_unsigned_integer (cd, strp, LM32_OPERAND_UIMM, (unsigned long *) (& fields->f_uimm)); 341 break; 342 case LM32_OPERAND_USER : 343 errmsg = cgen_parse_unsigned_integer (cd, strp, LM32_OPERAND_USER, (unsigned long *) (& fields->f_user)); 344 break; 345 346 default : 347 /* xgettext:c-format */ 348 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex); 349 abort (); 350 } 351 352 return errmsg; 353} 354 355cgen_parse_fn * const lm32_cgen_parse_handlers[] = 356{ 357 parse_insn_normal, 358}; 359 360void 361lm32_cgen_init_asm (CGEN_CPU_DESC cd) 362{ 363 lm32_cgen_init_opcode_table (cd); 364 lm32_cgen_init_ibld_table (cd); 365 cd->parse_handlers = & lm32_cgen_parse_handlers[0]; 366 cd->parse_operand = lm32_cgen_parse_operand; 367#ifdef CGEN_ASM_INIT_HOOK 368CGEN_ASM_INIT_HOOK 369#endif 370} 371 372 373 374/* Regex construction routine. 375 376 This translates an opcode syntax string into a regex string, 377 by replacing any non-character syntax element (such as an 378 opcode) with the pattern '.*' 379 380 It then compiles the regex and stores it in the opcode, for 381 later use by lm32_cgen_assemble_insn 382 383 Returns NULL for success, an error message for failure. */ 384 385char * 386lm32_cgen_build_insn_regex (CGEN_INSN *insn) 387{ 388 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn); 389 const char *mnem = CGEN_INSN_MNEMONIC (insn); 390 char rxbuf[CGEN_MAX_RX_ELEMENTS]; 391 char *rx = rxbuf; 392 const CGEN_SYNTAX_CHAR_TYPE *syn; 393 int reg_err; 394 395 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc)); 396 397 /* Mnemonics come first in the syntax string. */ 398 if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 399 return _("missing mnemonic in syntax string"); 400 ++syn; 401 402 /* Generate a case sensitive regular expression that emulates case 403 insensitive matching in the "C" locale. We cannot generate a case 404 insensitive regular expression because in Turkish locales, 'i' and 'I' 405 are not equal modulo case conversion. */ 406 407 /* Copy the literal mnemonic out of the insn. */ 408 for (; *mnem; mnem++) 409 { 410 char c = *mnem; 411 412 if (ISALPHA (c)) 413 { 414 *rx++ = '['; 415 *rx++ = TOLOWER (c); 416 *rx++ = TOUPPER (c); 417 *rx++ = ']'; 418 } 419 else 420 *rx++ = c; 421 } 422 423 /* Copy any remaining literals from the syntax string into the rx. */ 424 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn) 425 { 426 if (CGEN_SYNTAX_CHAR_P (* syn)) 427 { 428 char c = CGEN_SYNTAX_CHAR (* syn); 429 430 switch (c) 431 { 432 /* Escape any regex metacharacters in the syntax. */ 433 case '.': case '[': case '\\': 434 case '*': case '^': case '$': 435 436#ifdef CGEN_ESCAPE_EXTENDED_REGEX 437 case '?': case '{': case '}': 438 case '(': case ')': case '*': 439 case '|': case '+': case ']': 440#endif 441 *rx++ = '\\'; 442 *rx++ = c; 443 break; 444 445 default: 446 if (ISALPHA (c)) 447 { 448 *rx++ = '['; 449 *rx++ = TOLOWER (c); 450 *rx++ = TOUPPER (c); 451 *rx++ = ']'; 452 } 453 else 454 *rx++ = c; 455 break; 456 } 457 } 458 else 459 { 460 /* Replace non-syntax fields with globs. */ 461 *rx++ = '.'; 462 *rx++ = '*'; 463 } 464 } 465 466 /* Trailing whitespace ok. */ 467 * rx++ = '['; 468 * rx++ = ' '; 469 * rx++ = '\t'; 470 * rx++ = ']'; 471 * rx++ = '*'; 472 473 /* But anchor it after that. */ 474 * rx++ = '$'; 475 * rx = '\0'; 476 477 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t)); 478 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB); 479 480 if (reg_err == 0) 481 return NULL; 482 else 483 { 484 static char msg[80]; 485 486 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80); 487 regfree ((regex_t *) CGEN_INSN_RX (insn)); 488 free (CGEN_INSN_RX (insn)); 489 (CGEN_INSN_RX (insn)) = NULL; 490 return msg; 491 } 492} 493 494 495/* Default insn parser. 496 497 The syntax string is scanned and operands are parsed and stored in FIELDS. 498 Relocs are queued as we go via other callbacks. 499 500 ??? Note that this is currently an all-or-nothing parser. If we fail to 501 parse the instruction, we return 0 and the caller will start over from 502 the beginning. Backtracking will be necessary in parsing subexpressions, 503 but that can be handled there. Not handling backtracking here may get 504 expensive in the case of the m68k. Deal with later. 505 506 Returns NULL for success, an error message for failure. */ 507 508static const char * 509parse_insn_normal (CGEN_CPU_DESC cd, 510 const CGEN_INSN *insn, 511 const char **strp, 512 CGEN_FIELDS *fields) 513{ 514 /* ??? Runtime added insns not handled yet. */ 515 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 516 const char *str = *strp; 517 const char *errmsg; 518 const char *p; 519 const CGEN_SYNTAX_CHAR_TYPE * syn; 520#ifdef CGEN_MNEMONIC_OPERANDS 521 /* FIXME: wip */ 522 int past_opcode_p; 523#endif 524 525 /* For now we assume the mnemonic is first (there are no leading operands). 526 We can parse it without needing to set up operand parsing. 527 GAS's input scrubber will ensure mnemonics are lowercase, but we may 528 not be called from GAS. */ 529 p = CGEN_INSN_MNEMONIC (insn); 530 while (*p && TOLOWER (*p) == TOLOWER (*str)) 531 ++p, ++str; 532 533 if (* p) 534 return _("unrecognized instruction"); 535 536#ifndef CGEN_MNEMONIC_OPERANDS 537 if (* str && ! ISSPACE (* str)) 538 return _("unrecognized instruction"); 539#endif 540 541 CGEN_INIT_PARSE (cd); 542 cgen_init_parse_operand (cd); 543#ifdef CGEN_MNEMONIC_OPERANDS 544 past_opcode_p = 0; 545#endif 546 547 /* We don't check for (*str != '\0') here because we want to parse 548 any trailing fake arguments in the syntax string. */ 549 syn = CGEN_SYNTAX_STRING (syntax); 550 551 /* Mnemonics come first for now, ensure valid string. */ 552 if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 553 abort (); 554 555 ++syn; 556 557 while (* syn != 0) 558 { 559 /* Non operand chars must match exactly. */ 560 if (CGEN_SYNTAX_CHAR_P (* syn)) 561 { 562 /* FIXME: While we allow for non-GAS callers above, we assume the 563 first char after the mnemonic part is a space. */ 564 /* FIXME: We also take inappropriate advantage of the fact that 565 GAS's input scrubber will remove extraneous blanks. */ 566 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn))) 567 { 568#ifdef CGEN_MNEMONIC_OPERANDS 569 if (CGEN_SYNTAX_CHAR(* syn) == ' ') 570 past_opcode_p = 1; 571#endif 572 ++ syn; 573 ++ str; 574 } 575 else if (*str) 576 { 577 /* Syntax char didn't match. Can't be this insn. */ 578 static char msg [80]; 579 580 /* xgettext:c-format */ 581 sprintf (msg, _("syntax error (expected char `%c', found `%c')"), 582 CGEN_SYNTAX_CHAR(*syn), *str); 583 return msg; 584 } 585 else 586 { 587 /* Ran out of input. */ 588 static char msg [80]; 589 590 /* xgettext:c-format */ 591 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"), 592 CGEN_SYNTAX_CHAR(*syn)); 593 return msg; 594 } 595 continue; 596 } 597 598#ifdef CGEN_MNEMONIC_OPERANDS 599 (void) past_opcode_p; 600#endif 601 /* We have an operand of some sort. */ 602 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields); 603 if (errmsg) 604 return errmsg; 605 606 /* Done with this operand, continue with next one. */ 607 ++ syn; 608 } 609 610 /* If we're at the end of the syntax string, we're done. */ 611 if (* syn == 0) 612 { 613 /* FIXME: For the moment we assume a valid `str' can only contain 614 blanks now. IE: We needn't try again with a longer version of 615 the insn and it is assumed that longer versions of insns appear 616 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ 617 while (ISSPACE (* str)) 618 ++ str; 619 620 if (* str != '\0') 621 return _("junk at end of line"); /* FIXME: would like to include `str' */ 622 623 return NULL; 624 } 625 626 /* We couldn't parse it. */ 627 return _("unrecognized instruction"); 628} 629 630/* Main entry point. 631 This routine is called for each instruction to be assembled. 632 STR points to the insn to be assembled. 633 We assume all necessary tables have been initialized. 634 The assembled instruction, less any fixups, is stored in BUF. 635 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value 636 still needs to be converted to target byte order, otherwise BUF is an array 637 of bytes in target byte order. 638 The result is a pointer to the insn's entry in the opcode table, 639 or NULL if an error occured (an error message will have already been 640 printed). 641 642 Note that when processing (non-alias) macro-insns, 643 this function recurses. 644 645 ??? It's possible to make this cpu-independent. 646 One would have to deal with a few minor things. 647 At this point in time doing so would be more of a curiosity than useful 648 [for example this file isn't _that_ big], but keeping the possibility in 649 mind helps keep the design clean. */ 650 651const CGEN_INSN * 652lm32_cgen_assemble_insn (CGEN_CPU_DESC cd, 653 const char *str, 654 CGEN_FIELDS *fields, 655 CGEN_INSN_BYTES_PTR buf, 656 char **errmsg) 657{ 658 const char *start; 659 CGEN_INSN_LIST *ilist; 660 const char *parse_errmsg = NULL; 661 const char *insert_errmsg = NULL; 662 int recognized_mnemonic = 0; 663 664 /* Skip leading white space. */ 665 while (ISSPACE (* str)) 666 ++ str; 667 668 /* The instructions are stored in hashed lists. 669 Get the first in the list. */ 670 ilist = CGEN_ASM_LOOKUP_INSN (cd, str); 671 672 /* Keep looking until we find a match. */ 673 start = str; 674 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) 675 { 676 const CGEN_INSN *insn = ilist->insn; 677 recognized_mnemonic = 1; 678 679#ifdef CGEN_VALIDATE_INSN_SUPPORTED 680 /* Not usually needed as unsupported opcodes 681 shouldn't be in the hash lists. */ 682 /* Is this insn supported by the selected cpu? */ 683 if (! lm32_cgen_insn_supported (cd, insn)) 684 continue; 685#endif 686 /* If the RELAXED attribute is set, this is an insn that shouldn't be 687 chosen immediately. Instead, it is used during assembler/linker 688 relaxation if possible. */ 689 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0) 690 continue; 691 692 str = start; 693 694 /* Skip this insn if str doesn't look right lexically. */ 695 if (CGEN_INSN_RX (insn) != NULL && 696 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) 697 continue; 698 699 /* Allow parse/insert handlers to obtain length of insn. */ 700 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); 701 702 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields); 703 if (parse_errmsg != NULL) 704 continue; 705 706 /* ??? 0 is passed for `pc'. */ 707 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf, 708 (bfd_vma) 0); 709 if (insert_errmsg != NULL) 710 continue; 711 712 /* It is up to the caller to actually output the insn and any 713 queued relocs. */ 714 return insn; 715 } 716 717 { 718 static char errbuf[150]; 719 const char *tmp_errmsg; 720#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS 721#define be_verbose 1 722#else 723#define be_verbose 0 724#endif 725 726 if (be_verbose) 727 { 728 /* If requesting verbose error messages, use insert_errmsg. 729 Failing that, use parse_errmsg. */ 730 tmp_errmsg = (insert_errmsg ? insert_errmsg : 731 parse_errmsg ? parse_errmsg : 732 recognized_mnemonic ? 733 _("unrecognized form of instruction") : 734 _("unrecognized instruction")); 735 736 if (strlen (start) > 50) 737 /* xgettext:c-format */ 738 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start); 739 else 740 /* xgettext:c-format */ 741 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start); 742 } 743 else 744 { 745 if (strlen (start) > 50) 746 /* xgettext:c-format */ 747 sprintf (errbuf, _("bad instruction `%.50s...'"), start); 748 else 749 /* xgettext:c-format */ 750 sprintf (errbuf, _("bad instruction `%.50s'"), start); 751 } 752 753 *errmsg = errbuf; 754 return NULL; 755 } 756} 757