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 "fr30-desc.h"
00040 #include "fr30-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
00058
00059 static int parse_register_number
00060 PARAMS ((const char **));
00061 static const char * parse_register_list
00062 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *, int, int));
00063 static const char * parse_low_register_list_ld
00064 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
00065 static const char * parse_hi_register_list_ld
00066 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
00067 static const char * parse_low_register_list_st
00068 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
00069 static const char * parse_hi_register_list_st
00070 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
00071
00072 static int
00073 parse_register_number (strp)
00074 const char **strp;
00075 {
00076 int regno;
00077 if (**strp < '0' || **strp > '9')
00078 return -1;
00079 regno = **strp - '0';
00080 ++*strp;
00081
00082 if (**strp >= '0' && **strp <= '9')
00083 {
00084 regno = regno * 10 + (**strp - '0');
00085 ++*strp;
00086 }
00087
00088 return regno;
00089 }
00090
00091 static const char *
00092 parse_register_list (cd, strp, opindex, valuep, high_low, load_store)
00093 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
00094 const char **strp;
00095 int opindex ATTRIBUTE_UNUSED;
00096 unsigned long *valuep;
00097 int high_low;
00098 int load_store;
00099 {
00100 int regno;
00101
00102 *valuep = 0;
00103 while (**strp && **strp != ')')
00104 {
00105 if (**strp != 'R' && **strp != 'r')
00106 break;
00107 ++*strp;
00108
00109 regno = parse_register_number (strp);
00110 if (regno == -1)
00111 return "Register number is not valid";
00112 if (regno > 7 && !high_low)
00113 return "Register must be between r0 and r7";
00114 if (regno < 8 && high_low)
00115 return "Register must be between r8 and r15";
00116
00117 if (high_low)
00118 regno -= 8;
00119
00120 if (load_store)
00121 *valuep |= 0x80 >> regno;
00122 else
00123 *valuep |= 1 << regno;
00124
00125 if (**strp == ',')
00126 {
00127 if (*(*strp + 1) == ')')
00128 break;
00129 ++*strp;
00130 }
00131 }
00132
00133 if (!*strp || **strp != ')')
00134 return "Register list is not valid";
00135
00136 return NULL;
00137 }
00138
00139 static const char *
00140 parse_low_register_list_ld (cd, strp, opindex, valuep)
00141 CGEN_CPU_DESC cd;
00142 const char **strp;
00143 int opindex;
00144 unsigned long *valuep;
00145 {
00146 return parse_register_list (cd, strp, opindex, valuep, 0, 0);
00147 }
00148
00149 static const char *
00150 parse_hi_register_list_ld (cd, strp, opindex, valuep)
00151 CGEN_CPU_DESC cd;
00152 const char **strp;
00153 int opindex;
00154 unsigned long *valuep;
00155 {
00156 return parse_register_list (cd, strp, opindex, valuep, 1, 0);
00157 }
00158
00159 static const char *
00160 parse_low_register_list_st (cd, strp, opindex, valuep)
00161 CGEN_CPU_DESC cd;
00162 const char **strp;
00163 int opindex;
00164 unsigned long *valuep;
00165 {
00166 return parse_register_list (cd, strp, opindex, valuep, 0, 1);
00167 }
00168
00169 static const char *
00170 parse_hi_register_list_st (cd, strp, opindex, valuep)
00171 CGEN_CPU_DESC cd;
00172 const char **strp;
00173 int opindex;
00174 unsigned long *valuep;
00175 {
00176 return parse_register_list (cd, strp, opindex, valuep, 1, 1);
00177 }
00178
00179
00180
00181 const char * fr30_cgen_parse_operand
00182 PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 const char *
00198 fr30_cgen_parse_operand (cd, opindex, strp, fields)
00199 CGEN_CPU_DESC cd;
00200 int opindex;
00201 const char ** strp;
00202 CGEN_FIELDS * fields;
00203 {
00204 const char * errmsg = NULL;
00205
00206 long junk ATTRIBUTE_UNUSED;
00207
00208 switch (opindex)
00209 {
00210 case FR30_OPERAND_CRI :
00211 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRi);
00212 break;
00213 case FR30_OPERAND_CRJ :
00214 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRj);
00215 break;
00216 case FR30_OPERAND_R13 :
00217 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r13, & junk);
00218 break;
00219 case FR30_OPERAND_R14 :
00220 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r14, & junk);
00221 break;
00222 case FR30_OPERAND_R15 :
00223 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r15, & junk);
00224 break;
00225 case FR30_OPERAND_RI :
00226 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ri);
00227 break;
00228 case FR30_OPERAND_RIC :
00229 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ric);
00230 break;
00231 case FR30_OPERAND_RJ :
00232 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rj);
00233 break;
00234 case FR30_OPERAND_RJC :
00235 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rjc);
00236 break;
00237 case FR30_OPERAND_RS1 :
00238 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs1);
00239 break;
00240 case FR30_OPERAND_RS2 :
00241 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs2);
00242 break;
00243 case FR30_OPERAND_CC :
00244 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CC, (unsigned long *) (& fields->f_cc));
00245 break;
00246 case FR30_OPERAND_CCC :
00247 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CCC, (unsigned long *) (& fields->f_ccc));
00248 break;
00249 case FR30_OPERAND_DIR10 :
00250 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR10, (unsigned long *) (& fields->f_dir10));
00251 break;
00252 case FR30_OPERAND_DIR8 :
00253 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR8, (unsigned long *) (& fields->f_dir8));
00254 break;
00255 case FR30_OPERAND_DIR9 :
00256 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR9, (unsigned long *) (& fields->f_dir9));
00257 break;
00258 case FR30_OPERAND_DISP10 :
00259 errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP10, (long *) (& fields->f_disp10));
00260 break;
00261 case FR30_OPERAND_DISP8 :
00262 errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP8, (long *) (& fields->f_disp8));
00263 break;
00264 case FR30_OPERAND_DISP9 :
00265 errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP9, (long *) (& fields->f_disp9));
00266 break;
00267 case FR30_OPERAND_I20 :
00268 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I20, (unsigned long *) (& fields->f_i20));
00269 break;
00270 case FR30_OPERAND_I32 :
00271 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I32, (unsigned long *) (& fields->f_i32));
00272 break;
00273 case FR30_OPERAND_I8 :
00274 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I8, (unsigned long *) (& fields->f_i8));
00275 break;
00276 case FR30_OPERAND_LABEL12 :
00277 {
00278 bfd_vma value;
00279 errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL12, 0, NULL, & value);
00280 fields->f_rel12 = value;
00281 }
00282 break;
00283 case FR30_OPERAND_LABEL9 :
00284 {
00285 bfd_vma value;
00286 errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL9, 0, NULL, & value);
00287 fields->f_rel9 = value;
00288 }
00289 break;
00290 case FR30_OPERAND_M4 :
00291 errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_M4, (long *) (& fields->f_m4));
00292 break;
00293 case FR30_OPERAND_PS :
00294 errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_ps, & junk);
00295 break;
00296 case FR30_OPERAND_REGLIST_HI_LD :
00297 errmsg = parse_hi_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_HI_LD, (unsigned long *) (& fields->f_reglist_hi_ld));
00298 break;
00299 case FR30_OPERAND_REGLIST_HI_ST :
00300 errmsg = parse_hi_register_list_st (cd, strp, FR30_OPERAND_REGLIST_HI_ST, (unsigned long *) (& fields->f_reglist_hi_st));
00301 break;
00302 case FR30_OPERAND_REGLIST_LOW_LD :
00303 errmsg = parse_low_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_LOW_LD, (unsigned long *) (& fields->f_reglist_low_ld));
00304 break;
00305 case FR30_OPERAND_REGLIST_LOW_ST :
00306 errmsg = parse_low_register_list_st (cd, strp, FR30_OPERAND_REGLIST_LOW_ST, (unsigned long *) (& fields->f_reglist_low_st));
00307 break;
00308 case FR30_OPERAND_S10 :
00309 errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_S10, (long *) (& fields->f_s10));
00310 break;
00311 case FR30_OPERAND_U10 :
00312 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U10, (unsigned long *) (& fields->f_u10));
00313 break;
00314 case FR30_OPERAND_U4 :
00315 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4, (unsigned long *) (& fields->f_u4));
00316 break;
00317 case FR30_OPERAND_U4C :
00318 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4C, (unsigned long *) (& fields->f_u4c));
00319 break;
00320 case FR30_OPERAND_U8 :
00321 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U8, (unsigned long *) (& fields->f_u8));
00322 break;
00323 case FR30_OPERAND_UDISP6 :
00324 errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_UDISP6, (unsigned long *) (& fields->f_udisp6));
00325 break;
00326
00327 default :
00328
00329 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
00330 abort ();
00331 }
00332
00333 return errmsg;
00334 }
00335
00336 cgen_parse_fn * const fr30_cgen_parse_handlers[] =
00337 {
00338 parse_insn_normal,
00339 };
00340
00341 void
00342 fr30_cgen_init_asm (cd)
00343 CGEN_CPU_DESC cd;
00344 {
00345 fr30_cgen_init_opcode_table (cd);
00346 fr30_cgen_init_ibld_table (cd);
00347 cd->parse_handlers = & fr30_cgen_parse_handlers[0];
00348 cd->parse_operand = fr30_cgen_parse_operand;
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 char *
00365 fr30_cgen_build_insn_regex (CGEN_INSN *insn)
00366 {
00367 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
00368 const char *mnem = CGEN_INSN_MNEMONIC (insn);
00369 char rxbuf[CGEN_MAX_RX_ELEMENTS];
00370 char *rx = rxbuf;
00371 const CGEN_SYNTAX_CHAR_TYPE *syn;
00372 int reg_err;
00373
00374 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
00375
00376
00377 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00378 return _("missing mnemonic in syntax string");
00379 ++syn;
00380
00381
00382
00383
00384
00385
00386
00387 for (; *mnem; mnem++)
00388 {
00389 char c = *mnem;
00390
00391 if (ISALPHA (c))
00392 {
00393 *rx++ = '[';
00394 *rx++ = TOLOWER (c);
00395 *rx++ = TOUPPER (c);
00396 *rx++ = ']';
00397 }
00398 else
00399 *rx++ = c;
00400 }
00401
00402
00403 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
00404 {
00405 if (CGEN_SYNTAX_CHAR_P (* syn))
00406 {
00407 char c = CGEN_SYNTAX_CHAR (* syn);
00408
00409 switch (c)
00410 {
00411
00412 case '.': case '[': case '\\':
00413 case '*': case '^': case '$':
00414
00415 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
00416 case '?': case '{': case '}':
00417 case '(': case ')': case '*':
00418 case '|': case '+': case ']':
00419 #endif
00420 *rx++ = '\\';
00421 *rx++ = c;
00422 break;
00423
00424 default:
00425 if (ISALPHA (c))
00426 {
00427 *rx++ = '[';
00428 *rx++ = TOLOWER (c);
00429 *rx++ = TOUPPER (c);
00430 *rx++ = ']';
00431 }
00432 else
00433 *rx++ = c;
00434 break;
00435 }
00436 }
00437 else
00438 {
00439
00440 *rx++ = '.';
00441 *rx++ = '*';
00442 }
00443 }
00444
00445
00446 * rx++ = '[';
00447 * rx++ = ' ';
00448 * rx++ = '\t';
00449 * rx++ = ']';
00450 * rx++ = '*';
00451
00452
00453 * rx++ = '$';
00454 * rx = '\0';
00455
00456 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
00457 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
00458
00459 if (reg_err == 0)
00460 return NULL;
00461 else
00462 {
00463 static char msg[80];
00464
00465 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
00466 regfree ((regex_t *) CGEN_INSN_RX (insn));
00467 free (CGEN_INSN_RX (insn));
00468 (CGEN_INSN_RX (insn)) = NULL;
00469 return msg;
00470 }
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 static const char *
00488 parse_insn_normal (CGEN_CPU_DESC cd,
00489 const CGEN_INSN *insn,
00490 const char **strp,
00491 CGEN_FIELDS *fields)
00492 {
00493
00494 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00495 const char *str = *strp;
00496 const char *errmsg;
00497 const char *p;
00498 const CGEN_SYNTAX_CHAR_TYPE * syn;
00499 #ifdef CGEN_MNEMONIC_OPERANDS
00500
00501 int past_opcode_p;
00502 #endif
00503
00504
00505
00506
00507
00508 p = CGEN_INSN_MNEMONIC (insn);
00509 while (*p && TOLOWER (*p) == TOLOWER (*str))
00510 ++p, ++str;
00511
00512 if (* p)
00513 return _("unrecognized instruction");
00514
00515 #ifndef CGEN_MNEMONIC_OPERANDS
00516 if (* str && ! ISSPACE (* str))
00517 return _("unrecognized instruction");
00518 #endif
00519
00520 CGEN_INIT_PARSE (cd);
00521 cgen_init_parse_operand (cd);
00522 #ifdef CGEN_MNEMONIC_OPERANDS
00523 past_opcode_p = 0;
00524 #endif
00525
00526
00527
00528 syn = CGEN_SYNTAX_STRING (syntax);
00529
00530
00531 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00532 abort ();
00533
00534 ++syn;
00535
00536 while (* syn != 0)
00537 {
00538
00539 if (CGEN_SYNTAX_CHAR_P (* syn))
00540 {
00541
00542
00543
00544
00545 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
00546 {
00547 #ifdef CGEN_MNEMONIC_OPERANDS
00548 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
00549 past_opcode_p = 1;
00550 #endif
00551 ++ syn;
00552 ++ str;
00553 }
00554 else if (*str)
00555 {
00556
00557 static char msg [80];
00558
00559
00560 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
00561 CGEN_SYNTAX_CHAR(*syn), *str);
00562 return msg;
00563 }
00564 else
00565 {
00566
00567 static char msg [80];
00568
00569
00570 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
00571 CGEN_SYNTAX_CHAR(*syn));
00572 return msg;
00573 }
00574 continue;
00575 }
00576
00577
00578 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
00579 &str, fields);
00580 if (errmsg)
00581 return errmsg;
00582
00583
00584 ++ syn;
00585 }
00586
00587
00588 if (* syn == 0)
00589 {
00590
00591
00592
00593
00594 while (ISSPACE (* str))
00595 ++ str;
00596
00597 if (* str != '\0')
00598 return _("junk at end of line");
00599
00600 return NULL;
00601 }
00602
00603
00604 return _("unrecognized instruction");
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 const CGEN_INSN *
00629 fr30_cgen_assemble_insn (CGEN_CPU_DESC cd,
00630 const char *str,
00631 CGEN_FIELDS *fields,
00632 CGEN_INSN_BYTES_PTR buf,
00633 char **errmsg)
00634 {
00635 const char *start;
00636 CGEN_INSN_LIST *ilist;
00637 const char *parse_errmsg = NULL;
00638 const char *insert_errmsg = NULL;
00639 int recognized_mnemonic = 0;
00640
00641
00642 while (ISSPACE (* str))
00643 ++ str;
00644
00645
00646
00647 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
00648
00649
00650 start = str;
00651 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
00652 {
00653 const CGEN_INSN *insn = ilist->insn;
00654 recognized_mnemonic = 1;
00655
00656 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
00657
00658
00659
00660 if (! fr30_cgen_insn_supported (cd, insn))
00661 continue;
00662 #endif
00663
00664
00665
00666 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
00667 continue;
00668
00669 str = start;
00670
00671
00672 if (CGEN_INSN_RX (insn) != NULL &&
00673 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
00674 continue;
00675
00676
00677 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
00678
00679 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
00680 if (parse_errmsg != NULL)
00681 continue;
00682
00683
00684 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
00685 (bfd_vma) 0);
00686 if (insert_errmsg != NULL)
00687 continue;
00688
00689
00690
00691 return insn;
00692 }
00693
00694 {
00695 static char errbuf[150];
00696 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
00697 const char *tmp_errmsg;
00698
00699
00700
00701 tmp_errmsg = (insert_errmsg ? insert_errmsg :
00702 parse_errmsg ? parse_errmsg :
00703 recognized_mnemonic ?
00704 _("unrecognized form of instruction") :
00705 _("unrecognized instruction"));
00706
00707 if (strlen (start) > 50)
00708
00709 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
00710 else
00711
00712 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
00713 #else
00714 if (strlen (start) > 50)
00715
00716 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
00717 else
00718
00719 sprintf (errbuf, _("bad instruction `%.50s'"), start);
00720 #endif
00721
00722 *errmsg = errbuf;
00723 return NULL;
00724 }
00725 }
00726
00727 #if 0
00728
00729
00730
00731
00732
00733
00734
00735
00736 void
00737 fr30_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
00738 {
00739 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
00740 const CGEN_KEYWORD_ENTRY * ke;
00741
00742 while ((ke = cgen_keyword_search_next (& search)) != NULL)
00743 {
00744 #if 0
00745 if (! fr30_cgen_opval_supported (ke))
00746 continue;
00747 #endif
00748 cgen_asm_record_register (cd, ke->name, ke->value);
00749 }
00750 }
00751
00752 #endif