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

Annotation of src/external/gpl3/binutils.old/dist/opcodes/or1k-asm.c, Revision 1.7

1.6       christos    1: /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
1.1       christos    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.7     ! christos    8:    Copyright (C) 1996-2020 Free Software Foundation, Inc.
1.1       christos    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 "or1k-desc.h"
                     36: #include "or1k-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:
                     54: static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
1.7     ! christos   55: static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
        !            56: static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
1.1       christos   57:
                     58: #define CGEN_VERBOSE_ASSEMBLER_ERRORS
                     59:
                     60: static const char *
                     61: parse_disp26 (CGEN_CPU_DESC cd,
                     62:              const char ** strp,
                     63:              int opindex,
1.7     ! christos   64:              int opinfo ATTRIBUTE_UNUSED,
1.1       christos   65:              enum cgen_parse_operand_result * resultp,
                     66:              bfd_vma * valuep)
                     67: {
1.7     ! christos   68:   const char *str = *strp;
1.1       christos   69:   const char *errmsg = NULL;
1.7     ! christos   70:   bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
1.1       christos   71:
1.7     ! christos   72:   if (strncasecmp (str, "plta(", 5) == 0)
        !            73:     {
        !            74:       *strp = str + 5;
        !            75:       reloc = BFD_RELOC_OR1K_PLTA26;
        !            76:     }
        !            77:   else if (strncasecmp (str, "plt(", 4) == 0)
1.1       christos   78:     {
1.7     ! christos   79:       *strp = str + 4;
        !            80:       reloc = BFD_RELOC_OR1K_PLT26;
1.1       christos   81:     }
                     82:
1.7     ! christos   83:   errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
1.1       christos   84:
1.7     ! christos   85:   if (reloc != BFD_RELOC_OR1K_REL_26)
1.1       christos   86:     {
                     87:       if (**strp != ')')
                     88:        errmsg = MISSING_CLOSING_PARENTHESIS;
1.7     ! christos   89:       else
        !            90:        ++*strp;
1.1       christos   91:     }
                     92:
1.7     ! christos   93:   return errmsg;
        !            94: }
1.1       christos   95:
1.7     ! christos   96: static const char *
        !            97: parse_disp21 (CGEN_CPU_DESC cd,
        !            98:              const char ** strp,
        !            99:              int opindex,
        !           100:              int opinfo ATTRIBUTE_UNUSED,
        !           101:              enum cgen_parse_operand_result * resultp,
        !           102:              bfd_vma * valuep)
        !           103: {
        !           104:   const char *str = *strp;
        !           105:   const char *errmsg = NULL;
        !           106:   bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
1.1       christos  107:
1.7     ! christos  108:   if (strncasecmp (str, "got(", 4) == 0)
        !           109:     {
        !           110:       *strp = str + 4;
        !           111:       reloc = BFD_RELOC_OR1K_GOT_PG21;
1.1       christos  112:     }
1.7     ! christos  113:   else if (strncasecmp (str, "tlsgd(", 6) == 0)
1.1       christos  114:     {
1.7     ! christos  115:       *strp = str + 6;
        !           116:       reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
1.1       christos  117:     }
1.7     ! christos  118:   else if (strncasecmp (str, "tlsldm(", 7) == 0)
1.1       christos  119:     {
1.7     ! christos  120:       *strp = str + 7;
        !           121:       reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
1.1       christos  122:     }
1.7     ! christos  123:   else if (strncasecmp (str, "gottp(", 6) == 0)
1.1       christos  124:     {
1.7     ! christos  125:       *strp = str + 6;
        !           126:       reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
1.1       christos  127:     }
                    128:
1.7     ! christos  129:   errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
1.1       christos  130:
1.7     ! christos  131:   if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
        !           132:     {
1.1       christos  133:       if (**strp != ')')
1.7     ! christos  134:        errmsg = MISSING_CLOSING_PARENTHESIS;
        !           135:       else
        !           136:        ++*strp;
1.1       christos  137:     }
                    138:
1.7     ! christos  139:   return errmsg;
        !           140: }
        !           141:
        !           142: enum or1k_rclass
        !           143: {
        !           144:   RCLASS_DIRECT   = 0,
        !           145:   RCLASS_GOT      = 1,
        !           146:   RCLASS_GOTPC    = 2,
        !           147:   RCLASS_GOTOFF   = 3,
        !           148:   RCLASS_TLSGD    = 4,
        !           149:   RCLASS_TLSLDM   = 5,
        !           150:   RCLASS_DTPOFF   = 6,
        !           151:   RCLASS_GOTTPOFF = 7,
        !           152:   RCLASS_TPOFF    = 8,
        !           153: };
1.1       christos  154:
1.7     ! christos  155: enum or1k_rtype
        !           156: {
        !           157:   RTYPE_LO = 0,
        !           158:   RTYPE_SLO = 1,
        !           159:   RTYPE_PO = 2,
        !           160:   RTYPE_SPO = 3,
        !           161:   RTYPE_HI = 4,
        !           162:   RTYPE_AHI = 5,
        !           163: };
1.1       christos  164:
1.7     ! christos  165: #define RCLASS_SHIFT 3
        !           166: #define RTYPE_MASK   7
1.1       christos  167:
1.7     ! christos  168: static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
        !           169:   { BFD_RELOC_LO16,
        !           170:     BFD_RELOC_OR1K_SLO16,
        !           171:     BFD_RELOC_OR1K_LO13,
        !           172:     BFD_RELOC_OR1K_SLO13,
        !           173:     BFD_RELOC_HI16,
        !           174:     BFD_RELOC_HI16_S, },
        !           175:   { BFD_RELOC_OR1K_GOT16,
        !           176:     BFD_RELOC_UNUSED,
        !           177:     BFD_RELOC_OR1K_GOT_LO13,
        !           178:     BFD_RELOC_UNUSED,
        !           179:     BFD_RELOC_UNUSED,
        !           180:     BFD_RELOC_UNUSED },
        !           181:   { BFD_RELOC_OR1K_GOTPC_LO16,
        !           182:     BFD_RELOC_UNUSED,
        !           183:     BFD_RELOC_UNUSED,
        !           184:     BFD_RELOC_UNUSED,
        !           185:     BFD_RELOC_OR1K_GOTPC_HI16,
        !           186:     BFD_RELOC_UNUSED },
        !           187:   { BFD_RELOC_LO16_GOTOFF,
        !           188:     BFD_RELOC_OR1K_GOTOFF_SLO16,
        !           189:     BFD_RELOC_UNUSED,
        !           190:     BFD_RELOC_UNUSED,
        !           191:     BFD_RELOC_HI16_GOTOFF,
        !           192:     BFD_RELOC_HI16_S_GOTOFF },
        !           193:   { BFD_RELOC_OR1K_TLS_GD_LO16,
        !           194:     BFD_RELOC_UNUSED,
        !           195:     BFD_RELOC_OR1K_TLS_GD_LO13,
        !           196:     BFD_RELOC_UNUSED,
        !           197:     BFD_RELOC_OR1K_TLS_GD_HI16,
        !           198:     BFD_RELOC_UNUSED },
        !           199:   { BFD_RELOC_OR1K_TLS_LDM_LO16,
        !           200:     BFD_RELOC_UNUSED,
        !           201:     BFD_RELOC_OR1K_TLS_LDM_LO13,
        !           202:     BFD_RELOC_UNUSED,
        !           203:     BFD_RELOC_OR1K_TLS_LDM_HI16,
        !           204:     BFD_RELOC_UNUSED },
        !           205:   { BFD_RELOC_OR1K_TLS_LDO_LO16,
        !           206:     BFD_RELOC_UNUSED,
        !           207:     BFD_RELOC_UNUSED,
        !           208:     BFD_RELOC_UNUSED,
        !           209:     BFD_RELOC_OR1K_TLS_LDO_HI16,
        !           210:     BFD_RELOC_UNUSED },
        !           211:   { BFD_RELOC_OR1K_TLS_IE_LO16,
        !           212:     BFD_RELOC_UNUSED,
        !           213:     BFD_RELOC_OR1K_TLS_IE_LO13,
        !           214:     BFD_RELOC_UNUSED,
        !           215:     BFD_RELOC_OR1K_TLS_IE_HI16,
        !           216:     BFD_RELOC_OR1K_TLS_IE_AHI16 },
        !           217:   { BFD_RELOC_OR1K_TLS_LE_LO16,
        !           218:     BFD_RELOC_OR1K_TLS_LE_SLO16,
        !           219:     BFD_RELOC_UNUSED,
        !           220:     BFD_RELOC_UNUSED,
        !           221:     BFD_RELOC_OR1K_TLS_LE_HI16,
        !           222:     BFD_RELOC_OR1K_TLS_LE_AHI16 },
        !           223: };
1.1       christos  224:
1.7     ! christos  225: static int
        !           226: parse_reloc (const char **strp)
        !           227: {
        !           228:     const char *str = *strp;
        !           229:     enum or1k_rclass cls = RCLASS_DIRECT;
        !           230:     enum or1k_rtype typ;
1.1       christos  231:
1.7     ! christos  232:     if (strncasecmp (str, "got(", 4) == 0)
        !           233:       {
        !           234:        *strp = str + 4;
        !           235:        return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
        !           236:       }
        !           237:     if (strncasecmp (str, "gotpo(", 6) == 0)
        !           238:       {
        !           239:        *strp = str + 6;
        !           240:        return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
        !           241:       }
        !           242:     if (strncasecmp (str, "gottppo(", 8) == 0)
        !           243:       {
        !           244:        *strp = str + 8;
        !           245:        return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
        !           246:       }
1.1       christos  247:
1.7     ! christos  248:     if (strncasecmp (str, "gotpc", 5) == 0)
        !           249:       {
        !           250:        str += 5;
        !           251:        cls = RCLASS_GOTPC;
        !           252:       }
        !           253:     else if (strncasecmp (str, "gotoff", 6) == 0)
        !           254:       {
        !           255:        str += 6;
        !           256:        cls = RCLASS_GOTOFF;
        !           257:       }
        !           258:     else if (strncasecmp (str, "tlsgd", 5) == 0)
        !           259:       {
        !           260:        str += 5;
        !           261:        cls = RCLASS_TLSGD;
        !           262:       }
        !           263:     else if (strncasecmp (str, "tlsldm", 6) == 0)
        !           264:       {
        !           265:        str += 6;
        !           266:        cls = RCLASS_TLSLDM;
        !           267:       }
        !           268:     else if (strncasecmp (str, "dtpoff", 6) == 0)
        !           269:       {
        !           270:        str += 6;
        !           271:        cls = RCLASS_DTPOFF;
        !           272:       }
        !           273:     else if (strncasecmp (str, "gottpoff", 8) == 0)
        !           274:       {
        !           275:        str += 8;
        !           276:        cls = RCLASS_GOTTPOFF;
        !           277:       }
        !           278:     else if (strncasecmp (str, "tpoff", 5) == 0)
        !           279:       {
        !           280:        str += 5;
        !           281:        cls = RCLASS_TPOFF;
        !           282:       }
1.1       christos  283:
1.7     ! christos  284:     if (strncasecmp (str, "hi(", 3) == 0)
        !           285:       {
        !           286:        str += 3;
        !           287:        typ = RTYPE_HI;
        !           288:       }
        !           289:     else if (strncasecmp (str, "lo(", 3) == 0)
        !           290:       {
        !           291:        str += 3;
        !           292:        typ = RTYPE_LO;
        !           293:       }
        !           294:     else if (strncasecmp (str, "ha(", 3) == 0)
        !           295:       {
        !           296:        str += 3;
        !           297:        typ = RTYPE_AHI;
        !           298:       }
        !           299:     else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
        !           300:       {
        !           301:        str += 3;
        !           302:        typ = RTYPE_PO;
        !           303:       }
        !           304:     else
        !           305:       return -1;
1.1       christos  306:
1.7     ! christos  307:     *strp = str;
        !           308:     return (cls << RCLASS_SHIFT) | typ;
        !           309: }
1.1       christos  310:
1.7     ! christos  311: static const char *
        !           312: parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
        !           313:             long *valuep, int splitp)
        !           314: {
        !           315:   const char *errmsg;
        !           316:   enum cgen_parse_operand_result result_type;
        !           317:   bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
        !           318:   enum or1k_rtype reloc_type;
        !           319:   int reloc_code;
        !           320:   bfd_vma ret;
1.1       christos  321:
1.7     ! christos  322:   if (**strp == '#')
        !           323:     ++*strp;
1.1       christos  324:
1.7     ! christos  325:   reloc_code = parse_reloc (strp);
        !           326:   reloc_type = reloc_code & RTYPE_MASK;
        !           327:   if (reloc_code >= 0)
        !           328:     {
        !           329:       enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
        !           330:       if (splitp)
        !           331:        {
        !           332:          if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
        !           333:              && reloc_class != RCLASS_GOT)
        !           334:            /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
        !           335:            reloc_type |= 1;
        !           336:          else
        !           337:            return INVALID_STORE_RELOC;
        !           338:        }
        !           339:       reloc = or1k_imm16_relocs[reloc_class][reloc_type];
1.1       christos  340:     }
1.7     ! christos  341:
        !           342:   if (reloc != BFD_RELOC_UNUSED)
1.1       christos  343:     {
                    344:       bfd_vma value;
                    345:
1.7     ! christos  346:       errmsg = cgen_parse_address (cd, strp, opindex, reloc,
1.1       christos  347:                                   &result_type, &value);
                    348:       if (**strp != ')')
1.7     ! christos  349:        errmsg = MISSING_CLOSING_PARENTHESIS;
1.1       christos  350:       ++*strp;
                    351:
1.7     ! christos  352:       ret = value;
1.1       christos  353:
1.7     ! christos  354:       if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
        !           355:        switch (reloc_type)
        !           356:          {
        !           357:          case RTYPE_AHI:
        !           358:            ret += 0x8000;
        !           359:            /* FALLTHRU */
        !           360:          case RTYPE_HI:
        !           361:            ret >>= 16;
        !           362:            /* FALLTHRU */
        !           363:          case RTYPE_LO:
        !           364:          case RTYPE_SLO:
        !           365:            ret &= 0xffff;
        !           366:            ret = (ret ^ 0x8000) - 0x8000;
        !           367:            break;
        !           368:          case RTYPE_PO:
        !           369:          case RTYPE_SPO:
        !           370:            ret &= 0x1fff;
        !           371:            break;
        !           372:          default:
        !           373:            errmsg = INVALID_RELOC_TYPE;
        !           374:          }
1.1       christos  375:     }
                    376:   else
                    377:     {
                    378:       long value;
                    379:       errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
                    380:       ret = value;
                    381:     }
                    382:
                    383:   if (errmsg == NULL)
                    384:     *valuep = ret;
                    385:
                    386:   return errmsg;
                    387: }
                    388:
                    389: static const char *
1.7     ! christos  390: parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
        !           391: {
        !           392:   return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
        !           393: }
        !           394:
        !           395: static const char *
        !           396: parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
        !           397:                    long *valuep)
1.1       christos  398: {
1.7     ! christos  399:   return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
        !           400: }
        !           401:
        !           402: static const char *
        !           403: parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
        !           404:              unsigned long *valuep)
        !           405: {
        !           406:   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
        !           407:   if (errmsg == NULL)
        !           408:     *valuep &= 0xffff;
        !           409:   return errmsg;
        !           410: }
1.1       christos  411:
1.7     ! christos  412: static const char *
        !           413: parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
        !           414:                    unsigned long *valuep)
        !           415: {
        !           416:   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
1.1       christos  417:   if (errmsg == NULL)
                    418:     *valuep &= 0xffff;
                    419:   return errmsg;
                    420: }
                    421:
1.7     ! christos  422: /* Parse register pairs with syntax rA,rB to a flag + rA value.  */
        !           423:
        !           424: static const char *
        !           425: parse_regpair (CGEN_CPU_DESC cd, const char **strp,
        !           426:               int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
        !           427: {
        !           428:   long reg1_index;
        !           429:   long reg2_index;
        !           430:   const char *errmsg;
        !           431:
        !           432:   /* The first part should just be a register.  */
        !           433:   errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
        !           434:                               &reg1_index);
        !           435:
        !           436:   /* If that worked skip the comma separator.  */
        !           437:   if (errmsg == NULL)
        !           438:     {
        !           439:       if (**strp == ',')
        !           440:        ++*strp;
        !           441:       else
        !           442:        errmsg = "Unexpected character, expected ','";
        !           443:     }
        !           444:
        !           445:   /* If that worked the next part is just another register.  */
        !           446:   if (errmsg == NULL)
        !           447:     errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
        !           448:                                 &reg2_index);
        !           449:
        !           450:   /* Validate the register pair is valid and create the output value.  */
        !           451:   if (errmsg == NULL)
        !           452:     {
        !           453:       int regoffset = reg2_index - reg1_index;
        !           454:
        !           455:       if (regoffset == 1 || regoffset == 2)
        !           456:        {
        !           457:          unsigned short offsetmask;
        !           458:          unsigned short value;
        !           459:
        !           460:          offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
        !           461:          value = offsetmask | reg1_index;
        !           462:
        !           463:          *valuep = value;
        !           464:        }
        !           465:       else
        !           466:        errmsg = "Invalid register pair, offset not 1 or 2.";
        !           467:     }
        !           468:
        !           469:   return errmsg;
        !           470: }
        !           471:
1.1       christos  472: /* -- */
                    473:
                    474: const char * or1k_cgen_parse_operand
                    475:   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
                    476:
                    477: /* Main entry point for operand parsing.
                    478:
                    479:    This function is basically just a big switch statement.  Earlier versions
                    480:    used tables to look up the function to use, but
                    481:    - if the table contains both assembler and disassembler functions then
                    482:      the disassembler contains much of the assembler and vice-versa,
                    483:    - there's a lot of inlining possibilities as things grow,
                    484:    - using a switch statement avoids the function call overhead.
                    485:
                    486:    This function could be moved into `parse_insn_normal', but keeping it
                    487:    separate makes clear the interface between `parse_insn_normal' and each of
                    488:    the handlers.  */
                    489:
                    490: const char *
                    491: or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
                    492:                           int opindex,
                    493:                           const char ** strp,
                    494:                           CGEN_FIELDS * fields)
                    495: {
                    496:   const char * errmsg = NULL;
                    497:   /* Used by scalar operands that still need to be parsed.  */
                    498:   long junk ATTRIBUTE_UNUSED;
                    499:
                    500:   switch (opindex)
                    501:     {
1.7     ! christos  502:     case OR1K_OPERAND_DISP21 :
        !           503:       {
        !           504:         bfd_vma value = 0;
        !           505:         errmsg = parse_disp21 (cd, strp, OR1K_OPERAND_DISP21, 0, NULL,  & value);
        !           506:         fields->f_disp21 = value;
        !           507:       }
        !           508:       break;
1.1       christos  509:     case OR1K_OPERAND_DISP26 :
                    510:       {
                    511:         bfd_vma value = 0;
                    512:         errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL,  & value);
                    513:         fields->f_disp26 = value;
                    514:       }
                    515:       break;
                    516:     case OR1K_OPERAND_RA :
                    517:       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
                    518:       break;
1.7     ! christos  519:     case OR1K_OPERAND_RAD32F :
        !           520:       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RAD32F, (unsigned long *) (& fields->f_rad32));
        !           521:       break;
1.1       christos  522:     case OR1K_OPERAND_RADF :
1.7     ! christos  523:       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r2);
        !           524:       break;
        !           525:     case OR1K_OPERAND_RADI :
        !           526:       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RADI, (unsigned long *) (& fields->f_rad32));
1.1       christos  527:       break;
                    528:     case OR1K_OPERAND_RASF :
                    529:       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
                    530:       break;
                    531:     case OR1K_OPERAND_RB :
                    532:       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
                    533:       break;
1.7     ! christos  534:     case OR1K_OPERAND_RBD32F :
        !           535:       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBD32F, (unsigned long *) (& fields->f_rbd32));
        !           536:       break;
1.1       christos  537:     case OR1K_OPERAND_RBDF :
1.7     ! christos  538:       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r3);
        !           539:       break;
        !           540:     case OR1K_OPERAND_RBDI :
        !           541:       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBDI, (unsigned long *) (& fields->f_rbd32));
1.1       christos  542:       break;
                    543:     case OR1K_OPERAND_RBSF :
                    544:       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
                    545:       break;
                    546:     case OR1K_OPERAND_RD :
                    547:       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
                    548:       break;
1.7     ! christos  549:     case OR1K_OPERAND_RDD32F :
        !           550:       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDD32F, (unsigned long *) (& fields->f_rdd32));
        !           551:       break;
1.1       christos  552:     case OR1K_OPERAND_RDDF :
                    553:       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
                    554:       break;
1.7     ! christos  555:     case OR1K_OPERAND_RDDI :
        !           556:       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDDI, (unsigned long *) (& fields->f_rdd32));
        !           557:       break;
1.1       christos  558:     case OR1K_OPERAND_RDSF :
                    559:       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
                    560:       break;
                    561:     case OR1K_OPERAND_SIMM16 :
                    562:       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
                    563:       break;
                    564:     case OR1K_OPERAND_SIMM16_SPLIT :
1.7     ! christos  565:       errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
1.1       christos  566:       break;
                    567:     case OR1K_OPERAND_UIMM16 :
                    568:       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
                    569:       break;
                    570:     case OR1K_OPERAND_UIMM16_SPLIT :
1.7     ! christos  571:       errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
1.1       christos  572:       break;
                    573:     case OR1K_OPERAND_UIMM6 :
                    574:       errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
                    575:       break;
                    576:
                    577:     default :
                    578:       /* xgettext:c-format */
1.6       christos  579:       opcodes_error_handler
                    580:        (_("internal error: unrecognized field %d while parsing"),
                    581:         opindex);
1.1       christos  582:       abort ();
                    583:   }
                    584:
                    585:   return errmsg;
                    586: }
                    587:
1.3       christos  588: cgen_parse_fn * const or1k_cgen_parse_handlers[] =
1.1       christos  589: {
                    590:   parse_insn_normal,
                    591: };
                    592:
                    593: void
                    594: or1k_cgen_init_asm (CGEN_CPU_DESC cd)
                    595: {
                    596:   or1k_cgen_init_opcode_table (cd);
                    597:   or1k_cgen_init_ibld_table (cd);
                    598:   cd->parse_handlers = & or1k_cgen_parse_handlers[0];
                    599:   cd->parse_operand = or1k_cgen_parse_operand;
                    600: #ifdef CGEN_ASM_INIT_HOOK
                    601: CGEN_ASM_INIT_HOOK
                    602: #endif
                    603: }
                    604:
                    605: 
                    606:
                    607: /* Regex construction routine.
                    608:
                    609:    This translates an opcode syntax string into a regex string,
                    610:    by replacing any non-character syntax element (such as an
                    611:    opcode) with the pattern '.*'
                    612:
                    613:    It then compiles the regex and stores it in the opcode, for
                    614:    later use by or1k_cgen_assemble_insn
                    615:
                    616:    Returns NULL for success, an error message for failure.  */
                    617:
1.3       christos  618: char *
1.1       christos  619: or1k_cgen_build_insn_regex (CGEN_INSN *insn)
1.3       christos  620: {
1.1       christos  621:   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
                    622:   const char *mnem = CGEN_INSN_MNEMONIC (insn);
                    623:   char rxbuf[CGEN_MAX_RX_ELEMENTS];
                    624:   char *rx = rxbuf;
                    625:   const CGEN_SYNTAX_CHAR_TYPE *syn;
                    626:   int reg_err;
                    627:
                    628:   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
                    629:
                    630:   /* Mnemonics come first in the syntax string.  */
                    631:   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
                    632:     return _("missing mnemonic in syntax string");
                    633:   ++syn;
                    634:
                    635:   /* Generate a case sensitive regular expression that emulates case
                    636:      insensitive matching in the "C" locale.  We cannot generate a case
                    637:      insensitive regular expression because in Turkish locales, 'i' and 'I'
                    638:      are not equal modulo case conversion.  */
                    639:
                    640:   /* Copy the literal mnemonic out of the insn.  */
                    641:   for (; *mnem; mnem++)
                    642:     {
                    643:       char c = *mnem;
                    644:
                    645:       if (ISALPHA (c))
                    646:        {
                    647:          *rx++ = '[';
                    648:          *rx++ = TOLOWER (c);
                    649:          *rx++ = TOUPPER (c);
                    650:          *rx++ = ']';
                    651:        }
                    652:       else
                    653:        *rx++ = c;
                    654:     }
                    655:
                    656:   /* Copy any remaining literals from the syntax string into the rx.  */
                    657:   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
                    658:     {
1.3       christos  659:       if (CGEN_SYNTAX_CHAR_P (* syn))
1.1       christos  660:        {
                    661:          char c = CGEN_SYNTAX_CHAR (* syn);
                    662:
1.3       christos  663:          switch (c)
1.1       christos  664:            {
                    665:              /* Escape any regex metacharacters in the syntax.  */
1.3       christos  666:            case '.': case '[': case '\\':
                    667:            case '*': case '^': case '$':
1.1       christos  668:
                    669: #ifdef CGEN_ESCAPE_EXTENDED_REGEX
1.3       christos  670:            case '?': case '{': case '}':
1.1       christos  671:            case '(': case ')': case '*':
                    672:            case '|': case '+': case ']':
                    673: #endif
                    674:              *rx++ = '\\';
                    675:              *rx++ = c;
                    676:              break;
                    677:
                    678:            default:
                    679:              if (ISALPHA (c))
                    680:                {
                    681:                  *rx++ = '[';
                    682:                  *rx++ = TOLOWER (c);
                    683:                  *rx++ = TOUPPER (c);
                    684:                  *rx++ = ']';
                    685:                }
                    686:              else
                    687:                *rx++ = c;
                    688:              break;
                    689:            }
                    690:        }
                    691:       else
                    692:        {
                    693:          /* Replace non-syntax fields with globs.  */
                    694:          *rx++ = '.';
                    695:          *rx++ = '*';
                    696:        }
                    697:     }
                    698:
                    699:   /* Trailing whitespace ok.  */
1.3       christos  700:   * rx++ = '[';
                    701:   * rx++ = ' ';
                    702:   * rx++ = '\t';
                    703:   * rx++ = ']';
                    704:   * rx++ = '*';
1.1       christos  705:
                    706:   /* But anchor it after that.  */
1.3       christos  707:   * rx++ = '$';
1.1       christos  708:   * rx = '\0';
                    709:
                    710:   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
                    711:   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
                    712:
1.3       christos  713:   if (reg_err == 0)
1.1       christos  714:     return NULL;
                    715:   else
                    716:     {
                    717:       static char msg[80];
                    718:
                    719:       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
                    720:       regfree ((regex_t *) CGEN_INSN_RX (insn));
                    721:       free (CGEN_INSN_RX (insn));
                    722:       (CGEN_INSN_RX (insn)) = NULL;
                    723:       return msg;
                    724:     }
                    725: }
                    726:
                    727: 
                    728: /* Default insn parser.
                    729:
                    730:    The syntax string is scanned and operands are parsed and stored in FIELDS.
                    731:    Relocs are queued as we go via other callbacks.
                    732:
                    733:    ??? Note that this is currently an all-or-nothing parser.  If we fail to
                    734:    parse the instruction, we return 0 and the caller will start over from
                    735:    the beginning.  Backtracking will be necessary in parsing subexpressions,
                    736:    but that can be handled there.  Not handling backtracking here may get
                    737:    expensive in the case of the m68k.  Deal with later.
                    738:
                    739:    Returns NULL for success, an error message for failure.  */
                    740:
                    741: static const char *
                    742: parse_insn_normal (CGEN_CPU_DESC cd,
                    743:                   const CGEN_INSN *insn,
                    744:                   const char **strp,
                    745:                   CGEN_FIELDS *fields)
                    746: {
                    747:   /* ??? Runtime added insns not handled yet.  */
                    748:   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
                    749:   const char *str = *strp;
                    750:   const char *errmsg;
                    751:   const char *p;
                    752:   const CGEN_SYNTAX_CHAR_TYPE * syn;
                    753: #ifdef CGEN_MNEMONIC_OPERANDS
                    754:   /* FIXME: wip */
                    755:   int past_opcode_p;
                    756: #endif
                    757:
                    758:   /* For now we assume the mnemonic is first (there are no leading operands).
                    759:      We can parse it without needing to set up operand parsing.
                    760:      GAS's input scrubber will ensure mnemonics are lowercase, but we may
                    761:      not be called from GAS.  */
                    762:   p = CGEN_INSN_MNEMONIC (insn);
                    763:   while (*p && TOLOWER (*p) == TOLOWER (*str))
                    764:     ++p, ++str;
                    765:
                    766:   if (* p)
                    767:     return _("unrecognized instruction");
                    768:
                    769: #ifndef CGEN_MNEMONIC_OPERANDS
                    770:   if (* str && ! ISSPACE (* str))
                    771:     return _("unrecognized instruction");
                    772: #endif
                    773:
                    774:   CGEN_INIT_PARSE (cd);
                    775:   cgen_init_parse_operand (cd);
                    776: #ifdef CGEN_MNEMONIC_OPERANDS
                    777:   past_opcode_p = 0;
                    778: #endif
                    779:
                    780:   /* We don't check for (*str != '\0') here because we want to parse
                    781:      any trailing fake arguments in the syntax string.  */
                    782:   syn = CGEN_SYNTAX_STRING (syntax);
                    783:
                    784:   /* Mnemonics come first for now, ensure valid string.  */
                    785:   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
                    786:     abort ();
                    787:
                    788:   ++syn;
                    789:
                    790:   while (* syn != 0)
                    791:     {
                    792:       /* Non operand chars must match exactly.  */
                    793:       if (CGEN_SYNTAX_CHAR_P (* syn))
                    794:        {
                    795:          /* FIXME: While we allow for non-GAS callers above, we assume the
                    796:             first char after the mnemonic part is a space.  */
                    797:          /* FIXME: We also take inappropriate advantage of the fact that
                    798:             GAS's input scrubber will remove extraneous blanks.  */
                    799:          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
                    800:            {
                    801: #ifdef CGEN_MNEMONIC_OPERANDS
                    802:              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
                    803:                past_opcode_p = 1;
                    804: #endif
                    805:              ++ syn;
                    806:              ++ str;
                    807:            }
                    808:          else if (*str)
                    809:            {
                    810:              /* Syntax char didn't match.  Can't be this insn.  */
                    811:              static char msg [80];
                    812:
                    813:              /* xgettext:c-format */
                    814:              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
                    815:                       CGEN_SYNTAX_CHAR(*syn), *str);
                    816:              return msg;
                    817:            }
                    818:          else
                    819:            {
                    820:              /* Ran out of input.  */
                    821:              static char msg [80];
                    822:
                    823:              /* xgettext:c-format */
                    824:              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
                    825:                       CGEN_SYNTAX_CHAR(*syn));
                    826:              return msg;
                    827:            }
                    828:          continue;
                    829:        }
                    830:
                    831: #ifdef CGEN_MNEMONIC_OPERANDS
                    832:       (void) past_opcode_p;
                    833: #endif
                    834:       /* We have an operand of some sort.  */
                    835:       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
                    836:       if (errmsg)
                    837:        return errmsg;
                    838:
                    839:       /* Done with this operand, continue with next one.  */
                    840:       ++ syn;
                    841:     }
                    842:
                    843:   /* If we're at the end of the syntax string, we're done.  */
                    844:   if (* syn == 0)
                    845:     {
                    846:       /* FIXME: For the moment we assume a valid `str' can only contain
                    847:         blanks now.  IE: We needn't try again with a longer version of
                    848:         the insn and it is assumed that longer versions of insns appear
                    849:         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
                    850:       while (ISSPACE (* str))
                    851:        ++ str;
                    852:
                    853:       if (* str != '\0')
                    854:        return _("junk at end of line"); /* FIXME: would like to include `str' */
                    855:
                    856:       return NULL;
                    857:     }
                    858:
                    859:   /* We couldn't parse it.  */
                    860:   return _("unrecognized instruction");
                    861: }
                    862: 
                    863: /* Main entry point.
                    864:    This routine is called for each instruction to be assembled.
                    865:    STR points to the insn to be assembled.
                    866:    We assume all necessary tables have been initialized.
                    867:    The assembled instruction, less any fixups, is stored in BUF.
                    868:    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
                    869:    still needs to be converted to target byte order, otherwise BUF is an array
                    870:    of bytes in target byte order.
                    871:    The result is a pointer to the insn's entry in the opcode table,
                    872:    or NULL if an error occured (an error message will have already been
                    873:    printed).
                    874:
                    875:    Note that when processing (non-alias) macro-insns,
                    876:    this function recurses.
                    877:
                    878:    ??? It's possible to make this cpu-independent.
                    879:    One would have to deal with a few minor things.
                    880:    At this point in time doing so would be more of a curiosity than useful
                    881:    [for example this file isn't _that_ big], but keeping the possibility in
                    882:    mind helps keep the design clean.  */
                    883:
                    884: const CGEN_INSN *
                    885: or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
                    886:                           const char *str,
                    887:                           CGEN_FIELDS *fields,
                    888:                           CGEN_INSN_BYTES_PTR buf,
                    889:                           char **errmsg)
                    890: {
                    891:   const char *start;
                    892:   CGEN_INSN_LIST *ilist;
                    893:   const char *parse_errmsg = NULL;
                    894:   const char *insert_errmsg = NULL;
                    895:   int recognized_mnemonic = 0;
                    896:
                    897:   /* Skip leading white space.  */
                    898:   while (ISSPACE (* str))
                    899:     ++ str;
                    900:
                    901:   /* The instructions are stored in hashed lists.
                    902:      Get the first in the list.  */
                    903:   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
                    904:
                    905:   /* Keep looking until we find a match.  */
                    906:   start = str;
                    907:   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
                    908:     {
                    909:       const CGEN_INSN *insn = ilist->insn;
                    910:       recognized_mnemonic = 1;
                    911:
1.3       christos  912: #ifdef CGEN_VALIDATE_INSN_SUPPORTED
1.1       christos  913:       /* Not usually needed as unsupported opcodes
                    914:         shouldn't be in the hash lists.  */
                    915:       /* Is this insn supported by the selected cpu?  */
                    916:       if (! or1k_cgen_insn_supported (cd, insn))
                    917:        continue;
                    918: #endif
                    919:       /* If the RELAXED attribute is set, this is an insn that shouldn't be
                    920:         chosen immediately.  Instead, it is used during assembler/linker
                    921:         relaxation if possible.  */
                    922:       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
                    923:        continue;
                    924:
                    925:       str = start;
                    926:
                    927:       /* Skip this insn if str doesn't look right lexically.  */
                    928:       if (CGEN_INSN_RX (insn) != NULL &&
                    929:          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
                    930:        continue;
                    931:
                    932:       /* Allow parse/insert handlers to obtain length of insn.  */
                    933:       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
                    934:
                    935:       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
                    936:       if (parse_errmsg != NULL)
                    937:        continue;
                    938:
                    939:       /* ??? 0 is passed for `pc'.  */
                    940:       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
                    941:                                                 (bfd_vma) 0);
                    942:       if (insert_errmsg != NULL)
                    943:         continue;
                    944:
                    945:       /* It is up to the caller to actually output the insn and any
                    946:          queued relocs.  */
                    947:       return insn;
                    948:     }
                    949:
                    950:   {
                    951:     static char errbuf[150];
                    952:     const char *tmp_errmsg;
                    953: #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
                    954: #define be_verbose 1
                    955: #else
                    956: #define be_verbose 0
                    957: #endif
                    958:
                    959:     if (be_verbose)
                    960:       {
                    961:        /* If requesting verbose error messages, use insert_errmsg.
                    962:           Failing that, use parse_errmsg.  */
                    963:        tmp_errmsg = (insert_errmsg ? insert_errmsg :
                    964:                      parse_errmsg ? parse_errmsg :
                    965:                      recognized_mnemonic ?
                    966:                      _("unrecognized form of instruction") :
                    967:                      _("unrecognized instruction"));
                    968:
                    969:        if (strlen (start) > 50)
                    970:          /* xgettext:c-format */
                    971:          sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1.3       christos  972:        else
1.1       christos  973:          /* xgettext:c-format */
                    974:          sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
                    975:       }
                    976:     else
                    977:       {
                    978:        if (strlen (start) > 50)
                    979:          /* xgettext:c-format */
                    980:          sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1.3       christos  981:        else
1.1       christos  982:          /* xgettext:c-format */
                    983:          sprintf (errbuf, _("bad instruction `%.50s'"), start);
                    984:       }
1.3       christos  985:
1.1       christos  986:     *errmsg = errbuf;
                    987:     return NULL;
                    988:   }
                    989: }

CVSweb <webmaster@jp.NetBSD.org>