00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "sysdep.h"
00035 #include <stdio.h>
00036 #include "ansidecl.h"
00037 #include "bfd.h"
00038 #include "symcat.h"
00039 #include "m32r-desc.h"
00040 #include "m32r-opc.h"
00041 #include "opintl.h"
00042 #include "xregex.h"
00043 #include "libiberty.h"
00044 #include "safe-ctype.h"
00045
00046 #undef min
00047 #define min(a,b) ((a) < (b) ? (a) : (b))
00048 #undef max
00049 #define max(a,b) ((a) > (b) ? (a) : (b))
00050
00051 static const char * parse_insn_normal
00052 (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
00053
00054
00055
00056
00057 static const char * parse_hash
00058 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
00059 static const char * parse_hi16
00060 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
00061 static const char * parse_slo16
00062 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
00063 static const char * parse_ulo16
00064 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
00065
00066
00067
00068 static const char *
00069 parse_hash (cd, strp, opindex, valuep)
00070 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
00071 const char **strp;
00072 int opindex ATTRIBUTE_UNUSED;
00073 long *valuep ATTRIBUTE_UNUSED;
00074 {
00075 if (**strp == '#')
00076 ++*strp;
00077 return NULL;
00078 }
00079
00080
00081
00082 static const char *
00083 parse_hi16 (cd, strp, opindex, valuep)
00084 CGEN_CPU_DESC cd;
00085 const char **strp;
00086 int opindex;
00087 unsigned long *valuep;
00088 {
00089 const char *errmsg;
00090 enum cgen_parse_operand_result result_type;
00091 bfd_vma value;
00092
00093 if (**strp == '#')
00094 ++*strp;
00095
00096 if (strncasecmp (*strp, "high(", 5) == 0)
00097 {
00098 *strp += 5;
00099 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
00100 &result_type, &value);
00101 if (**strp != ')')
00102 return "missing `)'";
00103 ++*strp;
00104 if (errmsg == NULL
00105 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00106 value >>= 16;
00107 *valuep = value;
00108 return errmsg;
00109 }
00110 else if (strncasecmp (*strp, "shigh(", 6) == 0)
00111 {
00112 *strp += 6;
00113 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
00114 &result_type, &value);
00115 if (**strp != ')')
00116 return "missing `)'";
00117 ++*strp;
00118 if (errmsg == NULL
00119 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00120 {
00121 value = value + (value & 0x8000 ? 0x10000 : 0);
00122 value >>= 16;
00123 }
00124 *valuep = value;
00125 return errmsg;
00126 }
00127
00128 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00129 }
00130
00131
00132
00133
00134
00135 static const char *
00136 parse_slo16 (cd, strp, opindex, valuep)
00137 CGEN_CPU_DESC cd;
00138 const char **strp;
00139 int opindex;
00140 long *valuep;
00141 {
00142 const char *errmsg;
00143 enum cgen_parse_operand_result result_type;
00144 bfd_vma value;
00145
00146 if (**strp == '#')
00147 ++*strp;
00148
00149 if (strncasecmp (*strp, "low(", 4) == 0)
00150 {
00151 *strp += 4;
00152 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
00153 &result_type, &value);
00154 if (**strp != ')')
00155 return "missing `)'";
00156 ++*strp;
00157 if (errmsg == NULL
00158 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00159 {
00160 value &= 0xffff;
00161 if (value & 0x8000)
00162 value |= 0xffff0000;
00163 }
00164 *valuep = value;
00165 return errmsg;
00166 }
00167
00168 if (strncasecmp (*strp, "sda(", 4) == 0)
00169 {
00170 *strp += 4;
00171 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
00172 NULL, &value);
00173 if (**strp != ')')
00174 return "missing `)'";
00175 ++*strp;
00176 *valuep = value;
00177 return errmsg;
00178 }
00179
00180 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
00181 }
00182
00183
00184
00185
00186
00187 static const char *
00188 parse_ulo16 (cd, strp, opindex, valuep)
00189 CGEN_CPU_DESC cd;
00190 const char **strp;
00191 int opindex;
00192 unsigned long *valuep;
00193 {
00194 const char *errmsg;
00195 enum cgen_parse_operand_result result_type;
00196 bfd_vma value;
00197
00198 if (**strp == '#')
00199 ++*strp;
00200
00201 if (strncasecmp (*strp, "low(", 4) == 0)
00202 {
00203 *strp += 4;
00204 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
00205 &result_type, &value);
00206 if (**strp != ')')
00207 return "missing `)'";
00208 ++*strp;
00209 if (errmsg == NULL
00210 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00211 value &= 0xffff;
00212 *valuep = value;
00213 return errmsg;
00214 }
00215
00216 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00217 }
00218
00219
00220
00221 const char * m32r_cgen_parse_operand
00222 PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 const char *
00238 m32r_cgen_parse_operand (cd, opindex, strp, fields)
00239 CGEN_CPU_DESC cd;
00240 int opindex;
00241 const char ** strp;
00242 CGEN_FIELDS * fields;
00243 {
00244 const char * errmsg = NULL;
00245
00246 long junk ATTRIBUTE_UNUSED;
00247
00248 switch (opindex)
00249 {
00250 case M32R_OPERAND_ACC :
00251 errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_acc);
00252 break;
00253 case M32R_OPERAND_ACCD :
00254 errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accd);
00255 break;
00256 case M32R_OPERAND_ACCS :
00257 errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accs);
00258 break;
00259 case M32R_OPERAND_DCR :
00260 errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r1);
00261 break;
00262 case M32R_OPERAND_DISP16 :
00263 {
00264 bfd_vma value;
00265 errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP16, 0, NULL, & value);
00266 fields->f_disp16 = value;
00267 }
00268 break;
00269 case M32R_OPERAND_DISP24 :
00270 {
00271 bfd_vma value;
00272 errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP24, 0, NULL, & value);
00273 fields->f_disp24 = value;
00274 }
00275 break;
00276 case M32R_OPERAND_DISP8 :
00277 {
00278 bfd_vma value;
00279 errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP8, 0, NULL, & value);
00280 fields->f_disp8 = value;
00281 }
00282 break;
00283 case M32R_OPERAND_DR :
00284 errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
00285 break;
00286 case M32R_OPERAND_HASH :
00287 errmsg = parse_hash (cd, strp, M32R_OPERAND_HASH, (long *) (& junk));
00288 break;
00289 case M32R_OPERAND_HI16 :
00290 errmsg = parse_hi16 (cd, strp, M32R_OPERAND_HI16, (unsigned long *) (& fields->f_hi16));
00291 break;
00292 case M32R_OPERAND_IMM1 :
00293 errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_IMM1, (unsigned long *) (& fields->f_imm1));
00294 break;
00295 case M32R_OPERAND_SCR :
00296 errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r2);
00297 break;
00298 case M32R_OPERAND_SIMM16 :
00299 errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM16, (long *) (& fields->f_simm16));
00300 break;
00301 case M32R_OPERAND_SIMM8 :
00302 errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM8, (long *) (& fields->f_simm8));
00303 break;
00304 case M32R_OPERAND_SLO16 :
00305 errmsg = parse_slo16 (cd, strp, M32R_OPERAND_SLO16, (long *) (& fields->f_simm16));
00306 break;
00307 case M32R_OPERAND_SR :
00308 errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
00309 break;
00310 case M32R_OPERAND_SRC1 :
00311 errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
00312 break;
00313 case M32R_OPERAND_SRC2 :
00314 errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
00315 break;
00316 case M32R_OPERAND_UIMM16 :
00317 errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
00318 break;
00319 case M32R_OPERAND_UIMM24 :
00320 {
00321 bfd_vma value;
00322 errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_UIMM24, 0, NULL, & value);
00323 fields->f_uimm24 = value;
00324 }
00325 break;
00326 case M32R_OPERAND_UIMM3 :
00327 errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM3, (unsigned long *) (& fields->f_uimm3));
00328 break;
00329 case M32R_OPERAND_UIMM4 :
00330 errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM4, (unsigned long *) (& fields->f_uimm4));
00331 break;
00332 case M32R_OPERAND_UIMM5 :
00333 errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM5, (unsigned long *) (& fields->f_uimm5));
00334 break;
00335 case M32R_OPERAND_UIMM8 :
00336 errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM8, (unsigned long *) (& fields->f_uimm8));
00337 break;
00338 case M32R_OPERAND_ULO16 :
00339 errmsg = parse_ulo16 (cd, strp, M32R_OPERAND_ULO16, (unsigned long *) (& fields->f_uimm16));
00340 break;
00341
00342 default :
00343
00344 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
00345 abort ();
00346 }
00347
00348 return errmsg;
00349 }
00350
00351 cgen_parse_fn * const m32r_cgen_parse_handlers[] =
00352 {
00353 parse_insn_normal,
00354 };
00355
00356 void
00357 m32r_cgen_init_asm (cd)
00358 CGEN_CPU_DESC cd;
00359 {
00360 m32r_cgen_init_opcode_table (cd);
00361 m32r_cgen_init_ibld_table (cd);
00362 cd->parse_handlers = & m32r_cgen_parse_handlers[0];
00363 cd->parse_operand = m32r_cgen_parse_operand;
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 char *
00380 m32r_cgen_build_insn_regex (CGEN_INSN *insn)
00381 {
00382 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
00383 const char *mnem = CGEN_INSN_MNEMONIC (insn);
00384 char rxbuf[CGEN_MAX_RX_ELEMENTS];
00385 char *rx = rxbuf;
00386 const CGEN_SYNTAX_CHAR_TYPE *syn;
00387 int reg_err;
00388
00389 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
00390
00391
00392 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00393 return _("missing mnemonic in syntax string");
00394 ++syn;
00395
00396
00397
00398
00399
00400
00401
00402 for (; *mnem; mnem++)
00403 {
00404 char c = *mnem;
00405
00406 if (ISALPHA (c))
00407 {
00408 *rx++ = '[';
00409 *rx++ = TOLOWER (c);
00410 *rx++ = TOUPPER (c);
00411 *rx++ = ']';
00412 }
00413 else
00414 *rx++ = c;
00415 }
00416
00417
00418 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
00419 {
00420 if (CGEN_SYNTAX_CHAR_P (* syn))
00421 {
00422 char c = CGEN_SYNTAX_CHAR (* syn);
00423
00424 switch (c)
00425 {
00426
00427 case '.': case '[': case '\\':
00428 case '*': case '^': case '$':
00429
00430 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
00431 case '?': case '{': case '}':
00432 case '(': case ')': case '*':
00433 case '|': case '+': case ']':
00434 #endif
00435 *rx++ = '\\';
00436 *rx++ = c;
00437 break;
00438
00439 default:
00440 if (ISALPHA (c))
00441 {
00442 *rx++ = '[';
00443 *rx++ = TOLOWER (c);
00444 *rx++ = TOUPPER (c);
00445 *rx++ = ']';
00446 }
00447 else
00448 *rx++ = c;
00449 break;
00450 }
00451 }
00452 else
00453 {
00454
00455 *rx++ = '.';
00456 *rx++ = '*';
00457 }
00458 }
00459
00460
00461 * rx++ = '[';
00462 * rx++ = ' ';
00463 * rx++ = '\t';
00464 * rx++ = ']';
00465 * rx++ = '*';
00466
00467
00468 * rx++ = '$';
00469 * rx = '\0';
00470
00471 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
00472 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
00473
00474 if (reg_err == 0)
00475 return NULL;
00476 else
00477 {
00478 static char msg[80];
00479
00480 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
00481 regfree ((regex_t *) CGEN_INSN_RX (insn));
00482 free (CGEN_INSN_RX (insn));
00483 (CGEN_INSN_RX (insn)) = NULL;
00484 return msg;
00485 }
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 static const char *
00503 parse_insn_normal (CGEN_CPU_DESC cd,
00504 const CGEN_INSN *insn,
00505 const char **strp,
00506 CGEN_FIELDS *fields)
00507 {
00508
00509 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00510 const char *str = *strp;
00511 const char *errmsg;
00512 const char *p;
00513 const CGEN_SYNTAX_CHAR_TYPE * syn;
00514 #ifdef CGEN_MNEMONIC_OPERANDS
00515
00516 int past_opcode_p;
00517 #endif
00518
00519
00520
00521
00522
00523 p = CGEN_INSN_MNEMONIC (insn);
00524 while (*p && TOLOWER (*p) == TOLOWER (*str))
00525 ++p, ++str;
00526
00527 if (* p)
00528 return _("unrecognized instruction");
00529
00530 #ifndef CGEN_MNEMONIC_OPERANDS
00531 if (* str && ! ISSPACE (* str))
00532 return _("unrecognized instruction");
00533 #endif
00534
00535 CGEN_INIT_PARSE (cd);
00536 cgen_init_parse_operand (cd);
00537 #ifdef CGEN_MNEMONIC_OPERANDS
00538 past_opcode_p = 0;
00539 #endif
00540
00541
00542
00543 syn = CGEN_SYNTAX_STRING (syntax);
00544
00545
00546 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00547 abort ();
00548
00549 ++syn;
00550
00551 while (* syn != 0)
00552 {
00553
00554 if (CGEN_SYNTAX_CHAR_P (* syn))
00555 {
00556
00557
00558
00559
00560 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
00561 {
00562 #ifdef CGEN_MNEMONIC_OPERANDS
00563 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
00564 past_opcode_p = 1;
00565 #endif
00566 ++ syn;
00567 ++ str;
00568 }
00569 else if (*str)
00570 {
00571
00572 static char msg [80];
00573
00574
00575 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
00576 CGEN_SYNTAX_CHAR(*syn), *str);
00577 return msg;
00578 }
00579 else
00580 {
00581
00582 static char msg [80];
00583
00584
00585 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
00586 CGEN_SYNTAX_CHAR(*syn));
00587 return msg;
00588 }
00589 continue;
00590 }
00591
00592
00593 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
00594 &str, fields);
00595 if (errmsg)
00596 return errmsg;
00597
00598
00599 ++ syn;
00600 }
00601
00602
00603 if (* syn == 0)
00604 {
00605
00606
00607
00608
00609 while (ISSPACE (* str))
00610 ++ str;
00611
00612 if (* str != '\0')
00613 return _("junk at end of line");
00614
00615 return NULL;
00616 }
00617
00618
00619 return _("unrecognized instruction");
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 const CGEN_INSN *
00644 m32r_cgen_assemble_insn (CGEN_CPU_DESC cd,
00645 const char *str,
00646 CGEN_FIELDS *fields,
00647 CGEN_INSN_BYTES_PTR buf,
00648 char **errmsg)
00649 {
00650 const char *start;
00651 CGEN_INSN_LIST *ilist;
00652 const char *parse_errmsg = NULL;
00653 const char *insert_errmsg = NULL;
00654 int recognized_mnemonic = 0;
00655
00656
00657 while (ISSPACE (* str))
00658 ++ str;
00659
00660
00661
00662 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
00663
00664
00665 start = str;
00666 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
00667 {
00668 const CGEN_INSN *insn = ilist->insn;
00669 recognized_mnemonic = 1;
00670
00671 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
00672
00673
00674
00675 if (! m32r_cgen_insn_supported (cd, insn))
00676 continue;
00677 #endif
00678
00679
00680
00681 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
00682 continue;
00683
00684 str = start;
00685
00686
00687 if (CGEN_INSN_RX (insn) != NULL &&
00688 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
00689 continue;
00690
00691
00692 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
00693
00694 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
00695 if (parse_errmsg != NULL)
00696 continue;
00697
00698
00699 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
00700 (bfd_vma) 0);
00701 if (insert_errmsg != NULL)
00702 continue;
00703
00704
00705
00706 return insn;
00707 }
00708
00709 {
00710 static char errbuf[150];
00711 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
00712 const char *tmp_errmsg;
00713
00714
00715
00716 tmp_errmsg = (insert_errmsg ? insert_errmsg :
00717 parse_errmsg ? parse_errmsg :
00718 recognized_mnemonic ?
00719 _("unrecognized form of instruction") :
00720 _("unrecognized instruction"));
00721
00722 if (strlen (start) > 50)
00723
00724 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
00725 else
00726
00727 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
00728 #else
00729 if (strlen (start) > 50)
00730
00731 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
00732 else
00733
00734 sprintf (errbuf, _("bad instruction `%.50s'"), start);
00735 #endif
00736
00737 *errmsg = errbuf;
00738 return NULL;
00739 }
00740 }
00741
00742 #if 0
00743
00744
00745
00746
00747
00748
00749
00750
00751 void
00752 m32r_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
00753 {
00754 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
00755 const CGEN_KEYWORD_ENTRY * ke;
00756
00757 while ((ke = cgen_keyword_search_next (& search)) != NULL)
00758 {
00759 #if 0
00760 if (! m32r_cgen_opval_supported (ke))
00761 continue;
00762 #endif
00763 cgen_asm_record_register (cd, ke->name, ke->value);
00764 }
00765 }
00766
00767 #endif