Annotation of GNUtools/cctools/as/m88k.c, revision 1.1

1.1     ! root        1: /* m88k.c -- Assemble for the 88100
        !             2:    Copyright (C) 1989 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is not yet part of GAS, the GNU Assembler.
        !             5: 
        !             6: GAS is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 1, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GAS is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GAS; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: #include <ctype.h>
        !            21: #include <string.h>
        !            22: #include <mach-o/m88k/reloc.h>
        !            23: #include "m88k-opcode.h"
        !            24: #include "as.h"
        !            25: #include "flonum.h"
        !            26: #include "expr.h"
        !            27: #include "hash.h"
        !            28: #include "frags.h"
        !            29: #include "fixes.h"
        !            30: #include "read.h"
        !            31: #include "md.h"
        !            32: #include "obstack.h"
        !            33: #include "symbols.h"
        !            34: #include "messages.h"
        !            35: #include "input-scrub.h"
        !            36: #include "sections.h"
        !            37: 
        !            38: /*
        !            39:  * These are the default cputype and cpusubtype for the m88k architecture.
        !            40:  */
        !            41: const cpu_type_t md_cputype = CPU_TYPE_MC88000;
        !            42: cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_MC88000_ALL;
        !            43: 
        !            44: /* This is the byte sex for the m88k architecture */
        !            45: const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX;
        !            46: 
        !            47: #ifdef NeXT
        !            48: static long in_delay_slot = 0;
        !            49: #endif
        !            50: 
        !            51: static char *cmpslot[] = { "**", "**", "eq", "ne", "gt", "le", "lt", "ge",
        !            52:                           "hi", "ls", "lo", "hs",
        !            53: #ifdef m88110
        !            54:                           "be", "nb", "he", "nh",
        !            55: #endif m88110
        !            56:                            NULL };
        !            57: 
        !            58: static struct {
        !            59:        char *name;
        !            60:        unsigned int num;
        !            61: 
        !            62: } cndmsk[] = {
        !            63:                "eq0", 0x02,
        !            64:                "ne0", 0x0d,
        !            65:                "gt0", 0x01,
        !            66:                "lt0", 0x0c,
        !            67:                "ge0", 0x03,
        !            68:                "le0", 0x0e,
        !            69:                NULL,  0x00,
        !            70:              };
        !            71: 
        !            72: struct m88k_insn {
        !            73:         unsigned long opcode;
        !            74:         expressionS exp;
        !            75: #ifdef NeXT
        !            76:         enum reloc_type_m88k reloc;
        !            77: #else
        !            78:         enum reloc_type reloc;
        !            79: #endif
        !            80: };
        !            81: 
        !            82: static struct hash_control *op_hash = NULL;
        !            83: 
        !            84: /* These chars start a comment anywhere in a source file (except inside
        !            85:    another comment */
        !            86: const char md_comment_chars[] = ";";
        !            87: 
        !            88: /* These chars only start a comment at the beginning of a line. */
        !            89: const char md_line_comment_chars[] = "#";
        !            90: 
        !            91: /* Chars that can be used to separate mant from exp in floating point nums */
        !            92: const char md_EXP_CHARS[] = "eE";
        !            93: 
        !            94: /* Chars that mean this number is a floating point constant */
        !            95: /* as in 0f123.456 */
        !            96: /* or    0H1.234E-12 (see exp chars above) */
        !            97: const char md_FLT_CHARS[] = "dDfF";
        !            98: 
        !            99: static int calcop(
        !           100:     struct m88k_opcode *format,
        !           101:     char *param,
        !           102:     struct m88k_insn *insn);
        !           103: static char * parse_reg(
        !           104:     char *param,
        !           105:     struct m88k_insn *insn,
        !           106:     struct m88k_opcode *format,
        !           107:     int parcnt);
        !           108: #ifdef m88110
        !           109: static char *parse_ereg(
        !           110:     char *param,
        !           111:     struct m88k_insn *insn,
        !           112:     struct m88k_opcode *format,
        !           113:     int parcnt);
        !           114: static char *parse_e4rot(
        !           115:     char *param,
        !           116:     struct m88k_insn *insn,
        !           117:     struct m88k_opcode *format,
        !           118:     int parcnt);
        !           119: static char *parse_xreg(
        !           120:     char *param,
        !           121:     struct m88k_insn *insn,
        !           122:     struct m88k_opcode *format,
        !           123:     int parcnt);
        !           124: #endif m88110
        !           125: static char *parse_pcr(
        !           126:     char *param,
        !           127:     struct m88k_insn *insn,
        !           128:     struct m88k_opcode *format,
        !           129:     int parcnt);
        !           130: static char *parse_cmp(
        !           131:     char *param,
        !           132:     struct m88k_insn *insn,
        !           133:     struct m88k_opcode *format,
        !           134:     int parcnt);
        !           135: static char *parse_cnd(
        !           136:     char *param,
        !           137:     struct m88k_insn *insn,
        !           138:     struct m88k_opcode *format,
        !           139:     int parcnt);
        !           140: static char *parse_bf(
        !           141:     char *param,
        !           142:     struct m88k_insn *insn,
        !           143:     struct m88k_opcode *format,
        !           144:     int parcnt);
        !           145: static char *parse_rot(
        !           146:     char *param,
        !           147:     struct m88k_insn *insn,
        !           148:     struct m88k_opcode *format,
        !           149:     int parcnt);
        !           150: static char *parse_rsc(
        !           151:     char *param,
        !           152:     struct m88k_insn *insn,
        !           153:     struct m88k_opcode *format,
        !           154:     int parcnt);
        !           155: static char *parse_cr(
        !           156:     char *param,
        !           157:     struct m88k_insn *insn,
        !           158:     struct m88k_opcode *format,
        !           159:     int parcnt);
        !           160: static char *parse_fcr(
        !           161:     char *param,
        !           162:     struct m88k_insn *insn,
        !           163:     struct m88k_opcode *format,
        !           164:     int parcnt);
        !           165: static char *parse_cst(
        !           166:     char *param,
        !           167:     struct m88k_insn *insn,
        !           168:     struct m88k_opcode *format,
        !           169:     int parcnt);
        !           170: static char *getval(
        !           171:     char *param,
        !           172:     unsigned int *val);
        !           173: #ifdef NeXT
        !           174: static void s_reg(
        !           175:     int reg);
        !           176: static void s_scaled(
        !           177:     int value);
        !           178: static void s_m88k_abs(
        !           179:     int value);
        !           180: static void s_no_delay(
        !           181:     int value);
        !           182: static void s_dot(
        !           183:     int value);
        !           184: #endif /* NeXT */
        !           185: 
        !           186: const pseudo_typeS md_pseudo_table[] =
        !           187: {
        !           188: #ifdef NeXT
        !           189:        {"greg", s_reg, 'r' },
        !           190:        {"xreg", s_reg, 'x' },
        !           191:        {"scaled", s_scaled, 0},
        !           192:        {"abs", s_m88k_abs, 0},
        !           193:        {"no_delay", s_no_delay, 0},
        !           194:        {"dot", s_dot, 0},
        !           195: #endif
        !           196: #ifndef NeXT
        !           197:        /* At NeXT we don't allow these */
        !           198:        {"dfloat", float_cons, 'd'},
        !           199:        {"ffloat", float_cons, 'f'},
        !           200:        {"global", s_globl, 0},
        !           201:        {"half", cons, 2 },
        !           202:        {"ln", s_line, 0},
        !           203:        {"zero", s_space, 0},
        !           204:        {"word", cons, 4 },
        !           205: #endif
        !           206:        {0}
        !           207: };
        !           208: 
        !           209: #ifdef NeXT
        !           210: static
        !           211: void
        !           212: s_dot(
        !           213: int value)
        !           214: {
        !           215:        char *name, *end_name, delim;
        !           216:        symbolS *symbolP;
        !           217: 
        !           218:        if( * input_line_pointer == '"')
        !           219:          name = input_line_pointer + 1;
        !           220:        else
        !           221:          name = input_line_pointer;
        !           222:        delim = get_symbol_end();
        !           223:        end_name = input_line_pointer;
        !           224:        *end_name = 0;
        !           225: 
        !           226:        symbolP = symbol_find_or_make (name);
        !           227:        symbolP -> sy_type = N_ABS;
        !           228:        symbolP -> sy_other = 0; /* NO_SECT */
        !           229:        symbolP -> sy_value = obstack_next_free(&frags) - frag_now->fr_literal;
        !           230:        symbolP -> sy_frag = &zero_address_frag;
        !           231: 
        !           232:        *end_name = delim;
        !           233:        totally_ignore_line();
        !           234: }
        !           235: /*
        !           236:  * s_reg() is used to implement ".greg symbol,exp" and ".xreg symbol,exp"
        !           237:  * which set symbol to 1 or 0 depending on if the expression is a general
        !           238:  * register or extended register respectfully.  These are intended for use in
        !           239:  * macros.
        !           240:  */
        !           241: static
        !           242: void
        !           243: s_reg(
        !           244: int reg)
        !           245: {
        !           246:        char *name, *end_name, delim;
        !           247:        symbolS *symbolP;
        !           248:        unsigned long n_value, val;
        !           249: 
        !           250:        if( * input_line_pointer == '"')
        !           251:          name = input_line_pointer + 1;
        !           252:        else
        !           253:          name = input_line_pointer;
        !           254:        delim = get_symbol_end();
        !           255:        end_name = input_line_pointer;
        !           256:        *end_name = delim;
        !           257:        SKIP_WHITESPACE();
        !           258:        if ( * input_line_pointer != ',' ) {
        !           259:                *end_name = 0;
        !           260:                as_warn("Expected comma after name \"%s\"", name);
        !           261:                *end_name = delim;
        !           262:                ignore_rest_of_line();
        !           263:                return;
        !           264:        }
        !           265:        input_line_pointer ++;
        !           266:        *end_name = 0;
        !           267: 
        !           268:        SKIP_WHITESPACE();
        !           269:        n_value = 0;
        !           270:        if (*input_line_pointer == reg || *input_line_pointer == toupper(reg)){
        !           271:            input_line_pointer++;
        !           272:            if(isdigit(*input_line_pointer)){
        !           273:                val = 0;
        !           274:                while (isdigit(*input_line_pointer)){
        !           275:                    if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
        !           276:                        break;
        !           277:                }
        !           278:                SKIP_WHITESPACE();
        !           279:                if(val <= 31 &&
        !           280:                   (*input_line_pointer == '\n' || *input_line_pointer == '@'))
        !           281:                    n_value = 1;
        !           282:            }
        !           283:        }
        !           284: 
        !           285:        symbolP = symbol_find_or_make (name);
        !           286:        symbolP -> sy_type = N_ABS;
        !           287:        symbolP -> sy_other = 0; /* NO_SECT */
        !           288:        symbolP -> sy_value = n_value;
        !           289:        symbolP -> sy_frag = &zero_address_frag;
        !           290: 
        !           291:        *end_name = delim;
        !           292:        totally_ignore_line();
        !           293: }
        !           294: 
        !           295: /*
        !           296:  * s_scaled() is used to implement ".scaled symbol,exp" which sets symbol to 1
        !           297:  * or 0 depending on if the expression is a scaled general register expression
        !           298:  * "r1[r2]" or not respectfully.  This is intended for use in macros.
        !           299:  */
        !           300: static
        !           301: void
        !           302: s_scaled(
        !           303: int value)
        !           304: {
        !           305:        char *name, *end_name, delim;
        !           306:        symbolS *symbolP;
        !           307:        unsigned long n_value, val;
        !           308: 
        !           309:        if( * input_line_pointer == '"')
        !           310:          name = input_line_pointer + 1;
        !           311:        else
        !           312:          name = input_line_pointer;
        !           313:        delim = get_symbol_end();
        !           314:        end_name = input_line_pointer;
        !           315:        *end_name = delim;
        !           316:        SKIP_WHITESPACE();
        !           317:        if ( * input_line_pointer != ',' ) {
        !           318:                *end_name = 0;
        !           319:                as_warn("Expected comma after name \"%s\"", name);
        !           320:                *end_name = delim;
        !           321:                ignore_rest_of_line();
        !           322:                return;
        !           323:        }
        !           324:        input_line_pointer ++;
        !           325:        *end_name = 0;
        !           326: 
        !           327:        SKIP_WHITESPACE();
        !           328:        n_value = 0;
        !           329:        if (*input_line_pointer == 'r' || *input_line_pointer == 'R'){
        !           330:            input_line_pointer++;
        !           331:            if(isdigit(*input_line_pointer)){
        !           332:                val = 0;
        !           333:                while (isdigit(*input_line_pointer)){
        !           334:                    if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
        !           335:                        break;
        !           336:                }
        !           337:                SKIP_WHITESPACE();
        !           338:                if(val <= 31 && *input_line_pointer == '['){
        !           339:                    input_line_pointer++;
        !           340:                    if (*input_line_pointer == 'r' ||
        !           341:                        *input_line_pointer == 'R'){
        !           342:                        input_line_pointer++;
        !           343:                        if(isdigit(*input_line_pointer)){
        !           344:                            val = 0;
        !           345:                            while (isdigit(*input_line_pointer)){
        !           346:                                if ((val = val * 10 +
        !           347:                                           *input_line_pointer++ - '0') > 31)
        !           348:                                    break;
        !           349:                            }
        !           350:                            if(val <= 31 && *input_line_pointer == ']'){
        !           351:                                input_line_pointer++;
        !           352:                                SKIP_WHITESPACE();
        !           353:                                if(*input_line_pointer == '\n' ||
        !           354:                                   *input_line_pointer == '@')
        !           355:                                    n_value = 1;
        !           356:                            }
        !           357:                        }
        !           358:                    }
        !           359:                }
        !           360:            }
        !           361:        }
        !           362: 
        !           363:        symbolP = symbol_find_or_make (name);
        !           364:        symbolP -> sy_type = N_ABS;
        !           365:        symbolP -> sy_other = 0; /* NO_SECT */
        !           366:        symbolP -> sy_value = n_value;
        !           367:        symbolP -> sy_frag = & zero_address_frag;
        !           368: 
        !           369:        *end_name = delim;
        !           370:        totally_ignore_line();
        !           371: }
        !           372: 
        !           373: /*
        !           374:  * s_m88k_abs() is used to implement ".abs symbol,exp" which sets symbol to 1
        !           375:  * or 0 depending on if the expression is an absolute expression or not
        !           376:  * respectfully.  This is intended for use in macros.
        !           377:  */
        !           378: static
        !           379: void
        !           380: s_m88k_abs(
        !           381: int value)
        !           382: {
        !           383:        char *name, *end_name, delim, *start;
        !           384:        symbolS *symbolP;
        !           385:        unsigned long n_value, val, is_reg_exp;
        !           386: 
        !           387:        start = input_line_pointer;
        !           388:        if( * input_line_pointer == '"')
        !           389:          name = input_line_pointer + 1;
        !           390:        else
        !           391:          name = input_line_pointer;
        !           392:        delim = get_symbol_end();
        !           393:        end_name = input_line_pointer;
        !           394:        *end_name = delim;
        !           395:        SKIP_WHITESPACE();
        !           396:        if ( * input_line_pointer != ',' ) {
        !           397:                *end_name = 0;
        !           398:                as_warn("Expected comma after name \"%s\"", name);
        !           399:                *end_name = delim;
        !           400:                ignore_rest_of_line();
        !           401:                return;
        !           402:        }
        !           403:        input_line_pointer ++;
        !           404:        *end_name = 0;
        !           405: 
        !           406:        SKIP_WHITESPACE();
        !           407:        is_reg_exp = 0;
        !           408:        n_value = 0;
        !           409:        if(*input_line_pointer == 'r' || *input_line_pointer == 'R'){
        !           410:            input_line_pointer++;
        !           411:            if(isdigit(*input_line_pointer)){
        !           412:                val = 0;
        !           413:                while (isdigit(*input_line_pointer)){
        !           414:                    if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
        !           415:                        break;
        !           416:                }
        !           417:                SKIP_WHITESPACE();
        !           418:                if(val <= 31)
        !           419:                    is_reg_exp = 1;
        !           420:            }
        !           421:        }
        !           422:        if(is_reg_exp == 0){
        !           423:            *end_name = delim;
        !           424:            input_line_pointer = start;
        !           425:            s_abs(value);
        !           426:            return;
        !           427:        }
        !           428: 
        !           429:        symbolP = symbol_find_or_make (name);
        !           430:        symbolP -> sy_type = N_ABS;
        !           431:        symbolP -> sy_other = 0; /* NO_SECT */
        !           432:        symbolP -> sy_value = n_value;
        !           433:        symbolP -> sy_frag = & zero_address_frag;
        !           434:        *end_name = delim;
        !           435: 
        !           436:        totally_ignore_line();
        !           437: }
        !           438: 
        !           439: /*
        !           440:  * s_no_delay() is used to implement ".no_delay string" which will abort and
        !           441:  * print the string if the last instruction assembled has a delay slot.
        !           442:  * This is intended for use in macros that expand to more than one instruction
        !           443:  * that could be put in delay slots.  This is not really correct in it's
        !           444:  * operation in that it is not per-section and does not take into account
        !           445:  * anything other than assembled instructions.
        !           446:  */
        !           447: static
        !           448: void
        !           449: s_no_delay(
        !           450: int value)
        !           451: {
        !           452:        char *p, c;
        !           453: 
        !           454:        p = input_line_pointer;
        !           455:        while(*p != '\n' && *p != '@' && *p != '\0')
        !           456:            p++;
        !           457:        c = *p;
        !           458:        *p = '\0';
        !           459:        
        !           460:        if(in_delay_slot)
        !           461:            as_fatal("delay slot abort %s detected.  Assembly stopping.",
        !           462:                     input_line_pointer);
        !           463:        input_line_pointer = p;
        !           464:        *p = c;
        !           465: }
        !           466: #endif /* NeXT */
        !           467: 
        !           468: void
        !           469: md_begin(
        !           470: void)
        !           471: {
        !           472:        register char *retval = NULL;
        !           473:        register unsigned int i = 0;
        !           474: 
        !           475:        /* initialize hash table */
        !           476: 
        !           477:        op_hash = hash_new();
        !           478:        if (op_hash == NULL)
        !           479:                as_fatal("Could not initialize hash table");
        !           480: 
        !           481:        /* loop until you see the end of the list */
        !           482: 
        !           483:        while (*m88k_opcodes[i].name) {
        !           484:                char *name = m88k_opcodes[i].name;
        !           485: 
        !           486:                /* hash each mnemonic and record its position */
        !           487: 
        !           488:                retval = hash_insert(op_hash, name, (char *)&m88k_opcodes[i]);
        !           489: 
        !           490:                if (retval != NULL && *retval != '\0')
        !           491:                        as_fatal("Can't hash instruction '%s':%s",
        !           492:                                        m88k_opcodes[i].name, retval);
        !           493: 
        !           494:                /* skip to next unique mnemonic or end of list */
        !           495: 
        !           496:                for (i++; !strcmp(m88k_opcodes[i].name, name); i++);
        !           497:        }
        !           498: }
        !           499: 
        !           500: int
        !           501: md_parse_option(
        !           502: char **argP,
        !           503: int *cntP,
        !           504: char ***vecP)
        !           505: {
        !           506:        return (1);
        !           507: }
        !           508: 
        !           509: void
        !           510: md_assemble(
        !           511: char *op)
        !           512: {
        !           513:        char *param, *thisfrag;
        !           514:        struct m88k_opcode *format;
        !           515:        struct m88k_insn insn;
        !           516: #ifdef NeXT
        !           517:        long pcrel_reloc;
        !           518: #endif
        !           519: 
        !           520:        assert(op);
        !           521: 
        !           522:        /* skip over instruction to find parameters */
        !           523: 
        !           524:        /* *param != '\0' is need for instructions that have no parameters
        !           525:           like rte */
        !           526:        for (param = op; !isspace(*param) && *param != '\0' ; param++);
        !           527:        *param++ = '\0';
        !           528: 
        !           529:        /* try to find the instruction in the hash table */
        !           530: 
        !           531:        if ((format = (struct m88k_opcode *) hash_find(op_hash, op)) == NULL) {
        !           532:                as_warn("Invalid mnemonic '%s'", op);
        !           533:                return;
        !           534:        }
        !           535: 
        !           536:        /* try parsing this instruction into insn */
        !           537: 
        !           538:        while (!calcop(format,param,&insn))
        !           539: 
        !           540:                /* if it doesn't parse try the next instruction */
        !           541: 
        !           542:                if (!strcmp(format->name, format[1].name))
        !           543:                        format++;
        !           544:                else {
        !           545:                        as_warn("Parameter syntax error");
        !           546:                        return;
        !           547:                }
        !           548: 
        !           549:        /* grow the current frag and plop in the opcode */
        !           550: 
        !           551:        thisfrag = frag_more(4);
        !           552:        md_number_to_chars(thisfrag, insn.opcode, 4);
        !           553: #ifdef NeXT
        !           554:        in_delay_slot = format->delay_slot;
        !           555: #endif
        !           556: #ifdef NeXT    /* generate stabs for debugging assembly code */
        !           557:        /*
        !           558:         * If the -g flag is present generate a line number stab for the
        !           559:         * instruction.
        !           560:         * 
        !           561:         * See the detailed comments about stabs in read_a_source_file() for a
        !           562:         * description of what is going on here.
        !           563:         */
        !           564:        if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){
        !           565:            (void)symbol_new(
        !           566:                  "",
        !           567:                  68 /* N_SLINE */,
        !           568:                  text_nsect,
        !           569:                  logical_input_line /* n_desc, line number */,
        !           570:                  obstack_next_free(&frags) - frag_now->fr_literal,
        !           571:                  frag_now);
        !           572:        }
        !           573: #endif /* NeXT */
        !           574: 
        !           575: #ifdef NeXT
        !           576:        pcrel_reloc = 0;
        !           577:        if (insn.reloc == M88K_RELOC_PC16 || insn.reloc == M88K_RELOC_PC26){
        !           578:            /*
        !           579:             * The NeXT linker has the ability to scatter blocks of
        !           580:             * sections between labels.  This requires that brances to
        !           581:             * labels that survive to the link phase must be able to
        !           582:             * be relocated.
        !           583:             */
        !           584:            if(insn.exp.X_add_symbol != NULL &&
        !           585:               (insn.exp.X_add_symbol->sy_name[0] != 'L' || flagseen ['L']))
        !           586:                pcrel_reloc = 1;
        !           587:            else
        !           588:                pcrel_reloc = 0;
        !           589:        }
        !           590: #endif /* NeXT */
        !           591: 
        !           592:        /* if this instruction requires labels mark it for later */
        !           593:        switch (insn.reloc) {
        !           594: 
        !           595:                case NO_RELOC:
        !           596:                                break;
        !           597: 
        !           598:                case M88K_RELOC_LO16:
        !           599:                case M88K_RELOC_HI16:
        !           600:                                fix_new(
        !           601:                                        frag_now,
        !           602: #ifdef NeXT
        !           603:                                        thisfrag - frag_now->fr_literal,
        !           604:                                        4,
        !           605: #else
        !           606:                                        thisfrag - frag_now->fr_literal + 2,
        !           607:                                        2,
        !           608: #endif
        !           609:                                        insn.exp.X_add_symbol,
        !           610:                                        insn.exp.X_subtract_symbol,
        !           611:                                        insn.exp.X_add_number,
        !           612:                                        0, 0,
        !           613:                                        insn.reloc
        !           614:                                );
        !           615:                                break;
        !           616: 
        !           617: #ifndef NeXT
        !           618:                case M88K_RELOC_IW16:
        !           619:                                fix_new(
        !           620:                                        frag_now,
        !           621:                                        thisfrag - frag_now->fr_literal,
        !           622:                                        4,
        !           623:                                        insn.exp.X_add_symbol,
        !           624:                                        insn.exp.X_subtract_symbol,
        !           625:                                        insn.exp.X_add_number,
        !           626:                                        0, 0,
        !           627:                                        insn.reloc
        !           628:                                );
        !           629:                                break;
        !           630: #endif /* !defined(NeXT) */
        !           631: 
        !           632:                case M88K_RELOC_PC16:
        !           633:                                fix_new(
        !           634:                                        frag_now,
        !           635: #ifdef NeXT
        !           636:                                        thisfrag - frag_now->fr_literal,
        !           637:                                        4,
        !           638: #else
        !           639:                                        thisfrag - frag_now->fr_literal + 2,
        !           640:                                        2,
        !           641: #endif
        !           642:                                        insn.exp.X_add_symbol,
        !           643:                                        insn.exp.X_subtract_symbol,
        !           644:                                        insn.exp.X_add_number,
        !           645:                                        1, pcrel_reloc,
        !           646:                                        insn.reloc
        !           647:                                );
        !           648:                                break;
        !           649: 
        !           650:                case M88K_RELOC_PC26:
        !           651:                                fix_new(
        !           652:                                        frag_now,
        !           653:                                        thisfrag - frag_now->fr_literal,
        !           654:                                        4,
        !           655:                                        insn.exp.X_add_symbol,
        !           656:                                        insn.exp.X_subtract_symbol,
        !           657:                                        insn.exp.X_add_number,
        !           658:                                        1, pcrel_reloc,
        !           659:                                        insn.reloc
        !           660:                                );
        !           661:                                break;
        !           662: 
        !           663:                default:
        !           664:                                as_warn("Unknown relocation type");
        !           665:                                break;
        !           666:        }
        !           667: }
        !           668: 
        !           669: static
        !           670: int
        !           671: calcop(
        !           672: struct m88k_opcode *format,
        !           673: char *param,
        !           674: struct m88k_insn *insn)
        !           675: {
        !           676:        int parcnt;
        !           677: 
        !           678:        /* initial the passed structure */
        !           679: 
        !           680:        memset(insn, '\0', sizeof(*insn));
        !           681:        insn->reloc = NO_RELOC;
        !           682:        insn->opcode = format->opcode;
        !           683: 
        !           684:        /* parse all parameters */
        !           685: 
        !           686:        for (parcnt=0; parcnt<3 && format->op[parcnt].type != NIL; parcnt++) {
        !           687: 
        !           688:                switch (format->op[parcnt].type) {
        !           689: 
        !           690:                        case CNST:
        !           691:                                param = parse_cst(param, insn, format, parcnt);
        !           692:                                break;
        !           693: 
        !           694:                        case REG:
        !           695:                                param = parse_reg(param, insn, format, parcnt);
        !           696:                                break;
        !           697: #ifdef m88110
        !           698:                        case EREG:
        !           699:                                param = parse_ereg(param, insn, format, parcnt);
        !           700:                                break;
        !           701: 
        !           702:                        case E4ROT:
        !           703:                                param = parse_e4rot(param, insn, format,parcnt);
        !           704:                                break;
        !           705: 
        !           706:                        case XREG:
        !           707:                                param = parse_xreg(param, insn, format, parcnt);
        !           708:                                break;
        !           709: #endif m88110
        !           710:                        case BF:
        !           711:                                param = parse_bf(param, insn, format, parcnt);
        !           712:                                break;
        !           713: 
        !           714:                        case ROT:
        !           715:                                param = parse_rot(param, insn, format, parcnt);
        !           716:                                break;
        !           717: 
        !           718:                        case REGSC:
        !           719:                                param = parse_rsc(param, insn, format, parcnt);
        !           720:                                break;
        !           721: 
        !           722:                        case CRREG:
        !           723:                                param = parse_cr(param, insn, format, parcnt);
        !           724:                                break;
        !           725: 
        !           726:                        case FCRREG:
        !           727:                                param = parse_fcr(param, insn, format, parcnt);
        !           728:                                break;
        !           729: 
        !           730:                        case PCREL:
        !           731:                                param = parse_pcr(param, insn, format, parcnt);
        !           732:                                break;
        !           733: 
        !           734:                        case CONDMASK:
        !           735:                                param = parse_cnd(param, insn, format, parcnt);
        !           736:                                break;
        !           737: 
        !           738:                        case CMPRSLT:
        !           739:                                param = parse_cmp(param, insn, format, parcnt);
        !           740:                                break;
        !           741: 
        !           742:                        default:
        !           743:                                as_fatal("Unknown parameter type");
        !           744:                }
        !           745: 
        !           746:                /* see if parser failed or not */
        !           747: 
        !           748:                if (param == NULL)
        !           749:                        return 0;
        !           750:        }
        !           751: 
        !           752:        return 1;
        !           753: }
        !           754: 
        !           755: static
        !           756: char *
        !           757: parse_pcr(
        !           758: char *param,
        !           759: struct m88k_insn *insn,
        !           760: struct m88k_opcode *format,
        !           761: int parcnt)
        !           762: {
        !           763:        char *saveptr, *saveparam;
        !           764:        segT seg;
        !           765: 
        !           766:        saveptr = input_line_pointer;
        !           767:        input_line_pointer = param;
        !           768: 
        !           769:        seg = expression(&insn->exp);
        !           770: 
        !           771:        saveparam = input_line_pointer;
        !           772:        input_line_pointer = saveptr;
        !           773: 
        !           774:        switch (format->op[parcnt].width) {
        !           775: 
        !           776:                case 16: insn->reloc = M88K_RELOC_PC16;
        !           777:                         break;
        !           778: 
        !           779:                case 26: insn->reloc = M88K_RELOC_PC26;
        !           780:                         break;
        !           781: 
        !           782:                default: as_warn("Strange PC relative width %d",
        !           783:                                                format->op[parcnt].width);
        !           784:                         break;
        !           785:        }
        !           786: 
        !           787:        return saveparam;
        !           788: }
        !           789: 
        !           790: static
        !           791: char *
        !           792: parse_reg(
        !           793: char *param,
        !           794: struct m88k_insn *insn,
        !           795: struct m88k_opcode *format,
        !           796: int parcnt)
        !           797: {
        !           798:        unsigned int val = 0;
        !           799: 
        !           800:        if (*param != 'r' && *param != 'R')
        !           801:                return NULL;
        !           802: 
        !           803:        param++;
        !           804: 
        !           805:        if (!isdigit(*param))
        !           806:                return NULL;
        !           807: 
        !           808:        while (isdigit(*param))
        !           809:                if ((val = val * 10 + *param++ - '0') > 31)
        !           810:                        return NULL;
        !           811: 
        !           812:        insn->opcode |= val << format->op[parcnt].offset;
        !           813: 
        !           814:        switch (*param) {
        !           815: 
        !           816:                case '\0' :
        !           817:                        if (parcnt == 2 || format->op[parcnt+1].type == NIL)
        !           818:                                return param;
        !           819:                        else
        !           820:                                return NULL;
        !           821: 
        !           822:                case '['  :
        !           823:                        if (parcnt != 2 && format->op[parcnt+1].type == REGSC)
        !           824:                                return param+1;
        !           825:                        else
        !           826:                                return NULL;
        !           827: 
        !           828:                case ','  :
        !           829:                        if (parcnt != 2 && format->op[parcnt+1].type != NIL)
        !           830:                                return param+1;
        !           831:                        else
        !           832:                                return NULL;
        !           833:        }
        !           834: 
        !           835:        return NULL;
        !           836: }
        !           837: 
        !           838: #ifdef m88110
        !           839: static
        !           840: char *
        !           841: parse_ereg(
        !           842: char *param,
        !           843: struct m88k_insn *insn,
        !           844: struct m88k_opcode *format,
        !           845: int parcnt)
        !           846: {
        !           847:        unsigned int val = 0;
        !           848: 
        !           849:        if (*param != 'r' && *param != 'R')
        !           850:                return NULL;
        !           851: 
        !           852:        param++;
        !           853: 
        !           854:        if (!isdigit(*param))
        !           855:                return NULL;
        !           856: 
        !           857:        while (isdigit(*param))
        !           858:                if ((val = val * 10 + *param++ - '0') > 31)
        !           859:                        return NULL;
        !           860: 
        !           861:        if((val & 0x1) != 0)
        !           862:                return NULL;
        !           863: 
        !           864:        insn->opcode |= val << format->op[parcnt].offset;
        !           865: 
        !           866:        switch (*param) {
        !           867: 
        !           868:                case '\0' :
        !           869:                        if (parcnt == 2 || format->op[parcnt+1].type == NIL)
        !           870:                                return param;
        !           871:                        else
        !           872:                                return NULL;
        !           873: 
        !           874:                case '['  :
        !           875:                        if (parcnt != 2 && format->op[parcnt+1].type == REGSC)
        !           876:                                return param+1;
        !           877:                        else
        !           878:                                return NULL;
        !           879: 
        !           880:                case ','  :
        !           881:                        if (parcnt != 2 && format->op[parcnt+1].type != NIL)
        !           882:                                return param+1;
        !           883:                        else
        !           884:                                return NULL;
        !           885:        }
        !           886: 
        !           887:        return NULL;
        !           888: }
        !           889: 
        !           890: static
        !           891: char *
        !           892: parse_e4rot(
        !           893: char *param,
        !           894: struct m88k_insn *insn,
        !           895: struct m88k_opcode *format,
        !           896: int parcnt)
        !           897: {
        !           898:        int val;
        !           899:        char *saveptr, save_c, *offset_ptr;
        !           900:         expressionS exp;
        !           901:        segT seg;
        !           902: 
        !           903:        /* Now step over the '<' and look for the offset expression before a
        !           904:           '>' and the end of line (which is a '\0' when we get here).  We
        !           905:           know there is a '\0' where the end of line was because that is
        !           906:           what parse_a_buffer() in read.c does before calling md_assemble */
        !           907:        if (*param++ != '<')
        !           908:                return NULL;
        !           909:        offset_ptr = param;
        !           910:        while(*param != '\0')
        !           911:                param++;
        !           912:        if(param == offset_ptr || param[-1] != '>')
        !           913:                return NULL;
        !           914:        param--;
        !           915:        save_c = *param;
        !           916:        *param = '\0';
        !           917:        saveptr = input_line_pointer;
        !           918:        input_line_pointer = offset_ptr;
        !           919:        seg = expression(&exp);
        !           920:        *param = save_c;
        !           921:        input_line_pointer = saveptr;
        !           922:        val = exp.X_add_number;
        !           923:        if(seg != SEG_ABSOLUTE || val > 60 || (val & 0x3) != 0)
        !           924:                return NULL;
        !           925: 
        !           926:        val >>= 2;
        !           927:        insn->opcode |= val << format->op[parcnt].offset;
        !           928: 
        !           929:        return param+1;
        !           930: }
        !           931: 
        !           932: static
        !           933: char *
        !           934: parse_xreg(
        !           935: char *param,
        !           936: struct m88k_insn *insn,
        !           937: struct m88k_opcode *format,
        !           938: int parcnt)
        !           939: {
        !           940:        unsigned int val = 0;
        !           941: 
        !           942:        if (*param != 'x' && *param != 'X')
        !           943:                return NULL;
        !           944: 
        !           945:        param++;
        !           946: 
        !           947:        if (!isdigit(*param))
        !           948:                return NULL;
        !           949: 
        !           950:        while (isdigit(*param))
        !           951:                if ((val = val * 10 + *param++ - '0') > 31)
        !           952:                        return NULL;
        !           953: 
        !           954:        insn->opcode |= val << format->op[parcnt].offset;
        !           955: 
        !           956:        switch (*param) {
        !           957: 
        !           958:                case '\0' :
        !           959:                        if (parcnt == 2 || format->op[parcnt+1].type == NIL)
        !           960:                                return param;
        !           961:                        else
        !           962:                                return NULL;
        !           963: 
        !           964:                case '['  :
        !           965:                        if (parcnt != 2 && format->op[parcnt+1].type == REGSC)
        !           966:                                return param+1;
        !           967:                        else
        !           968:                                return NULL;
        !           969: 
        !           970:                case ','  :
        !           971:                        if (parcnt != 2 && format->op[parcnt+1].type != NIL)
        !           972:                                return param+1;
        !           973:                        else
        !           974:                                return NULL;
        !           975:        }
        !           976: 
        !           977:        return NULL;
        !           978: }
        !           979: #endif m88110
        !           980: 
        !           981: static
        !           982: char *
        !           983: parse_cmp(
        !           984: char *param,
        !           985: struct m88k_insn *insn,
        !           986: struct m88k_opcode *format,
        !           987: int parcnt)
        !           988: {
        !           989:        int val;
        !           990:        char *saveptr, save_c, *offset_ptr, c;
        !           991:         expressionS exp;
        !           992:        segT seg;
        !           993: 
        !           994:        /* look for the offset expression before a ',' */
        !           995:        c = *param;
        !           996:        if (isdigit(c) || c == '(' || c == '-' || c == '+' || c == '!' ||
        !           997:            c == '~'){
        !           998:                offset_ptr = param;
        !           999:                while(*param != ',')
        !          1000:                        param++;
        !          1001:                if(param == offset_ptr || *param != ',')
        !          1002:                        return NULL;
        !          1003:                save_c = *param;
        !          1004:                *param = '\0';
        !          1005:                saveptr = input_line_pointer;
        !          1006:                input_line_pointer = offset_ptr;
        !          1007:                seg = expression(&exp);
        !          1008:                *param = save_c;
        !          1009:                input_line_pointer = saveptr;
        !          1010:                val = exp.X_add_number;
        !          1011:                if(seg != SEG_ABSOLUTE ||
        !          1012:                   val > (1 << format->op[parcnt].width) || val < 0)
        !          1013:                        return NULL;
        !          1014:        } else {
        !          1015:                if (isupper(*param))
        !          1016:                        *param = tolower(*param);
        !          1017: 
        !          1018:                if (isupper(*(param+1)))
        !          1019:                        *(param+1) = tolower(*(param+1));
        !          1020: 
        !          1021:                for (val=0; cmpslot[val] != NULL; val++)
        !          1022:                        if (!strncmp(param,cmpslot[val],2))
        !          1023:                                break;
        !          1024: 
        !          1025:                if (cmpslot[val] == NULL)
        !          1026:                        return NULL;
        !          1027: 
        !          1028:                param += 2;
        !          1029:        }
        !          1030: 
        !          1031:        if (*param++ != ',')
        !          1032:                return NULL;
        !          1033: 
        !          1034:        insn->opcode |= val << format->op[parcnt].offset;
        !          1035: 
        !          1036:        return param;
        !          1037: }
        !          1038: 
        !          1039: static
        !          1040: char *
        !          1041: parse_cnd(
        !          1042: char *param,
        !          1043: struct m88k_insn *insn,
        !          1044: struct m88k_opcode *format,
        !          1045: int parcnt)
        !          1046: {
        !          1047:        int val;
        !          1048:        char *saveptr, save_c, *offset_ptr, c;
        !          1049:         expressionS exp;
        !          1050:        segT seg;
        !          1051: 
        !          1052:        /* look for the offset expression before a ',' */
        !          1053:        c = *param;
        !          1054:        if (isdigit(c) || c == '(' || c == '-' || c == '+' || c == '!' ||
        !          1055:            c == '~'){
        !          1056:                offset_ptr = param;
        !          1057:                while(*param != ',')
        !          1058:                        param++;
        !          1059:                if(param == offset_ptr || *param != ',')
        !          1060:                        return NULL;
        !          1061:                save_c = *param;
        !          1062:                *param = '\0';
        !          1063:                saveptr = input_line_pointer;
        !          1064:                input_line_pointer = offset_ptr;
        !          1065:                seg = expression(&exp);
        !          1066:                *param = save_c;
        !          1067:                input_line_pointer = saveptr;
        !          1068:                val = exp.X_add_number;
        !          1069:                if(seg != SEG_ABSOLUTE ||
        !          1070:                   val > (1 << format->op[parcnt].width) || val < 0)
        !          1071:                        return NULL;
        !          1072:        } else {
        !          1073:                if (isupper(*param))
        !          1074:                        *param = tolower(*param);
        !          1075: 
        !          1076:                if (isupper(*(param+1)))
        !          1077:                        *(param+1) = tolower(*(param+1));
        !          1078: 
        !          1079:                for (val=0; cndmsk[val].name != NULL; val++)
        !          1080:                        if (!strncmp(param,cndmsk[val].name,3))
        !          1081:                                break;
        !          1082: 
        !          1083:                if (cndmsk[val].name == NULL)
        !          1084:                        return NULL;
        !          1085: 
        !          1086:                val = cndmsk[val].num;
        !          1087: 
        !          1088:                param += 3;
        !          1089:        }
        !          1090: 
        !          1091:        if (*param++ != ',')
        !          1092:                return NULL;
        !          1093: 
        !          1094:        insn->opcode |= val << format->op[parcnt].offset;
        !          1095: 
        !          1096:        return param;
        !          1097: }
        !          1098: 
        !          1099: static
        !          1100: char *
        !          1101: parse_bf(
        !          1102: char *param,
        !          1103: struct m88k_insn *insn,
        !          1104: struct m88k_opcode *format,
        !          1105: int parcnt)
        !          1106: {
        !          1107:        int val, width;
        !          1108:        char *saveptr, save_c, *offset_ptr, c;
        !          1109:         expressionS exp;
        !          1110:        segT seg;
        !          1111: 
        !          1112:        /* We know there is a '\0' where the end of line was because that is
        !          1113:           what parse_a_buffer() in read.c does before calling md_assemble */
        !          1114: 
        !          1115:        /* First look for the width expression before a '<' */
        !          1116:        saveptr = input_line_pointer;
        !          1117:        input_line_pointer = param;
        !          1118:        while(*param != '<' && *param != '\0')
        !          1119:                param++;
        !          1120:        if(*param == '\0'){
        !          1121:                input_line_pointer = saveptr;
        !          1122:                return NULL;
        !          1123:        }
        !          1124:        save_c = *param;
        !          1125:        *param = '\0';
        !          1126:        seg = expression(&exp);
        !          1127:        *param = save_c;
        !          1128:        input_line_pointer = saveptr;
        !          1129:        width = exp.X_add_number;
        !          1130:        if(seg != SEG_ABSOLUTE || width > 32 || width < 0)
        !          1131:                return NULL;
        !          1132: 
        !          1133:        /* Now step over the '<' and look for the offset expression before a
        !          1134:           '>' and the end of line (which is a '\0' when we get here) */
        !          1135:        param++;
        !          1136:        c = *param;
        !          1137:        if (isdigit(c) || c == '(' || c == '-' || c == '+' || c == '!' ||
        !          1138:            c == '~'){
        !          1139:                offset_ptr = param;
        !          1140:                while(*param != '\0')
        !          1141:                        param++;
        !          1142:                if(param != offset_ptr && param[-1] != '>')
        !          1143:                        return NULL;
        !          1144:                param--;
        !          1145:                save_c = *param;
        !          1146:                *param = '\0';
        !          1147:                saveptr = input_line_pointer;
        !          1148:                input_line_pointer = offset_ptr;
        !          1149:                seg = expression(&exp);
        !          1150:                *param = save_c;
        !          1151:                input_line_pointer = saveptr;
        !          1152:                val = exp.X_add_number;
        !          1153:                if(seg != SEG_ABSOLUTE || val > 32 || val < 0)
        !          1154:                        return NULL;
        !          1155:        }
        !          1156:        else {
        !          1157:                if (isupper(*param))
        !          1158:                        *param = tolower(*param);
        !          1159: 
        !          1160:                if (isupper(*(param+1)))
        !          1161:                        *(param+1) = tolower(*(param+1));
        !          1162: 
        !          1163:                for (val=0; cmpslot[val] != NULL; val++)
        !          1164:                        if (!strncmp(param,cmpslot[val],2))
        !          1165:                                break;
        !          1166: 
        !          1167:                if (cmpslot[val] == NULL)
        !          1168:                        return NULL;
        !          1169: 
        !          1170:                param += 2;
        !          1171:        }
        !          1172:        if (*param != '>')
        !          1173:                return NULL;
        !          1174:        insn->opcode |= width << 5;
        !          1175:        insn->opcode |= val;
        !          1176: 
        !          1177:        return param+1;
        !          1178: }
        !          1179: 
        !          1180: static
        !          1181: char *
        !          1182: parse_rot(
        !          1183: char *param,
        !          1184: struct m88k_insn *insn,
        !          1185: struct m88k_opcode *format,
        !          1186: int parcnt)
        !          1187: {
        !          1188:        int val;
        !          1189:        char *saveptr, save_c, *offset_ptr;
        !          1190:         expressionS exp;
        !          1191:        segT seg;
        !          1192: 
        !          1193:        /* Now step over the '<' and look for the offset expression before a
        !          1194:           '>' and the end of line (which is a '\0' when we get here).  We
        !          1195:           know there is a '\0' where the end of line was because that is
        !          1196:           what parse_a_buffer() in read.c does before calling md_assemble */
        !          1197:        if (*param++ != '<')
        !          1198:                return NULL;
        !          1199:        offset_ptr = param;
        !          1200:        while(*param != '\0')
        !          1201:                param++;
        !          1202:        if(param != offset_ptr && param[-1] != '>')
        !          1203:                return NULL;
        !          1204:        param--;
        !          1205:        save_c = *param;
        !          1206:        *param = '\0';
        !          1207:        saveptr = input_line_pointer;
        !          1208:        input_line_pointer = offset_ptr;
        !          1209:        seg = expression(&exp);
        !          1210:        *param = save_c;
        !          1211:        input_line_pointer = saveptr;
        !          1212:        val = exp.X_add_number;
        !          1213:        if(seg != SEG_ABSOLUTE && (val > 32 || val < 0))
        !          1214:                return NULL;
        !          1215: 
        !          1216:        insn->opcode |= val;
        !          1217: 
        !          1218:        return param+1;
        !          1219: }
        !          1220: 
        !          1221: static
        !          1222: char *
        !          1223: parse_rsc(
        !          1224: char *param,
        !          1225: struct m88k_insn *insn,
        !          1226: struct m88k_opcode *format,
        !          1227: int parcnt)
        !          1228: {
        !          1229:        unsigned int val = 0;
        !          1230: 
        !          1231:        if (*param != 'r' && *param != 'R')
        !          1232:                return NULL;
        !          1233: 
        !          1234:        param++;
        !          1235: 
        !          1236:        if (!isdigit(*param))
        !          1237:                return NULL;
        !          1238: 
        !          1239:        while (isdigit(*param))
        !          1240:                if ((val = val * 10 + *param++ - '0') > 31)
        !          1241:                        return NULL;
        !          1242: 
        !          1243:        insn->opcode |= val << format->op[parcnt].offset;
        !          1244: 
        !          1245:        if (*param != ']' || *(param+1) != '\0')
        !          1246:                return NULL;
        !          1247: 
        !          1248:        return param+1;
        !          1249: }
        !          1250: 
        !          1251: static
        !          1252: char *
        !          1253: parse_cr(
        !          1254: char *param,
        !          1255: struct m88k_insn *insn,
        !          1256: struct m88k_opcode *format,
        !          1257: int parcnt)
        !          1258: {
        !          1259:        unsigned int val = 0;
        !          1260: 
        !          1261:        if (strncmp(param, "cr", 2))
        !          1262:                return NULL;
        !          1263: 
        !          1264:        param += 2;
        !          1265: 
        !          1266:        if (!isdigit(*param))
        !          1267:                return NULL;
        !          1268: 
        !          1269:        while (isdigit(*param))
        !          1270:                if ((val = val * 10 + *param++ - '0') > 63)
        !          1271:                        return NULL;
        !          1272: 
        !          1273:        /*
        !          1274:         * the following fix is not as generic as I'd like, but the
        !          1275:         * hardware is real picky about this.   - [email protected]
        !          1276:         * This fix is to make sure the S1 and S2 fields are the same.
        !          1277:         */
        !          1278:        insn->opcode |= (insn->opcode & 0x001f0000) >> 16;
        !          1279: 
        !          1280:        insn->opcode |= val << format->op[parcnt].offset;
        !          1281: 
        !          1282:        if (*param != '\0')
        !          1283:                return NULL;
        !          1284: 
        !          1285:        return param;
        !          1286: }
        !          1287: 
        !          1288: static
        !          1289: char *
        !          1290: parse_fcr(
        !          1291: char *param,
        !          1292: struct m88k_insn *insn,
        !          1293: struct m88k_opcode *format,
        !          1294: int parcnt)
        !          1295: {
        !          1296:        unsigned int val = 0;
        !          1297: 
        !          1298:        if (strncmp(param, "fcr", 3))
        !          1299:                return NULL;
        !          1300: 
        !          1301:        param += 3;
        !          1302: 
        !          1303:        if (!isdigit(*param))
        !          1304:                return NULL;
        !          1305: 
        !          1306:        while (isdigit(*param))
        !          1307:                if ((val = val * 10 + *param++ - '0') > 63)
        !          1308:                        return NULL;
        !          1309: 
        !          1310:        /*
        !          1311:         * This is to make sure the S1 and S2 fields are the same.
        !          1312:         */
        !          1313:        insn->opcode |= (insn->opcode & 0x001f0000) >> 16;
        !          1314: 
        !          1315:        insn->opcode |= val << format->op[parcnt].offset;
        !          1316: 
        !          1317:        if (*param != '\0')
        !          1318:                return NULL;
        !          1319: 
        !          1320:        return param;
        !          1321: }
        !          1322: 
        !          1323: static
        !          1324: char *
        !          1325: parse_cst(
        !          1326: char *param,
        !          1327: struct m88k_insn *insn,
        !          1328: struct m88k_opcode *format,
        !          1329: int parcnt)
        !          1330: {
        !          1331:        char c, *saveptr, *saveparam;
        !          1332:        unsigned int val, nohilo = 0;
        !          1333:        segT seg;
        !          1334:         expressionS exp;
        !          1335: 
        !          1336:        c = *param;
        !          1337:        if (isdigit(c) || c == '(' || c == '-' || c == '+' || c == '!' ||
        !          1338:            c == '~'){
        !          1339:                saveptr = input_line_pointer;
        !          1340:                input_line_pointer = param;
        !          1341:                while(*param != '\0')
        !          1342:                        param++;
        !          1343:                seg = expression(&exp);
        !          1344:                input_line_pointer = saveptr;
        !          1345:                val = exp.X_add_number;
        !          1346:                if(seg != SEG_ABSOLUTE || val > (1 << format->op[parcnt].width))
        !          1347:                        return NULL;
        !          1348:        }
        !          1349:        else if (!strncmp(param,"hi16(",5))
        !          1350: 
        !          1351:                if (isdigit(*(param+5))) {
        !          1352:                        param = getval(param+5,&val);
        !          1353:                        val = (val & 0xffff0000) >> 16;
        !          1354:                        if (*param++ != ')')
        !          1355:                                return NULL;
        !          1356: 
        !          1357:                } else
        !          1358:                        insn->reloc = M88K_RELOC_HI16;
        !          1359:        else if (!strncmp(param,"lo16(",5))
        !          1360: 
        !          1361:                if (isdigit(*(param+5))) {
        !          1362:                        param = getval(param+5,&val);
        !          1363:                        val &= 0x0000ffff;
        !          1364:                        if (*param++ != ')')
        !          1365:                                return NULL;
        !          1366: 
        !          1367:                } else
        !          1368:                        insn->reloc = M88K_RELOC_LO16;
        !          1369: 
        !          1370: #ifndef NeXT
        !          1371:        else if (!strncmp(param,"iw16(",5))
        !          1372: 
        !          1373:                if (isdigit(*(param+5))) {
        !          1374:                        param = getval(param+5,&val);
        !          1375:                        val &= 0x0000ffff;
        !          1376:                        if (*param++ != ')')
        !          1377:                                return NULL;
        !          1378: 
        !          1379:                } else
        !          1380:                        insn->reloc = M88K_RELOC_IW16;
        !          1381: #endif /* !defined(NeXT) */
        !          1382: 
        !          1383:        else if (*param == 'r' && isdigit(*(param+1)))
        !          1384: 
        !          1385:                return NULL;
        !          1386: 
        !          1387:        else {
        !          1388:                insn->reloc = M88K_RELOC_LO16;
        !          1389:                nohilo = 1;
        !          1390:        }
        !          1391: 
        !          1392:        if (insn->reloc != NO_RELOC) {
        !          1393: 
        !          1394:                saveptr = input_line_pointer;
        !          1395:                input_line_pointer = param + (nohilo ? 0 : 5);
        !          1396: 
        !          1397:                seg = expression(&insn->exp);
        !          1398: 
        !          1399:                saveparam = input_line_pointer;
        !          1400:                input_line_pointer = saveptr;
        !          1401: 
        !          1402:                if (nohilo) {
        !          1403: 
        !          1404:                        if (*saveparam != '\0')
        !          1405:                                return NULL;
        !          1406: 
        !          1407:                        return saveparam;
        !          1408:                }
        !          1409: 
        !          1410:                if (*saveparam != ')')
        !          1411:                        return NULL;
        !          1412: 
        !          1413:                return saveparam+1;
        !          1414:        }
        !          1415: 
        !          1416:        if ((1 << format->op[parcnt].width) <= val)
        !          1417:                return NULL;
        !          1418: 
        !          1419:        insn->opcode |= val << format->op[parcnt].offset;
        !          1420: 
        !          1421:        if (*param != '\0')
        !          1422:                return NULL;
        !          1423: 
        !          1424:        return param;
        !          1425: }
        !          1426: 
        !          1427: #define isoct(z) (z >= '0' && z <= '7')
        !          1428: #define ishex(z) ((z >= '0' && z <= '9') || (z >= 'a' && z <= 'f') || (z >= 'A' && z <= 'F'))
        !          1429: #define hexval(z) \
        !          1430:   (isdigit(z) ? (z) - '0' :            \
        !          1431:    islower(z) ? (z) - 'a' + 10 :       \
        !          1432:    (z) - 'A' + 10)
        !          1433: 
        !          1434: static
        !          1435: char *
        !          1436: getval(
        !          1437: char *param,
        !          1438: unsigned int *val)
        !          1439: {
        !          1440:        *val = 0;
        !          1441: 
        !          1442:        if (*param == '0' && (*(param+1) == 'x' || *(param+1) == 'X'))
        !          1443: 
        !          1444:                for (param += 2; ishex(*param); param++)
        !          1445: 
        !          1446:                        if (*val > 0x0fffffff)
        !          1447:                                return param;
        !          1448:                        else
        !          1449:                                *val = *val * 16 + hexval(*param);
        !          1450: 
        !          1451:        else if (*param == '0')
        !          1452: 
        !          1453:                for (param++; isoct(*param); param++)
        !          1454: 
        !          1455:                        if (*val > 0x1fffffff)
        !          1456:                                return param;
        !          1457:                        else
        !          1458:                                *val = *val * 8 + *param - '0';
        !          1459: 
        !          1460:        else
        !          1461: 
        !          1462:                for (; isdigit(*param); param++)
        !          1463: 
        !          1464:                        *val = *val * 10 + *param - '0';
        !          1465: 
        !          1466:        return param;
        !          1467: }
        !          1468: 
        !          1469: void
        !          1470: md_number_to_chars(
        !          1471: char *buf,
        !          1472: long val,
        !          1473: int nbytes)
        !          1474: {
        !          1475:        switch(nbytes) {
        !          1476: 
        !          1477:                case 4:
        !          1478:                        *buf++ = val >> 24;
        !          1479:                        *buf++ = val >> 16;
        !          1480:                case 2:
        !          1481:                        *buf++ = val >> 8;
        !          1482:                case 1:
        !          1483:                        *buf = val;
        !          1484:                        break;
        !          1485: 
        !          1486:                default:
        !          1487:                        abort();
        !          1488:        }
        !          1489: }
        !          1490: 
        !          1491: void
        !          1492: md_number_to_imm(
        !          1493: unsigned char *buf,
        !          1494: long val,
        !          1495: int nbytes,
        !          1496: fixS *fixP,
        !          1497: int nsect)
        !          1498: {
        !          1499:        if(fixP->fx_r_type == NO_RELOC ||
        !          1500:           fixP->fx_r_type == M88K_RELOC_VANILLA) {
        !          1501:                switch (nbytes) {
        !          1502:                        case 4:
        !          1503:                                *buf++ = val >> 24;
        !          1504:                                *buf++ = val >> 16;
        !          1505:                        case 2:
        !          1506:                                *buf++ = val >> 8;
        !          1507:                        case 1:
        !          1508:                                *buf = val;
        !          1509:                                break;
        !          1510: 
        !          1511:                        default:
        !          1512:                                abort();
        !          1513:                }
        !          1514:                return;
        !          1515:        }
        !          1516: 
        !          1517:        switch (fixP->fx_r_type) {
        !          1518: #ifdef NeXT
        !          1519:                        case M88K_RELOC_LO16:
        !          1520:                                buf[2] = val >> 8;
        !          1521:                                buf[3] = val;
        !          1522:                                break;
        !          1523:                        case M88K_RELOC_HI16:
        !          1524:                                buf[2] = val >> 24;
        !          1525:                                buf[3] = val >> 16;
        !          1526:                                break;
        !          1527: 
        !          1528:                        case M88K_RELOC_PC16:
        !          1529:                                val += 4;
        !          1530:                                buf[2] = val >> 10;
        !          1531:                                buf[3] = val >> 2;
        !          1532:                                break;
        !          1533: 
        !          1534:                        case M88K_RELOC_PC26:
        !          1535:                                val += 4;
        !          1536:                                buf[0] |= (val >> 26) & 0x03;
        !          1537:                                buf[1] = val >> 18;
        !          1538:                                buf[2] = val >> 10;
        !          1539:                                buf[3] = val >> 2;
        !          1540:                                break;
        !          1541: #else /* !defined NeXT */
        !          1542:                        case M88K_RELOC_LO16:
        !          1543:                                buf[0] = val >> 8;
        !          1544:                                buf[1] = val;
        !          1545:                                break;
        !          1546: 
        !          1547:                        case M88K_RELOC_IW16:
        !          1548:                                buf[2] = val >> 8;
        !          1549:                                buf[3] = val;
        !          1550:                                break;
        !          1551: 
        !          1552:                        case M88K_RELOC_HI16:
        !          1553:                                buf[0] = val >> 24;
        !          1554:                                buf[1] = val >> 16;
        !          1555:                                break;
        !          1556: 
        !          1557:                        case M88K_RELOC_PC16:
        !          1558:                                val += 4;
        !          1559:                                buf[0] = val >> 10;
        !          1560:                                buf[1] = val >> 2;
        !          1561:                                break;
        !          1562: 
        !          1563:                        case M88K_RELOC_PC26:
        !          1564:                                val += 4;
        !          1565:                                buf[0] |= (val >> 26) & 0x03;
        !          1566:                                buf[1] = val >> 18;
        !          1567:                                buf[2] = val >> 10;
        !          1568:                                buf[3] = val >> 2;
        !          1569:                                break;
        !          1570: 
        !          1571:                        case M88K_RELOC_32:
        !          1572:                                buf[0] = val >> 24;
        !          1573:                                buf[1] = val >> 16;
        !          1574:                                buf[2] = val >> 8;
        !          1575:                                buf[3] = val;
        !          1576:                                break;
        !          1577: #endif /* !defined(NeXT) */
        !          1578: 
        !          1579:                        default:
        !          1580:                                as_warn("Bad relocation type");
        !          1581:                                break;
        !          1582:        }
        !          1583: }
        !          1584: 
        !          1585: #define MAX_LITTLENUMS 6
        !          1586: 
        !          1587: /* Turn a string in input_line_pointer into a floating point constant of type
        !          1588:    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
        !          1589:    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
        !          1590:  */
        !          1591: char *
        !          1592: md_atof(
        !          1593: int type,
        !          1594: char *litP,
        !          1595: int *sizeP)
        !          1596: {
        !          1597:        int     prec;
        !          1598:        LITTLENUM_TYPE words[MAX_LITTLENUMS];
        !          1599:        LITTLENUM_TYPE *wordP;
        !          1600:        char    *t;
        !          1601:        char    *atof_ieee();
        !          1602: 
        !          1603:        switch(type) {
        !          1604:        case 'f':
        !          1605:        case 'F':
        !          1606:        case 's':
        !          1607:        case 'S':
        !          1608:                prec = 2;
        !          1609:                break;
        !          1610: 
        !          1611:        case 'd':
        !          1612:        case 'D':
        !          1613:        case 'r':
        !          1614:        case 'R':
        !          1615:                prec = 4;
        !          1616:                break;
        !          1617: 
        !          1618:        case 'x':
        !          1619:        case 'X':
        !          1620:                prec = 6;
        !          1621:                break;
        !          1622: 
        !          1623:        case 'p':
        !          1624:        case 'P':
        !          1625:                prec = 6;
        !          1626:                break;
        !          1627: 
        !          1628:        default:
        !          1629:                *sizeP=0;
        !          1630:                return "Bad call to MD_ATOF()";
        !          1631:        }
        !          1632:        t=atof_ieee(input_line_pointer,type,words);
        !          1633:        if(t)
        !          1634:                input_line_pointer=t;
        !          1635: 
        !          1636:        *sizeP=prec * sizeof(LITTLENUM_TYPE);
        !          1637:        for(wordP=words;prec--;) {
        !          1638:                md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
        !          1639:                litP+=sizeof(LITTLENUM_TYPE);
        !          1640:        }
        !          1641:        return "";      /* Someone should teach Dean about null pointers */
        !          1642: }
        !          1643: 
        !          1644: const relax_typeS md_relax_table[] = {0};
        !          1645: 
        !          1646: int
        !          1647: md_estimate_size_before_relax(
        !          1648: fragS *fragP,
        !          1649: int segment_type)
        !          1650: {
        !          1651:        as_fatal("internal error: Relaxation should never occur");
        !          1652:        return(0);
        !          1653: }
        !          1654: 
        !          1655: void
        !          1656: md_convert_frag(
        !          1657: fragS *fragP)
        !          1658: {
        !          1659:        as_fatal("internal error: Relaxation should never occur");
        !          1660: }
        !          1661: 
        !          1662: void
        !          1663: md_end(
        !          1664: void)
        !          1665: {
        !          1666: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.