1 /* Assembler interface for targets using CGEN. -*- C -*- 2 CGEN: Cpu tools GENerator 3 4 This file is used to generate m32r-asm.c. 5 6 Copyright (C) 1996, 1997 Free Software Foundation, Inc. 7 8 This file is part of the GNU Binutils and GDB, the GNU debugger. 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2, or (at your option) 13 any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 23 24 #include "sysdep.h" 25 #include <ctype.h> 26 #include <stdio.h> 27 #include "ansidecl.h" 28 #include "bfd.h" 29 #include "m32r-opc.h" 30 31 /* ??? The layout of this stuff is still work in progress. 32 For speed in assembly/disassembly, we use inline functions. That of course 33 will only work for GCC. When this stuff is finished, we can decide whether 34 to keep the inline functions (and only get the performance increase when 35 compiled with GCC), or switch to macros, or use something else. 36 */ 37 38 static const char *parse_insn_normal 39 PARAMS ((const struct cgen_insn *, const char **, struct cgen_fields *)); 40 static void insert_insn_normal 41 PARAMS ((const struct cgen_insn *, struct cgen_fields *, cgen_insn_t *)); 42 43 /* Default insertion routine. 44 45 SHIFT is negative for left shifts, positive for right shifts. 46 All bits of VALUE to be inserted must be valid as we don't handle 47 signed vs unsigned shifts. 48 49 ATTRS is a mask of the boolean attributes. We don't need any at the 50 moment, but for consistency with extract_normal we have them. */ 51 52 /* FIXME: This duplicates functionality with bfd's howto table and 53 bfd_install_relocation. */ 54 /* FIXME: For architectures where insns can be representable as ints, 55 store insn in `field' struct and add registers, etc. while parsing. */ 56 57 static CGEN_INLINE void 58 insert_normal (value, attrs, start, length, shift, total_length, buffer) 59 long value; 60 unsigned int attrs; 61 int start, length, shift, total_length; 62 char *buffer; 63 { 64 bfd_vma x; 65 66 #if 0 /*def CGEN_INT_INSN*/ 67 *buffer |= ((value & ((1 << length) - 1)) 68 << (total_length - (start + length))); 69 #else 70 switch (total_length) 71 { 72 case 8: 73 x = *(unsigned char *) buffer; 74 break; 75 case 16: 76 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) 77 x = bfd_getb16 (buffer); 78 else 79 x = bfd_getl16 (buffer); 80 break; 81 case 32: 82 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) 83 x = bfd_getb32 (buffer); 84 else 85 x = bfd_getl32 (buffer); 86 break; 87 default : 88 abort (); 89 } 90 91 if (shift < 0) 92 value <<= -shift; 93 else 94 value >>= shift; 95 96 x |= ((value & ((1 << length) - 1)) 97 << (total_length - (start + length))); 98 99 switch (total_length) 100 { 101 case 8: 102 *buffer = value; 103 break; 104 case 16: 105 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) 106 bfd_putb16 (x, buffer); 107 else 108 bfd_putl16 (x, buffer); 109 break; 110 case 32: 111 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) 112 bfd_putb32 (x, buffer); 113 else 114 bfd_putl32 (x, buffer); 115 break; 116 default : 117 abort (); 118 } 119 #endif 120 } 121 122 /* -- assembler routines inserted here */ 123 /* -- asm.c */ 124 125 /* Handle shigh(), high(). */ 126 127 static const char * 128 parse_h_hi16 (strp, opindex, min, max, valuep) 129 const char **strp; 130 int opindex; 131 unsigned long min, max; 132 unsigned long *valuep; 133 { 134 const char *errmsg; 135 136 /* FIXME: Need # in assembler syntax (means '#' is optional). */ 137 if (**strp == '#') 138 ++*strp; 139 140 if (strncmp (*strp, "high(", 5) == 0) 141 { 142 *strp += 5; 143 /* FIXME: If value was a number, right shift by 16. */ 144 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_ULO, valuep); 145 if (**strp != ')') 146 return "missing `)'"; 147 ++*strp; 148 return errmsg; 149 } 150 else if (strncmp (*strp, "shigh(", 6) == 0) 151 { 152 *strp += 6; 153 /* FIXME: If value was a number, right shift by 16 (+ sign test). */ 154 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_SLO, valuep); 155 if (**strp != ')') 156 return "missing `)'"; 157 ++*strp; 158 return errmsg; 159 } 160 161 return cgen_parse_unsigned_integer (strp, opindex, min, max, valuep); 162 } 163 164 /* Handle low() in a signed context. Also handle sda(). 165 The signedness of the value doesn't matter to low(), but this also 166 handles the case where low() isn't present. */ 167 168 static const char * 169 parse_h_slo16 (strp, opindex, min, max, valuep) 170 const char **strp; 171 int opindex; 172 long min, max; 173 long *valuep; 174 { 175 const char *errmsg; 176 177 /* FIXME: Need # in assembler syntax (means '#' is optional). */ 178 if (**strp == '#') 179 ++*strp; 180 181 if (strncmp (*strp, "low(", 4) == 0) 182 { 183 *strp += 4; 184 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16, valuep); 185 if (**strp != ')') 186 return "missing `)'"; 187 ++*strp; 188 return errmsg; 189 } 190 191 if (strncmp (*strp, "sda(", 4) == 0) 192 { 193 *strp += 4; 194 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_SDA16, valuep); 195 if (**strp != ')') 196 return "missing `)'"; 197 ++*strp; 198 return errmsg; 199 } 200 201 return cgen_parse_signed_integer (strp, opindex, min, max, valuep); 202 } 203 204 /* Handle low() in an unsigned context. 205 The signedness of the value doesn't matter to low(), but this also 206 handles the case where low() isn't present. */ 207 208 static const char * 209 parse_h_ulo16 (strp, opindex, min, max, valuep) 210 const char **strp; 211 int opindex; 212 unsigned long min, max; 213 unsigned long *valuep; 214 { 215 const char *errmsg; 216 217 /* FIXME: Need # in assembler syntax (means '#' is optional). */ 218 if (**strp == '#') 219 ++*strp; 220 221 if (strncmp (*strp, "low(", 4) == 0) 222 { 223 *strp += 4; 224 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16, valuep); 225 if (**strp != ')') 226 return "missing `)'"; 227 ++*strp; 228 return errmsg; 229 } 230 231 return cgen_parse_unsigned_integer (strp, opindex, min, max, valuep); 232 } 233 234 /* -- */ 235 236 /* Main entry point for operand parsing. 237 238 This function is basically just a big switch statement. Earlier versions 239 used tables to look up the function to use, but 240 - if the table contains both assembler and disassembler functions then 241 the disassembler contains much of the assembler and vice-versa, 242 - there's a lot of inlining possibilities as things grow, 243 - using a switch statement avoids the function call overhead. 244 245 This function could be moved into `parse_insn_normal', but keeping it 246 separate makes clear the interface between `parse_insn_normal' and each of 247 the handlers. 248 */ 249 250 CGEN_INLINE const char * 251 m32r_cgen_parse_operand (opindex, strp, fields) 252 int opindex; 253 const char **strp; 254 struct cgen_fields *fields; 255 { 256 const char *errmsg; 257 258 switch (opindex) 259 { 260 case 0 : 261 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r2); 262 break; 263 case 1 : 264 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r1); 265 break; 266 case 2 : 267 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r1); 268 break; 269 case 3 : 270 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r2); 271 break; 272 case 4 : 273 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, &fields->f_r2); 274 break; 275 case 5 : 276 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, &fields->f_r1); 277 break; 278 case 6 : 279 errmsg = cgen_parse_signed_integer (strp, 6, -128, 127, &fields->f_simm8); 280 break; 281 case 7 : 282 errmsg = cgen_parse_signed_integer (strp, 7, -32768, 32767, &fields->f_simm16); 283 break; 284 case 8 : 285 errmsg = cgen_parse_unsigned_integer (strp, 8, 0, 15, &fields->f_uimm4); 286 break; 287 case 9 : 288 errmsg = cgen_parse_unsigned_integer (strp, 9, 0, 31, &fields->f_uimm5); 289 break; 290 case 10 : 291 errmsg = cgen_parse_unsigned_integer (strp, 10, 0, 65535, &fields->f_uimm16); 292 break; 293 case 11 : 294 errmsg = parse_h_hi16 (strp, 11, 0, 65535, &fields->f_hi16); 295 break; 296 case 12 : 297 errmsg = parse_h_slo16 (strp, 12, -32768, 32767, &fields->f_simm16); 298 break; 299 case 13 : 300 errmsg = parse_h_ulo16 (strp, 13, 0, 65535, &fields->f_uimm16); 301 break; 302 case 14 : 303 errmsg = cgen_parse_address (strp, 14, 0, &fields->f_uimm24); 304 break; 305 case 15 : 306 errmsg = cgen_parse_address (strp, 15, 0, &fields->f_disp8); 307 break; 308 case 16 : 309 errmsg = cgen_parse_address (strp, 16, 0, &fields->f_disp16); 310 break; 311 case 17 : 312 errmsg = cgen_parse_address (strp, 17, 0, &fields->f_disp24); 313 break; 314 315 default : 316 fprintf (stderr, "Unrecognized field %d while parsing.\n", opindex); 317 abort (); 318 } 319 320 return errmsg; 321 } 322 323 /* Main entry point for operand insertion. 324 325 This function is basically just a big switch statement. Earlier versions 326 used tables to look up the function to use, but 327 - if the table contains both assembler and disassembler functions then 328 the disassembler contains much of the assembler and vice-versa, 329 - there's a lot of inlining possibilities as things grow, 330 - using a switch statement avoids the function call overhead. 331 332 This function could be moved into `parse_insn_normal', but keeping it 333 separate makes clear the interface between `parse_insn_normal' and each of 334 the handlers. It's also needed by GAS to insert operands that couldn't be 335 resolved during parsing. 336 */ 337 338 CGEN_INLINE void 339 m32r_cgen_insert_operand (opindex, fields, buffer) 340 int opindex; 341 struct cgen_fields *fields; 342 cgen_insn_t *buffer; 343 { 344 switch (opindex) 345 { 346 case 0 : 347 insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 348 break; 349 case 1 : 350 insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 351 break; 352 case 2 : 353 insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 354 break; 355 case 3 : 356 insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 357 break; 358 case 4 : 359 insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 360 break; 361 case 5 : 362 insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 363 break; 364 case 6 : 365 insert_normal (fields->f_simm8, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 366 break; 367 case 7 : 368 insert_normal (fields->f_simm16, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 369 break; 370 case 8 : 371 insert_normal (fields->f_uimm4, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 372 break; 373 case 9 : 374 insert_normal (fields->f_uimm5, 0|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 375 break; 376 case 10 : 377 insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 378 break; 379 case 11 : 380 insert_normal (fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 381 break; 382 case 12 : 383 insert_normal (fields->f_simm16, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 384 break; 385 case 13 : 386 insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 387 break; 388 case 14 : 389 insert_normal (fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, 0, CGEN_FIELDS_BITSIZE (fields), buffer); 390 break; 391 case 15 : 392 insert_normal (fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, 2, CGEN_FIELDS_BITSIZE (fields), buffer); 393 break; 394 case 16 : 395 insert_normal (fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields), buffer); 396 break; 397 case 17 : 398 insert_normal (fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, 2, CGEN_FIELDS_BITSIZE (fields), buffer); 399 break; 400 401 default : 402 fprintf (stderr, "Unrecognized field %d while building insn.\n", 403 opindex); 404 abort (); 405 } 406 } 407 408 /* Main entry point for operand validation. 409 410 This function is called from GAS when it has fully resolved an operand 411 that couldn't be resolved during parsing. 412 413 The result is NULL for success or an error message (which may be 414 computed into a static buffer). 415 */ 416 417 CGEN_INLINE const char * 418 m32r_cgen_validate_operand (opindex, fields) 419 int opindex; 420 const struct cgen_fields *fields; 421 { 422 const char *errmsg = NULL; 423 424 switch (opindex) 425 { 426 case 0 : 427 /* nothing to do */ 428 break; 429 case 1 : 430 /* nothing to do */ 431 break; 432 case 2 : 433 /* nothing to do */ 434 break; 435 case 3 : 436 /* nothing to do */ 437 break; 438 case 4 : 439 /* nothing to do */ 440 break; 441 case 5 : 442 /* nothing to do */ 443 break; 444 case 6 : 445 errmsg = cgen_validate_signed_integer (fields->f_simm8, -128, 127); 446 break; 447 case 7 : 448 errmsg = cgen_validate_signed_integer (fields->f_simm16, -32768, 32767); 449 break; 450 case 8 : 451 errmsg = cgen_validate_unsigned_integer (fields->f_uimm4, 0, 15); 452 break; 453 case 9 : 454 errmsg = cgen_validate_unsigned_integer (fields->f_uimm5, 0, 31); 455 break; 456 case 10 : 457 errmsg = cgen_validate_unsigned_integer (fields->f_uimm16, 0, 65535); 458 break; 459 case 11 : 460 errmsg = cgen_validate_unsigned_integer (fields->f_hi16, 0, 65535); 461 break; 462 case 12 : 463 errmsg = cgen_validate_signed_integer (fields->f_simm16, -32768, 32767); 464 break; 465 case 13 : 466 errmsg = cgen_validate_unsigned_integer (fields->f_uimm16, 0, 65535); 467 break; 468 case 14 : 469 /* nothing to do */ 470 break; 471 case 15 : 472 /* nothing to do */ 473 break; 474 case 16 : 475 /* nothing to do */ 476 break; 477 case 17 : 478 /* nothing to do */ 479 break; 480 481 default : 482 fprintf (stderr, "Unrecognized field %d while validating operand.\n", 483 opindex); 484 abort (); 485 } 486 487 return errmsg; 488 } 489 490 cgen_parse_fn *m32r_cgen_parse_handlers[] = { 491 0, /* default */ 492 parse_insn_normal, 493 }; 494 495 cgen_insert_fn *m32r_cgen_insert_handlers[] = { 496 0, /* default */ 497 insert_insn_normal, 498 }; 499 500 void 501 m32r_cgen_init_asm (mach, endian) 502 int mach; 503 enum cgen_endian endian; 504 { 505 m32r_cgen_init_tables (mach); 506 cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian); 507 cgen_asm_init (); 508 } 509 510 511 /* Default insn parser. 512 513 The syntax string is scanned and operands are parsed and stored in FIELDS. 514 Relocs are queued as we go via other callbacks. 515 516 ??? Note that this is currently an all-or-nothing parser. If we fail to 517 parse the instruction, we return 0 and the caller will start over from 518 the beginning. Backtracking will be necessary in parsing subexpressions, 519 but that can be handled there. Not handling backtracking here may get 520 expensive in the case of the m68k. Deal with later. 521 522 Returns NULL for success, an error message for failure. 523 */ 524 525 static const char * 526 parse_insn_normal (insn, strp, fields) 527 const struct cgen_insn *insn; 528 const char **strp; 529 struct cgen_fields *fields; 530 { 531 const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn); 532 const char *str = *strp; 533 const char *errmsg; 534 const unsigned char *syn; 535 #ifdef CGEN_MNEMONIC_OPERANDS 536 int past_opcode_p; 537 #endif 538 539 /* If mnemonics are constant, they're not stored with the syntax string. */ 540 #ifndef CGEN_MNEMONIC_OPERANDS 541 { 542 const char *p = syntax->mnemonic; 543 544 while (*p && *p == *str) 545 ++p, ++str; 546 if (*p || (*str && !isspace (*str))) 547 return "unrecognized instruction"; 548 549 while (isspace (*str)) 550 ++str; 551 } 552 #endif 553 554 CGEN_INIT_PARSE (); 555 cgen_init_parse_operand (); 556 #ifdef CGEN_MNEMONIC_OPERANDS 557 past_opcode_p = 0; 558 #endif 559 560 /* We don't check for (*str != '\0') here because we want to parse 561 any trailing fake arguments in the syntax string. */ 562 for (syn = syntax->syntax; *syn != '\0'; ) 563 { 564 /* Non operand chars must match exactly. */ 565 /* FIXME: Need to better handle whitespace. */ 566 if (CGEN_SYNTAX_CHAR_P (*syn)) 567 { 568 if (*str == CGEN_SYNTAX_CHAR (*syn)) 569 { 570 #ifdef CGEN_MNEMONIC_OPERANDS 571 if (*syn == ' ') 572 past_opcode_p = 1; 573 #endif 574 ++syn; 575 ++str; 576 } 577 else 578 { 579 /* Syntax char didn't match. Can't be this insn. */ 580 /* FIXME: would like to return "expected char `c'" */ 581 return "syntax error"; 582 } 583 continue; 584 } 585 586 /* We have an operand of some sort. */ 587 errmsg = m32r_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn), 588 &str, fields); 589 if (errmsg) 590 return errmsg; 591 592 /* Done with this operand, continue with next one. */ 593 ++syn; 594 } 595 596 /* If we're at the end of the syntax string, we're done. */ 597 if (*syn == '\0') 598 { 599 /* FIXME: For the moment we assume a valid `str' can only contain 600 blanks now. IE: We needn't try again with a longer version of 601 the insn and it is assumed that longer versions of insns appear 602 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ 603 while (isspace (*str)) 604 ++str; 605 606 if (*str != '\0') 607 return "junk at end of line"; /* FIXME: would like to include `str' */ 608 609 return NULL; 610 } 611 612 /* We couldn't parse it. */ 613 return "unrecognized instruction"; 614 } 615 616 /* Default insn builder (insert handler). 617 The instruction is recorded in target byte order. */ 618 619 static void 620 insert_insn_normal (insn, fields, buffer) 621 const struct cgen_insn *insn; 622 struct cgen_fields *fields; 623 cgen_insn_t *buffer; 624 { 625 const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn); 626 bfd_vma value; 627 const unsigned char *syn; 628 629 CGEN_INIT_INSERT (); 630 value = syntax->value; 631 632 /* If we're recording insns as numbers (rather than a string of bytes), 633 target byte order handling is deferred until later. */ 634 #undef min 635 #define min(a,b) ((a) < (b) ? (a) : (b)) 636 #if 0 /*def CGEN_INT_INSN*/ 637 *buffer = value; 638 #else 639 switch (min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields))) 640 { 641 case 8: 642 *buffer = value; 643 break; 644 case 16: 645 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) 646 bfd_putb16 (value, (char *) buffer); 647 else 648 bfd_putl16 (value, (char *) buffer); 649 break; 650 case 32: 651 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) 652 bfd_putb32 (value, (char *) buffer); 653 else 654 bfd_putl32 (value, (char *) buffer); 655 break; 656 default: 657 abort (); 658 } 659 #endif 660 661 /* ??? Rather than scanning the syntax string again, we could store 662 in `fields' a null terminated list of the fields that are present. */ 663 664 for (syn = syntax->syntax; *syn != '\0'; ++syn) 665 { 666 if (CGEN_SYNTAX_CHAR_P (*syn)) 667 continue; 668 669 m32r_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn), fields, buffer); 670 } 671 } 672 673 /* Main entry point. 674 This routine is called for each instruction to be assembled. 675 STR points to the insn to be assembled. 676 We assume all necessary tables have been initialized. 677 The result is a pointer to the insn's entry in the opcode table, 678 or NULL if an error occured (an error message will have already been 679 printed). */ 680 681 const struct cgen_insn * 682 m32r_cgen_assemble_insn (str, fields, buf, errmsg) 683 const char *str; 684 struct cgen_fields *fields; 685 cgen_insn_t *buf; 686 char **errmsg; 687 { 688 const char *start; 689 CGEN_INSN_LIST *ilist; 690 691 /* Skip leading white space. */ 692 while (isspace (*str)) 693 ++str; 694 695 /* The instructions are stored in hashed lists. 696 Get the first in the list. */ 697 ilist = CGEN_ASM_LOOKUP_INSN (str); 698 699 /* Keep looking until we find a match. */ 700 701 start = str; 702 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) 703 { 704 const struct cgen_insn *insn = ilist->insn; 705 706 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */ 707 /* Is this insn supported by the selected cpu? */ 708 if (! m32r_cgen_insn_supported (insn)) 709 continue; 710 #endif 711 712 #if 1 /* FIXME: wip */ 713 /* If the RELAX attribute is set, this is an insn that shouldn't be 714 chosen immediately. Instead, it is used during assembler/linker 715 relaxation if possible. */ 716 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0) 717 continue; 718 #endif 719 720 str = start; 721 722 /* Record a default length for the insn. This will get set to the 723 correct value while parsing. */ 724 /* FIXME: wip */ 725 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); 726 727 /* ??? The extent to which moving the parse and insert handlers into 728 this function (thus removing the function call) will speed things up 729 is unclear. The simplicity and flexibility of the current scheme is 730 appropriate for now. One could have the best of both worlds with 731 inline functions but of course that would only work for gcc. Since 732 we're machine generating some code we could do that here too. Maybe 733 later. */ 734 if (! (*CGEN_PARSE_FN (insn)) (insn, &str, fields)) 735 { 736 (*CGEN_INSERT_FN (insn)) (insn, fields, buf); 737 /* It is up to the caller to actually output the insn and any 738 queued relocs. */ 739 return insn; 740 } 741 742 /* Try the next entry. */ 743 } 744 745 /* FIXME: We can return a better error message than this. 746 Need to track why it failed and pick the right one. */ 747 { 748 static char errbuf[100]; 749 sprintf (errbuf, "bad instruction `%.50s%s'", 750 start, strlen (start) > 50 ? "..." : ""); 751 *errmsg = errbuf; 752 return NULL; 753 } 754 } 755 756 #if 0 /* This calls back to GAS which we can't do without care. */ 757 758 /* Record each member of OPVALS in the assembler's symbol table. 759 This lets GAS parse registers for us. 760 ??? Interesting idea but not currently used. */ 761 762 void 763 m32r_cgen_asm_hash_keywords (opvals) 764 struct cgen_keyword *opvals; 765 { 766 struct cgen_keyword_search search = cgen_keyword_search_init (opvals, NULL); 767 const struct cgen_keyword_entry *ke; 768 769 while ((ke = cgen_keyword_search_next (&search)) != NULL) 770 { 771 #if 0 /* Unnecessary, should be done in the search routine. */ 772 if (! m32r_cgen_opval_supported (ke)) 773 continue; 774 #endif 775 cgen_asm_record_register (ke->name, ke->value); 776 } 777 } 778 779 #endif /* 0 */ 780