Annotation of GNUtools/cctools/as/m88k.c, revision 1.1.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.