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 "xstormy16-desc.h"
00040 #include "xstormy16-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_mem8
00058 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
00059 static const char * parse_small_immediate
00060 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
00061 static const char * parse_immediate16
00062 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
00063
00064
00065
00066
00067
00068
00069
00070 static const char *
00071 parse_mem8 (cd, strp, opindex, valuep)
00072 CGEN_CPU_DESC cd;
00073 const char **strp;
00074 int opindex;
00075 unsigned long *valuep;
00076 {
00077 if (**strp == '(')
00078 {
00079 const char *s = *strp;
00080
00081 if (s[1] == '-' && s[2] == '-')
00082 return _("Bad register in preincrement");
00083
00084 while (ISALNUM (*++s))
00085 ;
00086 if (s[0] == '+' && s[1] == '+' && (s[2] == ')' || s[2] == ','))
00087 return _("Bad register in postincrement");
00088 if (s[0] == ',' || s[0] == ')')
00089 return _("Bad register name");
00090 }
00091 else if (cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names,
00092 (long *) valuep) == NULL)
00093 return _("Label conflicts with register name");
00094 else if (strncasecmp (*strp, "rx,", 3) == 0
00095 || strncasecmp (*strp, "rxl,", 3) == 0
00096 || strncasecmp (*strp, "rxh,", 3) == 0)
00097 return _("Label conflicts with `Rx'");
00098 else if (**strp == '#')
00099 return _("Bad immediate expression");
00100
00101 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00102 }
00103
00104
00105
00106
00107
00108
00109 static const char *
00110 parse_small_immediate (cd, strp, opindex, valuep)
00111 CGEN_CPU_DESC cd;
00112 const char **strp;
00113 int opindex;
00114 unsigned long *valuep;
00115 {
00116 bfd_vma value;
00117 enum cgen_parse_operand_result result;
00118 const char *errmsg;
00119
00120 if (**strp == '@')
00121 return _("No relocation for small immediate");
00122
00123 errmsg = (* cd->parse_operand_fn)
00124 (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE,
00125 &result, &value);
00126
00127 if (errmsg)
00128 return errmsg;
00129
00130 if (result != CGEN_PARSE_OPERAND_RESULT_NUMBER)
00131 return _("Small operand was not an immediate number");
00132
00133 *valuep = value;
00134 return NULL;
00135 }
00136
00137
00138
00139 static const char *
00140 parse_immediate16 (cd, strp, opindex, valuep)
00141 CGEN_CPU_DESC cd;
00142 const char **strp;
00143 int opindex;
00144 unsigned long *valuep;
00145 {
00146 const char *errmsg;
00147 enum cgen_parse_operand_result result;
00148 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
00149 bfd_vma value;
00150
00151 if (strncmp (*strp, "@hi(", 4) == 0)
00152 {
00153 *strp += 4;
00154 code = BFD_RELOC_HI16;
00155 }
00156 else
00157 if (strncmp (*strp, "@lo(", 4) == 0)
00158 {
00159 *strp += 4;
00160 code = BFD_RELOC_LO16;
00161 }
00162
00163 if (code == BFD_RELOC_NONE)
00164 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00165 else
00166 {
00167 errmsg = cgen_parse_address (cd, strp, opindex, code, &result, &value);
00168 if ((errmsg == NULL) &&
00169 (result != CGEN_PARSE_OPERAND_RESULT_QUEUED))
00170 errmsg = _("Operand is not a symbol");
00171
00172 *valuep = value;
00173 if ((code == BFD_RELOC_HI16 || code == BFD_RELOC_LO16)
00174 && **strp == ')')
00175 *strp += 1;
00176 else
00177 {
00178 errmsg = _("Syntax error: No trailing ')'");
00179 return errmsg;
00180 }
00181 }
00182 return errmsg;
00183 }
00184
00185
00186 const char * xstormy16_cgen_parse_operand
00187 PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 const char *
00203 xstormy16_cgen_parse_operand (cd, opindex, strp, fields)
00204 CGEN_CPU_DESC cd;
00205 int opindex;
00206 const char ** strp;
00207 CGEN_FIELDS * fields;
00208 {
00209 const char * errmsg = NULL;
00210
00211 long junk ATTRIBUTE_UNUSED;
00212
00213 switch (opindex)
00214 {
00215 case XSTORMY16_OPERAND_RB :
00216 errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_Rb_names, & fields->f_Rb);
00217 break;
00218 case XSTORMY16_OPERAND_RBJ :
00219 errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_Rb_names, & fields->f_Rbj);
00220 break;
00221 case XSTORMY16_OPERAND_RD :
00222 errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rd);
00223 break;
00224 case XSTORMY16_OPERAND_RDM :
00225 errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rdm);
00226 break;
00227 case XSTORMY16_OPERAND_RM :
00228 errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rm);
00229 break;
00230 case XSTORMY16_OPERAND_RS :
00231 errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rs);
00232 break;
00233 case XSTORMY16_OPERAND_ABS24 :
00234 errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_ABS24, (unsigned long *) (& fields->f_abs24));
00235 break;
00236 case XSTORMY16_OPERAND_BCOND2 :
00237 errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_branchcond, & fields->f_op2);
00238 break;
00239 case XSTORMY16_OPERAND_BCOND5 :
00240 errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_branchcond, & fields->f_op5);
00241 break;
00242 case XSTORMY16_OPERAND_HMEM8 :
00243 errmsg = parse_mem8 (cd, strp, XSTORMY16_OPERAND_HMEM8, (unsigned long *) (& fields->f_hmem8));
00244 break;
00245 case XSTORMY16_OPERAND_IMM12 :
00246 errmsg = cgen_parse_signed_integer (cd, strp, XSTORMY16_OPERAND_IMM12, (long *) (& fields->f_imm12));
00247 break;
00248 case XSTORMY16_OPERAND_IMM16 :
00249 errmsg = parse_immediate16 (cd, strp, XSTORMY16_OPERAND_IMM16, (unsigned long *) (& fields->f_imm16));
00250 break;
00251 case XSTORMY16_OPERAND_IMM2 :
00252 errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM2, (unsigned long *) (& fields->f_imm2));
00253 break;
00254 case XSTORMY16_OPERAND_IMM3 :
00255 errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM3, (unsigned long *) (& fields->f_imm3));
00256 break;
00257 case XSTORMY16_OPERAND_IMM3B :
00258 errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM3B, (unsigned long *) (& fields->f_imm3b));
00259 break;
00260 case XSTORMY16_OPERAND_IMM4 :
00261 errmsg = parse_small_immediate (cd, strp, XSTORMY16_OPERAND_IMM4, (unsigned long *) (& fields->f_imm4));
00262 break;
00263 case XSTORMY16_OPERAND_IMM8 :
00264 errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM8, (unsigned long *) (& fields->f_imm8));
00265 break;
00266 case XSTORMY16_OPERAND_IMM8SMALL :
00267 errmsg = parse_small_immediate (cd, strp, XSTORMY16_OPERAND_IMM8SMALL, (unsigned long *) (& fields->f_imm8));
00268 break;
00269 case XSTORMY16_OPERAND_LMEM8 :
00270 errmsg = parse_mem8 (cd, strp, XSTORMY16_OPERAND_LMEM8, (unsigned long *) (& fields->f_lmem8));
00271 break;
00272 case XSTORMY16_OPERAND_REL12 :
00273 errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL12, (unsigned long *) (& fields->f_rel12));
00274 break;
00275 case XSTORMY16_OPERAND_REL12A :
00276 errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL12A, (unsigned long *) (& fields->f_rel12a));
00277 break;
00278 case XSTORMY16_OPERAND_REL8_2 :
00279 errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL8_2, (unsigned long *) (& fields->f_rel8_2));
00280 break;
00281 case XSTORMY16_OPERAND_REL8_4 :
00282 errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL8_4, (unsigned long *) (& fields->f_rel8_4));
00283 break;
00284 case XSTORMY16_OPERAND_WS2 :
00285 errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_wordsize, & fields->f_op2m);
00286 break;
00287
00288 default :
00289
00290 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
00291 abort ();
00292 }
00293
00294 return errmsg;
00295 }
00296
00297 cgen_parse_fn * const xstormy16_cgen_parse_handlers[] =
00298 {
00299 parse_insn_normal,
00300 };
00301
00302 void
00303 xstormy16_cgen_init_asm (cd)
00304 CGEN_CPU_DESC cd;
00305 {
00306 xstormy16_cgen_init_opcode_table (cd);
00307 xstormy16_cgen_init_ibld_table (cd);
00308 cd->parse_handlers = & xstormy16_cgen_parse_handlers[0];
00309 cd->parse_operand = xstormy16_cgen_parse_operand;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 char *
00326 xstormy16_cgen_build_insn_regex (CGEN_INSN *insn)
00327 {
00328 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
00329 const char *mnem = CGEN_INSN_MNEMONIC (insn);
00330 char rxbuf[CGEN_MAX_RX_ELEMENTS];
00331 char *rx = rxbuf;
00332 const CGEN_SYNTAX_CHAR_TYPE *syn;
00333 int reg_err;
00334
00335 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
00336
00337
00338 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00339 return _("missing mnemonic in syntax string");
00340 ++syn;
00341
00342
00343
00344
00345
00346
00347
00348 for (; *mnem; mnem++)
00349 {
00350 char c = *mnem;
00351
00352 if (ISALPHA (c))
00353 {
00354 *rx++ = '[';
00355 *rx++ = TOLOWER (c);
00356 *rx++ = TOUPPER (c);
00357 *rx++ = ']';
00358 }
00359 else
00360 *rx++ = c;
00361 }
00362
00363
00364 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
00365 {
00366 if (CGEN_SYNTAX_CHAR_P (* syn))
00367 {
00368 char c = CGEN_SYNTAX_CHAR (* syn);
00369
00370 switch (c)
00371 {
00372
00373 case '.': case '[': case '\\':
00374 case '*': case '^': case '$':
00375
00376 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
00377 case '?': case '{': case '}':
00378 case '(': case ')': case '*':
00379 case '|': case '+': case ']':
00380 #endif
00381 *rx++ = '\\';
00382 *rx++ = c;
00383 break;
00384
00385 default:
00386 if (ISALPHA (c))
00387 {
00388 *rx++ = '[';
00389 *rx++ = TOLOWER (c);
00390 *rx++ = TOUPPER (c);
00391 *rx++ = ']';
00392 }
00393 else
00394 *rx++ = c;
00395 break;
00396 }
00397 }
00398 else
00399 {
00400
00401 *rx++ = '.';
00402 *rx++ = '*';
00403 }
00404 }
00405
00406
00407 * rx++ = '[';
00408 * rx++ = ' ';
00409 * rx++ = '\t';
00410 * rx++ = ']';
00411 * rx++ = '*';
00412
00413
00414 * rx++ = '$';
00415 * rx = '\0';
00416
00417 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
00418 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
00419
00420 if (reg_err == 0)
00421 return NULL;
00422 else
00423 {
00424 static char msg[80];
00425
00426 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
00427 regfree ((regex_t *) CGEN_INSN_RX (insn));
00428 free (CGEN_INSN_RX (insn));
00429 (CGEN_INSN_RX (insn)) = NULL;
00430 return msg;
00431 }
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 static const char *
00449 parse_insn_normal (CGEN_CPU_DESC cd,
00450 const CGEN_INSN *insn,
00451 const char **strp,
00452 CGEN_FIELDS *fields)
00453 {
00454
00455 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00456 const char *str = *strp;
00457 const char *errmsg;
00458 const char *p;
00459 const CGEN_SYNTAX_CHAR_TYPE * syn;
00460 #ifdef CGEN_MNEMONIC_OPERANDS
00461
00462 int past_opcode_p;
00463 #endif
00464
00465
00466
00467
00468
00469 p = CGEN_INSN_MNEMONIC (insn);
00470 while (*p && TOLOWER (*p) == TOLOWER (*str))
00471 ++p, ++str;
00472
00473 if (* p)
00474 return _("unrecognized instruction");
00475
00476 #ifndef CGEN_MNEMONIC_OPERANDS
00477 if (* str && ! ISSPACE (* str))
00478 return _("unrecognized instruction");
00479 #endif
00480
00481 CGEN_INIT_PARSE (cd);
00482 cgen_init_parse_operand (cd);
00483 #ifdef CGEN_MNEMONIC_OPERANDS
00484 past_opcode_p = 0;
00485 #endif
00486
00487
00488
00489 syn = CGEN_SYNTAX_STRING (syntax);
00490
00491
00492 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00493 abort ();
00494
00495 ++syn;
00496
00497 while (* syn != 0)
00498 {
00499
00500 if (CGEN_SYNTAX_CHAR_P (* syn))
00501 {
00502
00503
00504
00505
00506 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
00507 {
00508 #ifdef CGEN_MNEMONIC_OPERANDS
00509 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
00510 past_opcode_p = 1;
00511 #endif
00512 ++ syn;
00513 ++ str;
00514 }
00515 else if (*str)
00516 {
00517
00518 static char msg [80];
00519
00520
00521 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
00522 CGEN_SYNTAX_CHAR(*syn), *str);
00523 return msg;
00524 }
00525 else
00526 {
00527
00528 static char msg [80];
00529
00530
00531 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
00532 CGEN_SYNTAX_CHAR(*syn));
00533 return msg;
00534 }
00535 continue;
00536 }
00537
00538
00539 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
00540 &str, fields);
00541 if (errmsg)
00542 return errmsg;
00543
00544
00545 ++ syn;
00546 }
00547
00548
00549 if (* syn == 0)
00550 {
00551
00552
00553
00554
00555 while (ISSPACE (* str))
00556 ++ str;
00557
00558 if (* str != '\0')
00559 return _("junk at end of line");
00560
00561 return NULL;
00562 }
00563
00564
00565 return _("unrecognized instruction");
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 const CGEN_INSN *
00590 xstormy16_cgen_assemble_insn (CGEN_CPU_DESC cd,
00591 const char *str,
00592 CGEN_FIELDS *fields,
00593 CGEN_INSN_BYTES_PTR buf,
00594 char **errmsg)
00595 {
00596 const char *start;
00597 CGEN_INSN_LIST *ilist;
00598 const char *parse_errmsg = NULL;
00599 const char *insert_errmsg = NULL;
00600 int recognized_mnemonic = 0;
00601
00602
00603 while (ISSPACE (* str))
00604 ++ str;
00605
00606
00607
00608 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
00609
00610
00611 start = str;
00612 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
00613 {
00614 const CGEN_INSN *insn = ilist->insn;
00615 recognized_mnemonic = 1;
00616
00617 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
00618
00619
00620
00621 if (! xstormy16_cgen_insn_supported (cd, insn))
00622 continue;
00623 #endif
00624
00625
00626
00627 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
00628 continue;
00629
00630 str = start;
00631
00632
00633 if (CGEN_INSN_RX (insn) != NULL &&
00634 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
00635 continue;
00636
00637
00638 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
00639
00640 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
00641 if (parse_errmsg != NULL)
00642 continue;
00643
00644
00645 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
00646 (bfd_vma) 0);
00647 if (insert_errmsg != NULL)
00648 continue;
00649
00650
00651
00652 return insn;
00653 }
00654
00655 {
00656 static char errbuf[150];
00657 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
00658 const char *tmp_errmsg;
00659
00660
00661
00662 tmp_errmsg = (insert_errmsg ? insert_errmsg :
00663 parse_errmsg ? parse_errmsg :
00664 recognized_mnemonic ?
00665 _("unrecognized form of instruction") :
00666 _("unrecognized instruction"));
00667
00668 if (strlen (start) > 50)
00669
00670 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
00671 else
00672
00673 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
00674 #else
00675 if (strlen (start) > 50)
00676
00677 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
00678 else
00679
00680 sprintf (errbuf, _("bad instruction `%.50s'"), start);
00681 #endif
00682
00683 *errmsg = errbuf;
00684 return NULL;
00685 }
00686 }
00687
00688 #if 0
00689
00690
00691
00692
00693
00694
00695
00696
00697 void
00698 xstormy16_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
00699 {
00700 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
00701 const CGEN_KEYWORD_ENTRY * ke;
00702
00703 while ((ke = cgen_keyword_search_next (& search)) != NULL)
00704 {
00705 #if 0
00706 if (! xstormy16_cgen_opval_supported (ke))
00707 continue;
00708 #endif
00709 cgen_asm_record_register (cd, ke->name, ke->value);
00710 }
00711 }
00712
00713 #endif