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