[BACK]Return to fr30-asm.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils / dist / opcodes

Annotation of src/external/gpl3/binutils/dist/opcodes/fr30-asm.c, Revision 1.1.1.5.2.2

1.1.1.5   christos    1: /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
1.1       skrll       2: /* Assembler interface for targets using CGEN. -*- C -*-
                      3:    CGEN: Cpu tools GENerator
                      4:
                      5:    THIS FILE IS MACHINE GENERATED WITH CGEN.
                      6:    - the resultant file is machine generated, cgen-asm.in isn't
                      7:
1.1.1.5.2.2! martin      8:    Copyright (C) 1996-2020 Free Software Foundation, Inc.
1.1       skrll       9:
                     10:    This file is part of libopcodes.
                     11:
                     12:    This library is free software; you can redistribute it and/or modify
                     13:    it under the terms of the GNU General Public License as published by
                     14:    the Free Software Foundation; either version 3, or (at your option)
                     15:    any later version.
                     16:
                     17:    It is distributed in the hope that it will be useful, but WITHOUT
                     18:    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     19:    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
                     20:    License for more details.
                     21:
                     22:    You should have received a copy of the GNU General Public License
                     23:    along with this program; if not, write to the Free Software Foundation, Inc.,
                     24:    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
                     25:
                     26:
                     27: /* ??? Eventually more and more of this stuff can go to cpu-independent files.
                     28:    Keep that in mind.  */
                     29:
                     30: #include "sysdep.h"
                     31: #include <stdio.h>
                     32: #include "ansidecl.h"
                     33: #include "bfd.h"
                     34: #include "symcat.h"
                     35: #include "fr30-desc.h"
                     36: #include "fr30-opc.h"
                     37: #include "opintl.h"
                     38: #include "xregex.h"
                     39: #include "libiberty.h"
                     40: #include "safe-ctype.h"
                     41:
                     42: #undef  min
                     43: #define min(a,b) ((a) < (b) ? (a) : (b))
                     44: #undef  max
                     45: #define max(a,b) ((a) > (b) ? (a) : (b))
                     46:
                     47: static const char * parse_insn_normal
                     48:   (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
                     49: 
                     50: /* -- assembler routines inserted here.  */
                     51:
                     52: /* -- asm.c */
                     53: /* Handle register lists for LDMx and STMx.  */
                     54:
                     55: static int
                     56: parse_register_number (const char **strp)
                     57: {
                     58:   int regno;
                     59:
                     60:   if (**strp < '0' || **strp > '9')
                     61:     return -1; /* Error.  */
                     62:   regno = **strp - '0';
                     63:   ++*strp;
                     64:
                     65:   if (**strp >= '0' && **strp <= '9')
                     66:     {
                     67:       regno = regno * 10 + (**strp - '0');
                     68:       ++*strp;
                     69:     }
                     70:
                     71:   return regno;
                     72: }
                     73:
                     74: static const char *
                     75: parse_register_list (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
                     76:                     const char **strp,
                     77:                     int opindex ATTRIBUTE_UNUSED,
                     78:                     unsigned long *valuep,
                     79:                     int high_low,   /* 0 == high, 1 == low.  */
                     80:                     int load_store) /* 0 == load, 1 == store.  */
                     81: {
                     82:   *valuep = 0;
                     83:   while (**strp && **strp != ')')
                     84:     {
                     85:       int regno;
                     86:
                     87:       if (**strp != 'R' && **strp != 'r')
                     88:        break;
                     89:       ++*strp;
                     90:
                     91:       regno = parse_register_number (strp);
                     92:       if (regno == -1)
                     93:        return _("Register number is not valid");
                     94:       if (regno > 7 && !high_low)
                     95:        return _("Register must be between r0 and r7");
                     96:       if (regno < 8 && high_low)
                     97:        return _("Register must be between r8 and r15");
                     98:
                     99:       if (high_low)
                    100:        regno -= 8;
                    101:
                    102:       if (load_store) /* Mask is reversed for store.  */
                    103:        *valuep |= 0x80 >> regno;
                    104:       else
                    105:        *valuep |= 1 << regno;
                    106:
                    107:       if (**strp == ',')
                    108:        {
                    109:          if (*(*strp + 1) == ')')
                    110:            break;
                    111:          ++*strp;
                    112:        }
                    113:     }
                    114:
                    115:   if (!*strp || **strp != ')')
                    116:     return _("Register list is not valid");
                    117:
                    118:   return NULL;
                    119: }
                    120:
                    121: static const char *
                    122: parse_low_register_list_ld (CGEN_CPU_DESC cd,
                    123:                            const char **strp,
                    124:                            int opindex,
                    125:                            unsigned long *valuep)
                    126: {
                    127:   return parse_register_list (cd, strp, opindex, valuep,
                    128:                              0 /* Low.  */, 0 /* Load.  */);
                    129: }
                    130:
                    131: static const char *
                    132: parse_hi_register_list_ld (CGEN_CPU_DESC cd,
                    133:                           const char **strp,
                    134:                           int opindex,
                    135:                           unsigned long *valuep)
                    136: {
                    137:   return parse_register_list (cd, strp, opindex, valuep,
                    138:                              1 /* High.  */, 0 /* Load.  */);
                    139: }
                    140:
                    141: static const char *
                    142: parse_low_register_list_st (CGEN_CPU_DESC cd,
                    143:                            const char **strp,
                    144:                            int opindex,
                    145:                            unsigned long *valuep)
                    146: {
                    147:   return parse_register_list (cd, strp, opindex, valuep,
                    148:                              0 /* Low.  */, 1 /* Store.  */);
                    149: }
                    150:
                    151: static const char *
                    152: parse_hi_register_list_st (CGEN_CPU_DESC cd,
                    153:                           const char **strp,
                    154:                           int opindex,
                    155:                           unsigned long *valuep)
                    156: {
                    157:   return parse_register_list (cd, strp, opindex, valuep,
                    158:                              1 /* High.  */, 1 /* Store.  */);
                    159: }
                    160:
                    161: /* -- */
                    162:
                    163: const char * fr30_cgen_parse_operand
                    164:   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
                    165:
                    166: /* Main entry point for operand parsing.
                    167:
                    168:    This function is basically just a big switch statement.  Earlier versions
                    169:    used tables to look up the function to use, but
                    170:    - if the table contains both assembler and disassembler functions then
                    171:      the disassembler contains much of the assembler and vice-versa,
                    172:    - there's a lot of inlining possibilities as things grow,
                    173:    - using a switch statement avoids the function call overhead.
                    174:
                    175:    This function could be moved into `parse_insn_normal', but keeping it
                    176:    separate makes clear the interface between `parse_insn_normal' and each of
                    177:    the handlers.  */
                    178:
                    179: const char *
                    180: fr30_cgen_parse_operand (CGEN_CPU_DESC cd,
                    181:                           int opindex,
                    182:                           const char ** strp,
                    183:                           CGEN_FIELDS * fields)
                    184: {
                    185:   const char * errmsg = NULL;
                    186:   /* Used by scalar operands that still need to be parsed.  */
                    187:   long junk ATTRIBUTE_UNUSED;
                    188:
                    189:   switch (opindex)
                    190:     {
                    191:     case FR30_OPERAND_CRI :
                    192:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRi);
                    193:       break;
                    194:     case FR30_OPERAND_CRJ :
                    195:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRj);
                    196:       break;
                    197:     case FR30_OPERAND_R13 :
                    198:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r13, & junk);
                    199:       break;
                    200:     case FR30_OPERAND_R14 :
                    201:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r14, & junk);
                    202:       break;
                    203:     case FR30_OPERAND_R15 :
                    204:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r15, & junk);
                    205:       break;
                    206:     case FR30_OPERAND_RI :
                    207:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ri);
                    208:       break;
                    209:     case FR30_OPERAND_RIC :
                    210:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ric);
                    211:       break;
                    212:     case FR30_OPERAND_RJ :
                    213:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rj);
                    214:       break;
                    215:     case FR30_OPERAND_RJC :
                    216:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rjc);
                    217:       break;
                    218:     case FR30_OPERAND_RS1 :
                    219:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs1);
                    220:       break;
                    221:     case FR30_OPERAND_RS2 :
                    222:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs2);
                    223:       break;
                    224:     case FR30_OPERAND_CC :
                    225:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CC, (unsigned long *) (& fields->f_cc));
                    226:       break;
                    227:     case FR30_OPERAND_CCC :
                    228:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CCC, (unsigned long *) (& fields->f_ccc));
                    229:       break;
                    230:     case FR30_OPERAND_DIR10 :
                    231:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR10, (unsigned long *) (& fields->f_dir10));
                    232:       break;
                    233:     case FR30_OPERAND_DIR8 :
                    234:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR8, (unsigned long *) (& fields->f_dir8));
                    235:       break;
                    236:     case FR30_OPERAND_DIR9 :
                    237:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR9, (unsigned long *) (& fields->f_dir9));
                    238:       break;
                    239:     case FR30_OPERAND_DISP10 :
                    240:       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP10, (long *) (& fields->f_disp10));
                    241:       break;
                    242:     case FR30_OPERAND_DISP8 :
                    243:       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP8, (long *) (& fields->f_disp8));
                    244:       break;
                    245:     case FR30_OPERAND_DISP9 :
                    246:       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP9, (long *) (& fields->f_disp9));
                    247:       break;
                    248:     case FR30_OPERAND_I20 :
                    249:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I20, (unsigned long *) (& fields->f_i20));
                    250:       break;
                    251:     case FR30_OPERAND_I32 :
                    252:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I32, (unsigned long *) (& fields->f_i32));
                    253:       break;
                    254:     case FR30_OPERAND_I8 :
                    255:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I8, (unsigned long *) (& fields->f_i8));
                    256:       break;
                    257:     case FR30_OPERAND_LABEL12 :
                    258:       {
                    259:         bfd_vma value = 0;
                    260:         errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL12, 0, NULL,  & value);
                    261:         fields->f_rel12 = value;
                    262:       }
                    263:       break;
                    264:     case FR30_OPERAND_LABEL9 :
                    265:       {
                    266:         bfd_vma value = 0;
                    267:         errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
                    268:         fields->f_rel9 = value;
                    269:       }
                    270:       break;
                    271:     case FR30_OPERAND_M4 :
                    272:       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_M4, (long *) (& fields->f_m4));
                    273:       break;
                    274:     case FR30_OPERAND_PS :
                    275:       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_ps, & junk);
                    276:       break;
                    277:     case FR30_OPERAND_REGLIST_HI_LD :
                    278:       errmsg = parse_hi_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_HI_LD, (unsigned long *) (& fields->f_reglist_hi_ld));
                    279:       break;
                    280:     case FR30_OPERAND_REGLIST_HI_ST :
                    281:       errmsg = parse_hi_register_list_st (cd, strp, FR30_OPERAND_REGLIST_HI_ST, (unsigned long *) (& fields->f_reglist_hi_st));
                    282:       break;
                    283:     case FR30_OPERAND_REGLIST_LOW_LD :
                    284:       errmsg = parse_low_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_LOW_LD, (unsigned long *) (& fields->f_reglist_low_ld));
                    285:       break;
                    286:     case FR30_OPERAND_REGLIST_LOW_ST :
                    287:       errmsg = parse_low_register_list_st (cd, strp, FR30_OPERAND_REGLIST_LOW_ST, (unsigned long *) (& fields->f_reglist_low_st));
                    288:       break;
                    289:     case FR30_OPERAND_S10 :
                    290:       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_S10, (long *) (& fields->f_s10));
                    291:       break;
                    292:     case FR30_OPERAND_U10 :
                    293:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U10, (unsigned long *) (& fields->f_u10));
                    294:       break;
                    295:     case FR30_OPERAND_U4 :
                    296:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4, (unsigned long *) (& fields->f_u4));
                    297:       break;
                    298:     case FR30_OPERAND_U4C :
                    299:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4C, (unsigned long *) (& fields->f_u4c));
                    300:       break;
                    301:     case FR30_OPERAND_U8 :
                    302:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U8, (unsigned long *) (& fields->f_u8));
                    303:       break;
                    304:     case FR30_OPERAND_UDISP6 :
                    305:       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_UDISP6, (unsigned long *) (& fields->f_udisp6));
                    306:       break;
                    307:
                    308:     default :
                    309:       /* xgettext:c-format */
1.1.1.5.2.1  christos  310:       opcodes_error_handler
                    311:        (_("internal error: unrecognized field %d while parsing"),
                    312:         opindex);
1.1       skrll     313:       abort ();
                    314:   }
                    315:
                    316:   return errmsg;
                    317: }
                    318:
1.1.1.3   christos  319: cgen_parse_fn * const fr30_cgen_parse_handlers[] =
1.1       skrll     320: {
                    321:   parse_insn_normal,
                    322: };
                    323:
                    324: void
                    325: fr30_cgen_init_asm (CGEN_CPU_DESC cd)
                    326: {
                    327:   fr30_cgen_init_opcode_table (cd);
                    328:   fr30_cgen_init_ibld_table (cd);
                    329:   cd->parse_handlers = & fr30_cgen_parse_handlers[0];
                    330:   cd->parse_operand = fr30_cgen_parse_operand;
                    331: #ifdef CGEN_ASM_INIT_HOOK
                    332: CGEN_ASM_INIT_HOOK
                    333: #endif
                    334: }
                    335:
                    336: 
                    337:
                    338: /* Regex construction routine.
                    339:
                    340:    This translates an opcode syntax string into a regex string,
                    341:    by replacing any non-character syntax element (such as an
                    342:    opcode) with the pattern '.*'
                    343:
                    344:    It then compiles the regex and stores it in the opcode, for
                    345:    later use by fr30_cgen_assemble_insn
                    346:
                    347:    Returns NULL for success, an error message for failure.  */
                    348:
1.1.1.3   christos  349: char *
1.1       skrll     350: fr30_cgen_build_insn_regex (CGEN_INSN *insn)
1.1.1.3   christos  351: {
1.1       skrll     352:   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
                    353:   const char *mnem = CGEN_INSN_MNEMONIC (insn);
                    354:   char rxbuf[CGEN_MAX_RX_ELEMENTS];
                    355:   char *rx = rxbuf;
                    356:   const CGEN_SYNTAX_CHAR_TYPE *syn;
                    357:   int reg_err;
                    358:
                    359:   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
                    360:
                    361:   /* Mnemonics come first in the syntax string.  */
                    362:   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
                    363:     return _("missing mnemonic in syntax string");
                    364:   ++syn;
                    365:
                    366:   /* Generate a case sensitive regular expression that emulates case
                    367:      insensitive matching in the "C" locale.  We cannot generate a case
                    368:      insensitive regular expression because in Turkish locales, 'i' and 'I'
                    369:      are not equal modulo case conversion.  */
                    370:
                    371:   /* Copy the literal mnemonic out of the insn.  */
                    372:   for (; *mnem; mnem++)
                    373:     {
                    374:       char c = *mnem;
                    375:
                    376:       if (ISALPHA (c))
                    377:        {
                    378:          *rx++ = '[';
                    379:          *rx++ = TOLOWER (c);
                    380:          *rx++ = TOUPPER (c);
                    381:          *rx++ = ']';
                    382:        }
                    383:       else
                    384:        *rx++ = c;
                    385:     }
                    386:
                    387:   /* Copy any remaining literals from the syntax string into the rx.  */
                    388:   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
                    389:     {
1.1.1.3   christos  390:       if (CGEN_SYNTAX_CHAR_P (* syn))
1.1       skrll     391:        {
                    392:          char c = CGEN_SYNTAX_CHAR (* syn);
                    393:
1.1.1.3   christos  394:          switch (c)
1.1       skrll     395:            {
                    396:              /* Escape any regex metacharacters in the syntax.  */
1.1.1.3   christos  397:            case '.': case '[': case '\\':
                    398:            case '*': case '^': case '$':
1.1       skrll     399:
                    400: #ifdef CGEN_ESCAPE_EXTENDED_REGEX
1.1.1.3   christos  401:            case '?': case '{': case '}':
1.1       skrll     402:            case '(': case ')': case '*':
                    403:            case '|': case '+': case ']':
                    404: #endif
                    405:              *rx++ = '\\';
                    406:              *rx++ = c;
                    407:              break;
                    408:
                    409:            default:
                    410:              if (ISALPHA (c))
                    411:                {
                    412:                  *rx++ = '[';
                    413:                  *rx++ = TOLOWER (c);
                    414:                  *rx++ = TOUPPER (c);
                    415:                  *rx++ = ']';
                    416:                }
                    417:              else
                    418:                *rx++ = c;
                    419:              break;
                    420:            }
                    421:        }
                    422:       else
                    423:        {
                    424:          /* Replace non-syntax fields with globs.  */
                    425:          *rx++ = '.';
                    426:          *rx++ = '*';
                    427:        }
                    428:     }
                    429:
                    430:   /* Trailing whitespace ok.  */
1.1.1.3   christos  431:   * rx++ = '[';
                    432:   * rx++ = ' ';
                    433:   * rx++ = '\t';
                    434:   * rx++ = ']';
                    435:   * rx++ = '*';
1.1       skrll     436:
                    437:   /* But anchor it after that.  */
1.1.1.3   christos  438:   * rx++ = '$';
1.1       skrll     439:   * rx = '\0';
                    440:
                    441:   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
                    442:   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
                    443:
1.1.1.3   christos  444:   if (reg_err == 0)
1.1       skrll     445:     return NULL;
                    446:   else
                    447:     {
                    448:       static char msg[80];
                    449:
                    450:       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
                    451:       regfree ((regex_t *) CGEN_INSN_RX (insn));
                    452:       free (CGEN_INSN_RX (insn));
                    453:       (CGEN_INSN_RX (insn)) = NULL;
                    454:       return msg;
                    455:     }
                    456: }
                    457:
                    458: 
                    459: /* Default insn parser.
                    460:
                    461:    The syntax string is scanned and operands are parsed and stored in FIELDS.
                    462:    Relocs are queued as we go via other callbacks.
                    463:
                    464:    ??? Note that this is currently an all-or-nothing parser.  If we fail to
                    465:    parse the instruction, we return 0 and the caller will start over from
                    466:    the beginning.  Backtracking will be necessary in parsing subexpressions,
                    467:    but that can be handled there.  Not handling backtracking here may get
                    468:    expensive in the case of the m68k.  Deal with later.
                    469:
                    470:    Returns NULL for success, an error message for failure.  */
                    471:
                    472: static const char *
                    473: parse_insn_normal (CGEN_CPU_DESC cd,
                    474:                   const CGEN_INSN *insn,
                    475:                   const char **strp,
                    476:                   CGEN_FIELDS *fields)
                    477: {
                    478:   /* ??? Runtime added insns not handled yet.  */
                    479:   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
                    480:   const char *str = *strp;
                    481:   const char *errmsg;
                    482:   const char *p;
                    483:   const CGEN_SYNTAX_CHAR_TYPE * syn;
                    484: #ifdef CGEN_MNEMONIC_OPERANDS
                    485:   /* FIXME: wip */
                    486:   int past_opcode_p;
                    487: #endif
                    488:
                    489:   /* For now we assume the mnemonic is first (there are no leading operands).
                    490:      We can parse it without needing to set up operand parsing.
                    491:      GAS's input scrubber will ensure mnemonics are lowercase, but we may
                    492:      not be called from GAS.  */
                    493:   p = CGEN_INSN_MNEMONIC (insn);
                    494:   while (*p && TOLOWER (*p) == TOLOWER (*str))
                    495:     ++p, ++str;
                    496:
                    497:   if (* p)
                    498:     return _("unrecognized instruction");
                    499:
                    500: #ifndef CGEN_MNEMONIC_OPERANDS
                    501:   if (* str && ! ISSPACE (* str))
                    502:     return _("unrecognized instruction");
                    503: #endif
                    504:
                    505:   CGEN_INIT_PARSE (cd);
                    506:   cgen_init_parse_operand (cd);
                    507: #ifdef CGEN_MNEMONIC_OPERANDS
                    508:   past_opcode_p = 0;
                    509: #endif
                    510:
                    511:   /* We don't check for (*str != '\0') here because we want to parse
                    512:      any trailing fake arguments in the syntax string.  */
                    513:   syn = CGEN_SYNTAX_STRING (syntax);
                    514:
                    515:   /* Mnemonics come first for now, ensure valid string.  */
                    516:   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
                    517:     abort ();
                    518:
                    519:   ++syn;
                    520:
                    521:   while (* syn != 0)
                    522:     {
                    523:       /* Non operand chars must match exactly.  */
                    524:       if (CGEN_SYNTAX_CHAR_P (* syn))
                    525:        {
                    526:          /* FIXME: While we allow for non-GAS callers above, we assume the
                    527:             first char after the mnemonic part is a space.  */
                    528:          /* FIXME: We also take inappropriate advantage of the fact that
                    529:             GAS's input scrubber will remove extraneous blanks.  */
                    530:          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
                    531:            {
                    532: #ifdef CGEN_MNEMONIC_OPERANDS
                    533:              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
                    534:                past_opcode_p = 1;
                    535: #endif
                    536:              ++ syn;
                    537:              ++ str;
                    538:            }
                    539:          else if (*str)
                    540:            {
                    541:              /* Syntax char didn't match.  Can't be this insn.  */
                    542:              static char msg [80];
                    543:
                    544:              /* xgettext:c-format */
                    545:              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
                    546:                       CGEN_SYNTAX_CHAR(*syn), *str);
                    547:              return msg;
                    548:            }
                    549:          else
                    550:            {
                    551:              /* Ran out of input.  */
                    552:              static char msg [80];
                    553:
                    554:              /* xgettext:c-format */
                    555:              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
                    556:                       CGEN_SYNTAX_CHAR(*syn));
                    557:              return msg;
                    558:            }
                    559:          continue;
                    560:        }
                    561:
1.1.1.2   christos  562: #ifdef CGEN_MNEMONIC_OPERANDS
                    563:       (void) past_opcode_p;
                    564: #endif
1.1       skrll     565:       /* We have an operand of some sort.  */
1.1.1.2   christos  566:       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
1.1       skrll     567:       if (errmsg)
                    568:        return errmsg;
                    569:
                    570:       /* Done with this operand, continue with next one.  */
                    571:       ++ syn;
                    572:     }
                    573:
                    574:   /* If we're at the end of the syntax string, we're done.  */
                    575:   if (* syn == 0)
                    576:     {
                    577:       /* FIXME: For the moment we assume a valid `str' can only contain
                    578:         blanks now.  IE: We needn't try again with a longer version of
                    579:         the insn and it is assumed that longer versions of insns appear
                    580:         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
                    581:       while (ISSPACE (* str))
                    582:        ++ str;
                    583:
                    584:       if (* str != '\0')
                    585:        return _("junk at end of line"); /* FIXME: would like to include `str' */
                    586:
                    587:       return NULL;
                    588:     }
                    589:
                    590:   /* We couldn't parse it.  */
                    591:   return _("unrecognized instruction");
                    592: }
                    593: 
                    594: /* Main entry point.
                    595:    This routine is called for each instruction to be assembled.
                    596:    STR points to the insn to be assembled.
                    597:    We assume all necessary tables have been initialized.
                    598:    The assembled instruction, less any fixups, is stored in BUF.
                    599:    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
                    600:    still needs to be converted to target byte order, otherwise BUF is an array
                    601:    of bytes in target byte order.
                    602:    The result is a pointer to the insn's entry in the opcode table,
                    603:    or NULL if an error occured (an error message will have already been
                    604:    printed).
                    605:
                    606:    Note that when processing (non-alias) macro-insns,
                    607:    this function recurses.
                    608:
                    609:    ??? It's possible to make this cpu-independent.
                    610:    One would have to deal with a few minor things.
                    611:    At this point in time doing so would be more of a curiosity than useful
                    612:    [for example this file isn't _that_ big], but keeping the possibility in
                    613:    mind helps keep the design clean.  */
                    614:
                    615: const CGEN_INSN *
                    616: fr30_cgen_assemble_insn (CGEN_CPU_DESC cd,
                    617:                           const char *str,
                    618:                           CGEN_FIELDS *fields,
                    619:                           CGEN_INSN_BYTES_PTR buf,
                    620:                           char **errmsg)
                    621: {
                    622:   const char *start;
                    623:   CGEN_INSN_LIST *ilist;
                    624:   const char *parse_errmsg = NULL;
                    625:   const char *insert_errmsg = NULL;
                    626:   int recognized_mnemonic = 0;
                    627:
                    628:   /* Skip leading white space.  */
                    629:   while (ISSPACE (* str))
                    630:     ++ str;
                    631:
                    632:   /* The instructions are stored in hashed lists.
                    633:      Get the first in the list.  */
                    634:   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
                    635:
                    636:   /* Keep looking until we find a match.  */
                    637:   start = str;
                    638:   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
                    639:     {
                    640:       const CGEN_INSN *insn = ilist->insn;
                    641:       recognized_mnemonic = 1;
                    642:
1.1.1.3   christos  643: #ifdef CGEN_VALIDATE_INSN_SUPPORTED
1.1       skrll     644:       /* Not usually needed as unsupported opcodes
                    645:         shouldn't be in the hash lists.  */
                    646:       /* Is this insn supported by the selected cpu?  */
                    647:       if (! fr30_cgen_insn_supported (cd, insn))
                    648:        continue;
                    649: #endif
                    650:       /* If the RELAXED attribute is set, this is an insn that shouldn't be
                    651:         chosen immediately.  Instead, it is used during assembler/linker
                    652:         relaxation if possible.  */
                    653:       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
                    654:        continue;
                    655:
                    656:       str = start;
                    657:
                    658:       /* Skip this insn if str doesn't look right lexically.  */
                    659:       if (CGEN_INSN_RX (insn) != NULL &&
                    660:          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
                    661:        continue;
                    662:
                    663:       /* Allow parse/insert handlers to obtain length of insn.  */
                    664:       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
                    665:
                    666:       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
                    667:       if (parse_errmsg != NULL)
                    668:        continue;
                    669:
                    670:       /* ??? 0 is passed for `pc'.  */
                    671:       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
                    672:                                                 (bfd_vma) 0);
                    673:       if (insert_errmsg != NULL)
                    674:         continue;
                    675:
                    676:       /* It is up to the caller to actually output the insn and any
                    677:          queued relocs.  */
                    678:       return insn;
                    679:     }
                    680:
                    681:   {
                    682:     static char errbuf[150];
                    683:     const char *tmp_errmsg;
1.1.1.2   christos  684: #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
                    685: #define be_verbose 1
1.1       skrll     686: #else
1.1.1.2   christos  687: #define be_verbose 0
1.1       skrll     688: #endif
1.1.1.2   christos  689:
                    690:     if (be_verbose)
                    691:       {
                    692:        /* If requesting verbose error messages, use insert_errmsg.
                    693:           Failing that, use parse_errmsg.  */
                    694:        tmp_errmsg = (insert_errmsg ? insert_errmsg :
                    695:                      parse_errmsg ? parse_errmsg :
                    696:                      recognized_mnemonic ?
                    697:                      _("unrecognized form of instruction") :
                    698:                      _("unrecognized instruction"));
                    699:
                    700:        if (strlen (start) > 50)
                    701:          /* xgettext:c-format */
                    702:          sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1.1.1.3   christos  703:        else
1.1.1.2   christos  704:          /* xgettext:c-format */
                    705:          sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
                    706:       }
                    707:     else
                    708:       {
                    709:        if (strlen (start) > 50)
                    710:          /* xgettext:c-format */
                    711:          sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1.1.1.3   christos  712:        else
1.1.1.2   christos  713:          /* xgettext:c-format */
                    714:          sprintf (errbuf, _("bad instruction `%.50s'"), start);
                    715:       }
1.1.1.3   christos  716:
1.1       skrll     717:     *errmsg = errbuf;
                    718:     return NULL;
                    719:   }
                    720: }

CVSweb <webmaster@jp.NetBSD.org>