Annotation of GNUtools/cctools/as/i860.c, revision 1.1.1.1

1.1       root        1: /* i860.c -- Assemble for the i860
                      2:    Copyright (C) 1989 Free Software Foundation, Inc.
                      3: 
                      4: This file is 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: 
                     21: #include <stdio.h>
                     22: #include <string.h>
                     23: #include <ctype.h>
                     24: #include <mach-o/i860/reloc.h>
                     25: 
                     26: #include "i860-opcode.h"
                     27: #include "as.h"
                     28: #include "flonum.h"
                     29: #include "expr.h"
                     30: #include "hash.h"
                     31: #include "frags.h"
                     32: #include "fixes.h"
                     33: #include "read.h"
                     34: #include "md.h"
                     35: #include "symbols.h"
                     36: #include "messages.h"
                     37: #include "sections.h"
                     38: 
                     39: /*
                     40:  * These are the default cputype and cpusubtype for the i860 architecture.
                     41:  */
                     42: const cpu_type_t md_cputype = CPU_TYPE_I860;
                     43: cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_I860_ALL;
                     44: 
                     45: /*
                     46:  * This is the byte sex for the i860 architecture.  The chip is running in
                     47:  * big endian mode so the assembler puts out the entire file (instructions
                     48:  * included) in big endian.  When the program is loaded in memory to be run
                     49:  * the program doing the loading byte swaps the fix width instructions.  If
                     50:  * this is not to be done by the loading program then BYTE_SWAP can be defined
                     51:  * in here that will put out the instructiona in little endian in the object
                     52:  * file.
                     53:  */
                     54: const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX;
                     55: 
                     56: static int i860_ip(
                     57:     char *str);
                     58: static void md_insn_to_chars(
                     59:     unsigned char *buf,
                     60:     long val,
                     61:     int n);
                     62: 
                     63: const relax_typeS md_relax_table[] = { 0 };
                     64: 
                     65: /* handle of the OPCODE hash table */
                     66: static struct hash_control *op_hash = NULL;
                     67: 
                     68: static void s_dual(
                     69:     int mode);
                     70: static void s_i860_align(
                     71:     int value);
                     72: static void s_i860_org(
                     73:     int value);
                     74: 
                     75: const pseudo_typeS md_pseudo_table[] = {
                     76:     { "float", float_cons,     'f'     },
                     77:     { "int",   cons,           4       },
                     78:     { "align", s_i860_align,   0       },      /* Alignment is in bytes */
                     79:     { "blkb",  s_space,        0       },      /* Reserve space, in bytes */
                     80:     { "dual",  s_dual,         1       },      /* Dual insn mode crock */
                     81:     { "enddual",s_dual,                0       },
                     82:     { "extern",        s_globl,        0       },      /* as860 equiv of .globl */
                     83:     { "ln",    s_line,         0       },      /* as860 equiv of .line */
                     84:     { "org",   s_i860_org,     0       },
                     85: #ifndef NeXT
                     86:     { "quad",  big_cons,       16      },      /* A quad is 16 bytes on 860 */
                     87: #endif /* NeXT */
                     88:     { "string",        stringer,       1       },      /* as860 equiv of .asciz */
                     89:     { NULL,     0,             0       },
                     90: };
                     91: 
                     92: static int dual_insn_mode = 0;
                     93: 
                     94: /* This array holds the chars that always start a comment.  If the
                     95:     pre-processor is disabled, these aren't very useful */
                     96: const char md_comment_chars[] = "|!";
                     97: 
                     98: /* This array holds the chars that only start a comment at the beginning of
                     99:    a line.  If the line seems to have the form '# 123 filename'
                    100:    .line and .file directives will appear in the pre-processed output */
                    101: /* Note that input_file.c hand checks for '#' at the beginning of the
                    102:    first line of the input file.  This is because the compiler outputs
                    103:    #NO_APP at the beginning of its output. */
                    104: /* Also note that a '/' followed by a '*' will always start a comment */
                    105: const char md_line_comment_chars[] = "#";
                    106: 
                    107: /* Chars that can be used to separate mant from exp in floating point nums */
                    108: const char md_EXP_CHARS[] = "eE";
                    109: 
                    110: /* Chars that mean this number is a floating point constant */
                    111: /* As in 0f12.456 */
                    112: /* or    0d1.2345e12 */
                    113: const char md_FLT_CHARS[] = "rRsSfFdDxXpP";
                    114: 
                    115: /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
                    116:    changed in read.c .  Ideally it shouldn't have to know about it at all,
                    117:    but nothing is ideal around here.
                    118:  */
                    119: int size_reloc_info = sizeof(struct relocation_info);
                    120: 
                    121: static unsigned char octal[256];
                    122: #define isoctal(c)  octal[c]
                    123: static unsigned char toHex[256];
                    124: 
                    125: /* Local fatal error flag.  Used to bomb assembler in md_end after scanning input */
                    126: static int I860_errors;
                    127: 
                    128: static int insn_count; /* Track insns assembled, as a word count */
                    129: 
                    130: struct i860_it {
                    131:     char    *error;
                    132:     unsigned long opcode;
                    133:     struct nlist *nlistp;
                    134:     expressionS exp;
                    135:     int pcrel;
                    136:     enum reloc_type_i860 reloc;
                    137: };
                    138: static struct i860_it the_insn;
                    139: 
                    140: #ifdef I860_DEBUG
                    141: static void print_insn(
                    142:     struct i860_it *insn);
                    143: #endif /* I860_DEBUG */
                    144: 
                    145: static int getExpression(
                    146:     char *str);
                    147: static char *expr_end;
                    148: 
                    149: /* Flags returned by i860_ip() */
                    150: #define INSERT_NOP     0x00000001
                    151: 
                    152: static
                    153: void
                    154: s_dual(
                    155: int mode)
                    156: {
                    157:        dual_insn_mode = mode;
                    158: }
                    159: 
                    160: static
                    161: void
                    162: s_i860_align(
                    163: int value)
                    164: {
                    165:     register unsigned int temp;
                    166:     register long int temp_fill;
                    167:     unsigned int i = 0;
                    168:     unsigned int bytes;
                    169:     char *toP;
                    170: 
                    171:     bytes = temp = get_absolute_expression ();
                    172: #define MAX_ALIGNMENT (1 << 15)
                    173:     if ( temp > MAX_ALIGNMENT ) {
                    174:        as_warn("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT);
                    175:     }
                    176: 
                    177:     /*
                    178:      * For the i860, `.align (1<<n)' actually means `.align n'
                    179:      * so we have to convert it.
                    180:      */
                    181:     if (temp != 0) {
                    182:        for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
                    183:            ;
                    184:     }
                    185:     if (temp != 1) {
                    186:        as_warn("Alignment not a power of 2");
                    187:     }
                    188:     temp = i;
                    189:     if (*input_line_pointer == ',') {
                    190:        input_line_pointer ++;
                    191:        temp_fill = get_absolute_expression ();
                    192:     } else {
                    193:        if ( frchain_now->frch_nsect == text_nsect )
                    194:                temp_fill = OP_NOP;
                    195:        else
                    196:                temp_fill = 0;
                    197:     }
                    198:     if ( frchain_now->frch_nsect == text_nsect )       /* emit NOPs! */
                    199:     {  /* Grow the code frag as needed and dump nops into it. */
                    200:        if ( bytes & 3 )
                    201:                as_warn( "Instruction alignment must be a multiple of 4." );
                    202:        bytes &= ~3;
                    203:        /* This is really tacky, but works for a fixed width insn machine */
                    204:        while ( bytes && ((insn_count * 4) % bytes) != 0 ) 
                    205:        {
                    206:                toP = frag_more(4);     /* Add an instruction */
                    207:                /* put out the opcode */
                    208:                md_insn_to_chars(toP, temp_fill, 4);    /* Fill instruction */
                    209:                insn_count++;
                    210:        }
                    211:        /* Clean up */
                    212:        demand_empty_rest_of_line();
                    213:        return;
                    214:     }
                    215:     /* Only make a frag if we HAVE to. . . */
                    216:     if (temp) {
                    217:        frag_align (temp, (int)temp_fill);
                    218:     }
                    219:     /*
                    220:      * If this alignment is larger than any previous alignment then this
                    221:      * becomes the section's alignment.
                    222:      */
                    223:     if(frchain_now->frch_section.align < temp)
                    224:        frchain_now->frch_section.align = temp;
                    225:     demand_empty_rest_of_line();
                    226:     return;
                    227: }
                    228: 
                    229: static
                    230: void
                    231: s_i860_org(
                    232: int value)
                    233: {
                    234:        register segT segment;
                    235:        expressionS exp;
                    236:        register long int temp_fill;
                    237:        register char *p;
                    238:        extern segT get_known_segmented_expression();
                    239: 
                    240: /*
                    241:  * Don't believe the documentation of BSD 4.2 AS.
                    242:  * There is no such thing as a sub-segment-relative origin.
                    243:  * Any absolute origin is given a warning, then assumed to be segment-relative.
                    244:  * Any segmented origin expression ("foo+42") had better be in the right
                    245:  * segment or the .org is ignored.
                    246:  *
                    247:  * BSD 4.2 AS warns if you try to .org backwards. We cannot because we
                    248:  * never know sub-segment sizes when we are reading code.
                    249:  * BSD will crash trying to emit -ve numbers of filler bytes in certain
                    250:  * .orgs. We don't crash, but see as-write for that code.
                    251:  */
                    252:        segment = get_known_segmented_expression(& exp);
                    253:        if ( *input_line_pointer == ',' ) {
                    254:                input_line_pointer ++;
                    255:                temp_fill = get_absolute_expression ();
                    256:        } else
                    257:                temp_fill = 0;
                    258: 
                    259:        if((segment != SEG_SECT ||
                    260:            exp.X_add_symbol->sy_other != frchain_now->frch_nsect) &&
                    261:            segment != SEG_ABSOLUTE)
                    262:            as_warn("Illegal expression. current section assumed.");
                    263: 
                    264:        if ( exp.X_add_symbol != NULL )
                    265:                as_warn("Symbol relative .org may corrupt alignment.");
                    266:        else if ( exp.X_add_number & 3 )
                    267:        {
                    268:            exp.X_add_number &= ~3;
                    269:            as_warn(".org not on instruction boundry. Adjusted to \".org %ld\"",
                    270:                exp.X_add_number);
                    271:        }
                    272:        if ( exp.X_add_symbol == NULL )
                    273:                insn_count = exp.X_add_number >> 2;
                    274:        p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp . X_add_symbol,
                    275: exp . X_add_number, (char *)0);
                    276:        * p = temp_fill;
                    277: 
                    278:        demand_empty_rest_of_line();
                    279: }
                    280: 
                    281: 
                    282: /*
                    283:  * This function is called once, at assembler startup time.  This should
                    284:  * set up all the tables, etc that the MD part of the assembler needs
                    285:  */
                    286: void
                    287: md_begin(
                    288: void)
                    289: {
                    290:     register char *retval = NULL;
                    291:     register int i;
                    292:     int j = 0;
                    293: 
                    294:     insn_count = 0;
                    295:     if ((op_hash = hash_new()) == NULL)
                    296:        as_fatal("Virtual memory exhausted");
                    297: 
                    298:     for (i = 0; i < NUMOPCODES; ++i) {
                    299:        if (~i860_opcodes[i].mask & i860_opcodes[i].match) {
                    300:            printf("bad opcode - `%s %s'\n",
                    301:                i860_opcodes[i].name, i860_opcodes[i].args);
                    302:            ++j;
                    303:        }
                    304:     }
                    305: 
                    306:     if (j)
                    307:        exit(1);
                    308: 
                    309:     for (i = 0; i < NUMOPCODES; ++i) {
                    310:       retval = hash_insert(op_hash, (char *)i860_opcodes[i].name,
                    311:                           (char *)&i860_opcodes[i]);
                    312:       if(retval && *retval) {
                    313:          as_fatal("Internal Error:  Can't hash %s: %s",
                    314:            i860_opcodes[i].name, retval);
                    315:       }
                    316:       while (!i860_opcodes[i].last)
                    317:          ++i;
                    318:     }
                    319:     for (i = '0'; i < '8'; ++i)
                    320:        octal[i] = 1;
                    321:     for (i = '0'; i <= '9'; ++i)
                    322:        toHex[i] = i - '0';
                    323:     for (i = 'a'; i <= 'f'; ++i)
                    324:        toHex[i] = i + 10 - 'a';
                    325:     for (i = 'A'; i <= 'F'; ++i)
                    326:        toHex[i] = i + 10 - 'A';
                    327: 
                    328:     I860_errors = 0;
                    329:     return;
                    330: }
                    331: 
                    332: void
                    333: md_end(
                    334: void)
                    335: {
                    336:     if ( I860_errors )
                    337:     {
                    338:        fprintf( stderr, "%d fatal %s encountered during assembly.\n", I860_errors,
                    339:                (I860_errors == 1 ? "error" : "errors") );
                    340:        exit( 42 );     /* Fatal errors seen during assembly */
                    341:     }
                    342: 
                    343:     return;
                    344: }
                    345: 
                    346: void
                    347: md_assemble(
                    348: char *str)
                    349: {
                    350:     char *toP;
                    351:     int flags;
                    352: 
                    353:     assert(str);
                    354:     flags = i860_ip(str);
                    355:     if ( flags & INSERT_NOP )
                    356:     {
                    357:         toP = frag_more(4);
                    358:         /* put out the opcode */
                    359:         md_insn_to_chars(toP, OP_NOP, 4);
                    360:        ++insn_count;
                    361:     }
                    362:     toP = frag_more(4);
                    363:     /* put out the opcode */
                    364:     md_insn_to_chars(toP, the_insn.opcode, 4);
                    365:     ++insn_count;
                    366: 
                    367:     /* put out the symbol-dependent stuff */
                    368:     if (the_insn.reloc != NO_RELOC) {
                    369:        fix_new(
                    370:            frag_now,                           /* which frag */
                    371:            (toP - frag_now->fr_literal), /* where */
                    372:            4,                                  /* size */
                    373:            the_insn.exp.X_add_symbol,
                    374:            the_insn.exp.X_subtract_symbol,
                    375:            the_insn.exp.X_add_number,
                    376:            the_insn.pcrel, 0,
                    377:            the_insn.reloc
                    378:        );
                    379:     }
                    380: }
                    381: 
                    382: static
                    383: int
                    384: i860_ip(
                    385: char *str)
                    386: {
                    387:     char *s;
                    388:     char *op;
                    389:     const char *args;
                    390:     char c;
                    391:     struct i860_opcode *insn;
                    392:     char *argsStart;
                    393:     char *s1;
                    394:     unsigned long   opcode;
                    395:     unsigned int mask;
                    396:     int this_insn_is_dual = 0;
                    397:     int adjustment;
                    398:     int        align_mask;
                    399:     int match = FALSE;
                    400:     int comma = 0;
                    401:     int flags = 0;
                    402:     static int expect_int_insn;        /* Tracking for fp/int insns in dual mode. */
                    403: 
                    404:     /* Advance s to end of opcode */
                    405:     for (s = str; islower(*s) || *s == '.' || isdigit(*s); ++s)
                    406:        ;
                    407:     switch (*s) {
                    408: 
                    409:     case '\0':
                    410:        break;
                    411: 
                    412:     case ',':
                    413:        comma = 1;
                    414: 
                    415:        /*FALLTHROUGH*/
                    416: 
                    417:     case ' ':
                    418:     case '\t':
                    419:        *s++ = '\0';
                    420:        break;
                    421: 
                    422:     default:
                    423:            as_warn("Unknown opcode: `%s'", str);
                    424:            exit(1);
                    425:     }
                    426:     /* Code to sniff for 'd.' prefix here and flag for dual insn mode */
                    427:     op = str;
                    428:     if ( *op == 'd' && *(op + 1) == '.' )
                    429:     {
                    430:        op += 2;
                    431:        this_insn_is_dual = 1;
                    432:     }
                    433:         
                    434:     if ((insn = (struct i860_opcode *) hash_find(op_hash, op)) == NULL) {
                    435:        as_warn("Unknown instruction or format: `%s'.", str);
                    436:        memset(&the_insn, '\0', sizeof(the_insn));      /* Patch in no-op to hold alignment */
                    437:        the_insn.reloc = NO_RELOC;
                    438:        the_insn.opcode = OP_NOP;
                    439:        ++I860_errors;                          /* Flag as fatal error */
                    440:        return flags;
                    441:     }
                    442:     if (comma) {
                    443:        *--s = ',';
                    444:     }
                    445:     argsStart = s;
                    446:     for (;;) {
                    447:        opcode = insn->match;
                    448:        memset(&the_insn, '\0', sizeof(the_insn));
                    449:        the_insn.reloc = NO_RELOC;
                    450: 
                    451:        /*
                    452:         * Build the opcode, checking as we go to make
                    453:         * sure that the operands match
                    454:         */
                    455:        for (args = insn->args; ; ++args) {
                    456:            align_mask = 0;
                    457:            switch (*args) {
                    458: 
                    459:            case '\0':  /* end of args */
                    460:                if (*s == '\0') {
                    461:                    match = TRUE;
                    462:                }
                    463:                break;
                    464: 
                    465:            case '+':
                    466:            case '(':   /* these must match exactly */
                    467:            case ')':
                    468:            case ',':
                    469:            case ' ':
                    470:                if (*s++ == *args)
                    471:                    continue;
                    472:                break;
                    473:                
                    474:            case 'C':   /* Control register */
                    475:                if (strncmp(s, "fir", 3) == 0) {
                    476:                    s += 3;
                    477:                    SET_RS2(opcode, 0);
                    478:                    continue;
                    479:                }
                    480:                if (strncmp(s, "psr", 3) == 0) {
                    481:                    s += 3;
                    482:                    SET_RS2(opcode, 1);
                    483:                    continue;
                    484:                }
                    485:                if (strncmp(s, "dirbase", 7) == 0) {
                    486:                    s += 7;
                    487:                    SET_RS2(opcode, 2);
                    488:                    continue;
                    489:                }
                    490:                if (strncmp(s, "db", 2) == 0) {
                    491:                    s += 2;
                    492:                    SET_RS2(opcode, 3);
                    493:                    continue;
                    494:                }
                    495:                if (strncmp(s, "fsr", 3) == 0) {
                    496:                    s += 3;
                    497:                    SET_RS2(opcode, 4);
                    498:                    continue;
                    499:                }
                    500:                if (strncmp(s, "epsr", 4) == 0) {
                    501:                    s += 4;
                    502:                    SET_RS2(opcode, 5);
                    503:                    continue;
                    504:                }
                    505:                break;
                    506: 
                    507:            case '1':   /* next operand must be a register */
                    508:            case '2':
                    509:            case 'd':
                    510:                {
                    511:                    switch (c = *s++) {
                    512: 
                    513:                    case 'f':   /* frame pointer */
                    514:                        if (*s++ == 'p') {
                    515:                            mask = 3;   /* register fp is alias for r3 */
                    516:                            break;
                    517:                        }
                    518:                        goto error;
                    519: 
                    520:                    case 's':   /* global register */
                    521:                        if (*s++ == 'p') {
                    522:                            mask = 2;   /* register sp is alias for r2 */
                    523:                            break;
                    524:                        }
                    525:                        goto error;
                    526: 
                    527:                    case 'r': /* any register */
                    528:                        if (!isdigit(c = *s++)) {
                    529:                            goto error;
                    530:                        }
                    531:                        if (isdigit(*s)) {
                    532:                            if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
                    533:                                goto error;
                    534:                            }
                    535:                        } else {
                    536:                            c -= '0';
                    537:                        }
                    538:                        mask= c;
                    539:                        break;
                    540: 
                    541:                    default:
                    542:                        goto error;
                    543:                    }
                    544:                    /*
                    545:                     * Got the register, now figure out where
                    546:                     * it goes in the opcode.
                    547:                     */
                    548:                    switch (*args) {
                    549: 
                    550:                    case '1':
                    551:                        SET_RS1(opcode, mask);
                    552:                        continue;
                    553: 
                    554:                    case '2':
                    555:                        SET_RS2(opcode, mask);
                    556:                        continue;
                    557: 
                    558:                    case 'd':
                    559:                        SET_RD(opcode, mask);
                    560:                        continue;
                    561:                    }
                    562:                }
                    563:                break;
                    564: 
                    565:            case 'e':    /* next operand is a floating point register */
                    566:            case 'f':
                    567:            case 'g':
                    568:            case 'E':
                    569:            case 'F':
                    570:            case 'G':
                    571:            case 'H':
                    572:                if (*s++ == 'f' && isdigit(*s)) {
                    573:                    mask = *s++;
                    574:                    if (isdigit(*s)) {
                    575:                        mask = 10 * (mask - '0') + (*s++ - '0');
                    576:                        if (mask >= 32) {
                    577:                            break;
                    578:                        }
                    579:                    } else {
                    580:                        mask -= '0';
                    581:                    }
                    582:                    if ( (*args == 'E' || *args == 'F' || *args == 'G') && (mask & 1) )
                    583:                    {
                    584:                        as_warn( "f%d: Even register required.  Adjusted to f%d.",
                    585:                                mask, mask & 0x1E );
                    586:                        mask &= 0x1E;
                    587:                    }
                    588:                    else if ( *args == 'H' && (mask & 3) )
                    589:                    {
                    590:                        as_warn( "f%d: Quad register required.  Adjusted to f%d.",
                    591:                                mask, mask & 0x1C );
                    592:                        mask &= 0x1C;
                    593:                    }
                    594:                    switch (*args) {
                    595: 
                    596:                    case 'e':
                    597:                    case 'E':
                    598:                        SET_RS1(opcode, mask);
                    599:                        continue;
                    600: 
                    601:                    case 'f':
                    602:                    case 'F':
                    603:                        SET_RS2(opcode, mask);
                    604:                        continue;
                    605: 
                    606:                    case 'g':
                    607:                    case 'G':
                    608:                    case 'H':
                    609:                        SET_RD(opcode, mask);
                    610:                        continue;
                    611:                    }
                    612:                }
                    613:                break;
                    614:        
                    615:            case 'B':   /* 5 bit immediate unsigned constant */ 
                    616:                (void)getExpression(s);
                    617:                s = expr_end;
                    618:                if ( the_insn.exp.X_seg != SEG_ABSOLUTE )
                    619:                {
                    620:                        as_warn( "Constant expression expected" );
                    621:                        ++I860_errors;
                    622:                }
                    623:                if ( the_insn.exp.X_add_number < 0 || the_insn.exp.X_add_number > 31 )
                    624:                    as_warn( "Constant must be between 0 and 31. Modulo 32 applied." );
                    625:                SET_RS1(opcode, the_insn.exp.X_add_number); /* Takes const modulo 32 */
                    626:                continue;
                    627:                
                    628:            case 'D':   /* immediate unsigned constant used in shift opcodes */ 
                    629:                (void)getExpression(s);
                    630:                s = expr_end;
                    631:                if ( the_insn.exp.X_seg != SEG_ABSOLUTE )
                    632:                {
                    633:                        as_warn( "Constant expression expected" );
                    634:                        ++I860_errors;
                    635:                }
                    636:                if ( the_insn.exp.X_add_number < 0 || the_insn.exp.X_add_number > 31 )
                    637:                    as_warn( "Constant must be between 0 and 31. Modulo 32 applied." );
                    638:                opcode |= (the_insn.exp.X_add_number & 0x1F);
                    639:                continue;
                    640: 
                    641:            case 'i':       /* low 16 bits, byte aligned */
                    642:                the_insn.reloc = I860_RELOC_LOW0;
                    643:                goto immediate;
                    644:                
                    645:            case 'I':       /* high 16 bits */
                    646:                the_insn.reloc = I860_RELOC_HIGH;
                    647:                goto immediate;
                    648: 
                    649:            case 'j':       /* low 16 bits, short aligned */
                    650:                the_insn.reloc = I860_RELOC_LOW1;
                    651:                align_mask = 1;
                    652:                goto immediate;
                    653: 
                    654:            case 'k':       /* low 16 bits, int aligned */
                    655:                the_insn.reloc = I860_RELOC_LOW2;
                    656:                align_mask = 3;
                    657:                goto immediate;
                    658: 
                    659:            case 'l':       /* low 16 bits, double aligned */
                    660:                the_insn.reloc = I860_RELOC_LOW3;
                    661:                align_mask = 7;
                    662:                goto immediate;
                    663: 
                    664:            case 'm':       /* low 16 bits, quad aligned */
                    665:                the_insn.reloc = I860_RELOC_LOW4;
                    666:                align_mask = 15;
                    667:                goto immediate;
                    668: 
                    669:            case 'n':       /* low 16 bits, byte aligned, split field */
                    670:                the_insn.reloc = I860_RELOC_SPLIT0;
                    671:                goto immediate;
                    672: 
                    673:            case 'o':       /* low 16 bits, short aligned, split field */
                    674:                the_insn.reloc = I860_RELOC_SPLIT1;
                    675:                align_mask = 1;
                    676:                goto immediate;
                    677: 
                    678:            case 'p':       /* low 16 bits, int aligned, split field */
                    679:                the_insn.reloc = I860_RELOC_SPLIT2;
                    680:                align_mask = 3;
                    681:                goto immediate;
                    682: 
                    683:            case 'J':       /* High 16 bits, requiring adjustment */
                    684:                the_insn.reloc = I860_RELOC_HIGHADJ;
                    685:                goto immediate;
                    686: 
                    687: 
                    688:            case 'K':   /* 26 bit PC relative immediate */
                    689:                the_insn.reloc = I860_RELOC_BRADDR;
                    690:                the_insn.pcrel = 1;
                    691:                goto immediate;
                    692: 
                    693:            case 'L':   /* 16 bit PC relative split format immediate */
                    694:                the_insn.reloc = I860_RELOC_SPLIT0;
                    695:                the_insn.pcrel = 1;
                    696:                goto immediate;
                    697:                /*FALLTHROUGH*/
                    698: 
                    699:            immediate:
                    700:                if(*s==' ')
                    701:                  s++;
                    702:                adjustment = 0;
                    703:                if ( *s == 'h' && *(s + 1) == '%' )
                    704:                {
                    705:                        adjustment = I860_RELOC_HIGH;
                    706:                        if ( the_insn.reloc == I860_RELOC_LOW0 && the_insn.pcrel == 0 )
                    707:                        {
                    708:                                the_insn.reloc = I860_RELOC_HIGH;
                    709:                        }
                    710:                        else
                    711:                                as_warn("Improper use of h%%.");
                    712:                        s += 2;
                    713:                }
                    714:                else if ( *s == 'h' && *(s + 1) == 'a' && *(s + 2) == '%' )
                    715:                {
                    716:                        adjustment = I860_RELOC_HIGHADJ;
                    717:                        if ( the_insn.reloc == I860_RELOC_LOW0 && the_insn.pcrel == 0 )
                    718:                        {
                    719:                                the_insn.reloc = I860_RELOC_HIGHADJ;
                    720:                        }
                    721:                        else
                    722:                                as_warn("Improper use of ha%%.");
                    723: 
                    724:                        s += 3;
                    725:                }
                    726:                else if ( *s == 'l' &&  *(s + 1) == '%' )
                    727:                {       /* the_insn.reloc is correct as is. */
                    728:                        adjustment = I860_RELOC_LOW0;
                    729:                        s += 2;
                    730:                }
                    731:                /* Note that if the getExpression() fails, we will still have
                    732:                   created U entries in the symbol table for the 'symbols'
                    733:                   in the input string.  Try not to create U symbols for
                    734:                   registers, etc. */
                    735:                   
                    736:                /* This stuff checks to see if the expression ends
                    737:                   in '(', as in ld.l foo(r20). If it does, it
                    738:                   removes the '(' from the expression, and 
                    739:                   re-sets 's' to point to the right place */
                    740: 
                    741:                for(s1=s;*s1 && *s1!=','&& *s1!=')';s1++)
                    742:                        ;
                    743: 
                    744:                if( s1 != s && *s1 == '(' && s1[1] == 'r' && isdigit(s1[2])
                    745:                    && (s1[3]==')' || (isdigit(s1[3]) && s1[4] == ')')) ) {
                    746:                                *s1='\0';
                    747:                                (void)getExpression(s);
                    748:                                *s1='(';
                    749:                                s=s1;
                    750:                }
                    751:                else
                    752:                {
                    753:                        (void)getExpression(s);
                    754:                        s = expr_end;
                    755:                }
                    756:                /*
                    757:                 * If there is an adjustment, we assume the user knows what
                    758:                 * they are doing.  If no adjustment, we very carefully range 
                    759:                 * check for both signed and unsigned operations, to avoid 
                    760:                 * unpleasant suprises.  The checks are skipped for branch and
                    761:                 * call instructions, matching the behavior of the Intel assembler.
                    762:                 */
                    763:                if ( ! adjustment && *op != 'b' && *op != 'c' )
                    764:                {
                    765:                    if ( the_insn.exp.X_seg != SEG_ABSOLUTE )
                    766:                    {
                    767:                        as_warn(
                    768:                          "Non-absolute expression requires h%%, l%%, or ha%% prefix."
                    769:                        );
                    770:                    }
                    771:                    else
                    772:                    {
                    773:                        if ( IS_LOGOP(opcode) )
                    774:                        {
                    775:                            if ( ((unsigned)the_insn.exp.X_add_number) > 0xFFFF )
                    776:                                as_warn("%lu is too big for 16 bit unsigned value!",
                    777:                                        the_insn.exp.X_add_number);
                    778:                        }
                    779:                        else
                    780:                        {
                    781:                            if ( ((int)the_insn.exp.X_add_number) > 32767 ||
                    782:                                 ((int)the_insn.exp.X_add_number) < -32768 )
                    783:                                as_warn("%ld is out of range for 16 bit signed value!",
                    784:                                        the_insn.exp.X_add_number);
                    785:                                        
                    786:                            if ((align_mask & the_insn.exp.X_add_number) != 0)
                    787:                                as_warn("Const offset 0x%x incorrectly aligned.",
                    788:                                        (unsigned int)the_insn.exp.X_add_number);
                    789:                        }
                    790:                    }
                    791:                }
                    792:                continue;
                    793:                
                    794:            default:
                    795:                abort();
                    796:            }
                    797:            break;
                    798:        }
                    799:        error:
                    800:        if (match == FALSE) {
                    801:            /* args don't match */
                    802:            if (!insn->last) {
                    803:                ++insn;
                    804:                s = argsStart;
                    805:                continue;
                    806:            } else {
                    807:                as_warn("Illegal operands (%s %s).", str, argsStart);
                    808:                ++I860_errors;
                    809:                return flags;
                    810:            }
                    811:        }
                    812:        break;
                    813:     }
                    814:     /* If the last insn was dual, check and make sure that this insn is integer insn */
                    815:     if ( expect_int_insn && (dual_insn_mode || this_insn_is_dual) )
                    816:     {
                    817:            if ( (opcode & OP_PREFIX_MASK) == PREFIX_FPU || opcode == OP_FNOP )
                    818:            {
                    819:                as_warn( "Core half of prev dual insn pair missing." );
                    820:            }
                    821:            expect_int_insn = 0;
                    822:     }
                    823:     /* Check the insn format and fold in the dual mode bit if appropriate. */
                    824:     if ( dual_insn_mode || this_insn_is_dual )
                    825:     {
                    826:            if ( (opcode & OP_PREFIX_MASK) == PREFIX_FPU || opcode == OP_FNOP )
                    827:            {
                    828:                    if ( insn_count & 1 )       /* Odd insn, not on 64 bit bound! */
                    829:                    {
                    830:                        as_warn( "Dual FP insn on odd addr." );
                    831:                    }
                    832:                    opcode |= DUAL_INSN_MODE_BIT;
                    833:                    expect_int_insn = 1;
                    834:            }
                    835:            else if ( this_insn_is_dual ) /* d. prefix on a non-FPU insn error */
                    836:            {
                    837:                    as_warn("d. prefix not allowed for `%s'. (Ignored!)", op);
                    838:            } 
                    839:     }
                    840:     else
                    841:            expect_int_insn = 0;        /* Single insn mode. */
                    842:     /* Check for correct alignment of const in branch to label + offset */
                    843:     if (    (the_insn.reloc == I860_RELOC_BRADDR
                    844:             || (the_insn.pcrel && the_insn.reloc == I860_RELOC_SPLIT0)
                    845:            ) && (the_insn.exp.X_add_number & 3) )
                    846:                as_warn( "Branch offset is not aligned to instruction boundry!" );
                    847:     the_insn.opcode = opcode;
                    848:     return flags;
                    849: }
                    850: 
                    851: static
                    852: int
                    853: getExpression(
                    854: char *str)
                    855: {
                    856:     char *save_in;
                    857:     segT seg;
                    858: 
                    859:     save_in = input_line_pointer;
                    860:     input_line_pointer = str;
                    861:     switch (seg = expression(&the_insn.exp)) {
                    862: 
                    863:     case SEG_ABSOLUTE:
                    864:     case SEG_SECT:
                    865:     case SEG_DIFFSECT:
                    866:     case SEG_UNKNOWN:
                    867:     case SEG_BIG:
                    868:     case SEG_NONE:
                    869:        break;
                    870: 
                    871:     default:
                    872:        the_insn.error = "bad segment";
                    873:        expr_end = input_line_pointer;
                    874:        input_line_pointer=save_in;
                    875:        return 1;
                    876:     }
                    877:     expr_end = input_line_pointer;
                    878:     input_line_pointer = save_in;
                    879:     return 0;
                    880: }
                    881: 
                    882: 
                    883: #define MAX_LITTLENUMS 6
                    884: 
                    885: /*
                    886:     This is identical to the md_atof in m68k.c.  I think this is right,
                    887:     but I'm not sure.
                    888: 
                    889:    Turn a string in input_line_pointer into a floating point constant of type
                    890:    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
                    891:    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
                    892:  */
                    893: char *
                    894: md_atof(
                    895: int type,
                    896: char *litP,
                    897: int *sizeP)
                    898: {
                    899:     int        prec;
                    900:     LITTLENUM_TYPE words[MAX_LITTLENUMS];
                    901:     LITTLENUM_TYPE *wordP;
                    902:     char       *t;
                    903:     char       *atof_ieee();
                    904: 
                    905:     switch(type) {
                    906: 
                    907:     case 'f':
                    908:     case 'F':
                    909:     case 's':
                    910:     case 'S':
                    911:        prec = 2;
                    912:        break;
                    913: 
                    914:     case 'd':
                    915:     case 'D':
                    916:     case 'r':
                    917:     case 'R':
                    918:        prec = 4;
                    919:        break;
                    920:     /* The following two formats get reduced to doubles. */
                    921:     case 'x':
                    922:     case 'X':
                    923:        type = 'd';
                    924:        prec = 4;
                    925:        break;
                    926: 
                    927:     case 'p':
                    928:     case 'P':
                    929:        type = 'd';
                    930:        prec = 4;
                    931:        break;
                    932: 
                    933:     default:
                    934:        *sizeP=0;
                    935:        return "Bad call to MD_ATOF()";
                    936:     }
                    937:     t=atof_ieee(input_line_pointer,type,words);
                    938:     if(t)
                    939:        input_line_pointer=t;
                    940:     *sizeP=prec * sizeof(LITTLENUM_TYPE);
                    941:     for(wordP=words;prec--;) {
                    942:        md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
                    943:        litP+=sizeof(LITTLENUM_TYPE);
                    944:     }
                    945:     return ""; /* Someone should teach Dean about null pointers */
                    946: }
                    947: 
                    948: /*
                    949:  * Write out big-endian.  Valid for data only in our I860 implementation.
                    950:  */
                    951: void
                    952: md_number_to_chars(
                    953: char *buf,
                    954: long val,
                    955: int n)
                    956: {
                    957: 
                    958:     switch(n) {
                    959: 
                    960:     case 4:
                    961:        *buf++ = val >> 24;
                    962:        *buf++ = val >> 16;
                    963:     case 2:
                    964:        *buf++ = val >> 8;
                    965:     case 1:
                    966:        *buf = val;
                    967:        break;
                    968: 
                    969:     default:
                    970:        abort();
                    971:     }
                    972:     return;
                    973: }
                    974: 
                    975: #ifdef BYTE_SWAP
                    976: /*
                    977:  * Write out little-endian.  Valid for instructions only in
                    978:  * our i860 implementation.
                    979:  */
                    980: static
                    981: void
                    982: md_insn_to_chars(
                    983: unsigned char *buf,
                    984: long val,
                    985: int n)
                    986: {
                    987: 
                    988:     switch(n) {
                    989: 
                    990:     case 4:
                    991:        *buf++ = val;
                    992:        *buf++ = val >> 8;
                    993:        *buf++ = val >> 16;
                    994:        *buf++ = val >> 24;
                    995:        break;
                    996:     case 2:
                    997:        *buf++ = val;
                    998:        *buf++ = val >> 8;
                    999:        break;
                   1000:     case 1:
                   1001:        *buf = val;
                   1002:        break;
                   1003: 
                   1004:     default:
                   1005:        abort();
                   1006:     }
                   1007:     return;
                   1008: }
                   1009: #else /* !defined(BYTE_SWAP) */
                   1010: 
                   1011: static
                   1012: void
                   1013: md_insn_to_chars(
                   1014: unsigned char *buf,
                   1015: long val,
                   1016: int n)
                   1017: {
                   1018:        md_number_to_chars(buf,val,n);
                   1019: }
                   1020: #endif /* BYTE_SWAP */
                   1021: 
                   1022: void
                   1023: md_number_to_imm(
                   1024: unsigned char *buf,
                   1025: long val,
                   1026: int n,
                   1027: fixS *fixP,
                   1028: int nsect)
                   1029: {
                   1030:     unsigned long opcode;
                   1031: 
                   1032:     if ( nsect == text_nsect && (n % 4) != 0 )
                   1033:        as_warn("Immediate write of non-aligned data into text segment." );
                   1034:        
                   1035:     if (nsect != text_nsect ||
                   1036:        fixP->fx_r_type == NO_RELOC ||
                   1037:        fixP->fx_r_type == I860_RELOC_VANILLA)
                   1038:     {
                   1039:        switch (n) {    /* Write out the data big-endian style. */
                   1040:        case 1:
                   1041:                *buf = val;
                   1042:                break;
                   1043:        case 2:
                   1044:                *buf++ = (val>>8);
                   1045:                *buf = val;
                   1046:                break;
                   1047:        case 4:
                   1048:                *buf++ = (val>>24);
                   1049:                *buf++ = (val>>16);
                   1050:                *buf++ = (val>>8);
                   1051:                *buf = val;
                   1052:                break;
                   1053:        default:
                   1054:                abort();
                   1055:        }
                   1056:        return;
                   1057:     }
                   1058: 
                   1059:     assert(n == 4);    /* Better be an instruction with relocation data.... */
                   1060:     assert(fixP->fx_r_type < NO_RELOC && fixP->fx_r_type > I860_RELOC_VANILLA);
                   1061:     /*
                   1062:      * Here is where we do initial bit fiddling to load immediate 
                   1063:      * values into the i860 bit fields.
                   1064:      */
                   1065: #ifdef BYTE_SWAP     
                   1066:     /* Note that all of these insns are ultimately little-endian */
                   1067:     /* Get the opcode from the buffer.  Less efficient, but more coherent... */
                   1068:     opcode = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
                   1069: #else
                   1070:     opcode = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
                   1071: #endif  
                   1072:     /* Apply the relocation value 'val' */
                   1073:     switch (fixP->fx_r_type) { 
                   1074:        case I860_RELOC_PAIR:
                   1075:                as_warn("questionable relocation type I860_RELOC_PAIR");
                   1076:                break;
                   1077:        case I860_RELOC_HIGH:
                   1078:                opcode &= ~0xFFFF;
                   1079:                opcode |= ((val >> 16) & 0xFFFF);
                   1080:                break;
                   1081:        case I860_RELOC_LOW0:
                   1082:                opcode &= ~0xFFFF;
                   1083:                opcode |= (val & 0xFFFF);
                   1084:                break;
                   1085:        case I860_RELOC_LOW1:
                   1086:                opcode &= 0xFFFF0001;
                   1087:                opcode |= (val & 0xFFFE);       /* Bit 0 is an insn bit! */
                   1088:                break;
                   1089:        case I860_RELOC_LOW2:
                   1090:                opcode &= 0xFFFF0003;
                   1091:                opcode |= (val & 0xFFFC);       /* Bits 0 and 1 are insn bits! */
                   1092:                break;
                   1093:        case I860_RELOC_LOW3:
                   1094:                opcode &= 0xFFFF0007;
                   1095:                opcode |= (val & 0xFFF8);       /* Bits 0 thru 2 are insn bits! */
                   1096:                break;
                   1097:        case I860_RELOC_LOW4:
                   1098:                opcode &= 0xFFFF000F;
                   1099:                opcode |= (val & 0xFFF0);       /* Bits 0 thru 3 are insn bits! */
                   1100:                break;
                   1101:        case I860_RELOC_SPLIT0:
                   1102:                opcode &= 0xFFE0F800;
                   1103:                if ( fixP->fx_pcrel )           /* A 16 bit branch relative insn? */
                   1104:                        val >>= 2;              /* Convert to word address */
                   1105:                opcode |= ((val & 0xF800) << 5) | (val & 0x7FF);
                   1106:                break;
                   1107:        case I860_RELOC_SPLIT1:
                   1108:                opcode &= 0xFFE0F801;           /* Again, bit 0 is an insn bit! */
                   1109:                opcode |= ((val & 0xF800) << 5) | (val & 0x7FE);
                   1110:                break;
                   1111:        case I860_RELOC_SPLIT2:
                   1112:                opcode &= 0xFFE0F803;           /* Bits 0 and 1 are insn bits! */
                   1113:                opcode |= ((val & 0xF800) << 5) | (val & 0x7FC);
                   1114:                break;
                   1115:        case I860_RELOC_HIGHADJ:                        /* Adjusted variant */
                   1116:                opcode &= ~0xFFFF;
                   1117:                /* If the low half would be negative, compensate by adding 1 to 
                   1118:                 * high half.
                   1119:                 */
                   1120:                if ( (val & 0x8000) != 0 )
                   1121:                        val = (val >> 16) + 1;
                   1122:                else
                   1123:                        val = (val >> 16);
                   1124:                opcode |= (val & 0xFFFF);
                   1125:                break;
                   1126:        case I860_RELOC_BRADDR:
                   1127:                if ( fixP->fx_pcrel )           /* A 26 bit branch relative insn? */
                   1128:                        val >>= 2;              /* Convert to word address */
                   1129:                opcode &= 0xFC000000;
                   1130:                opcode |= (val & 0x03FFFFFF);
                   1131:                break;
                   1132:        
                   1133:        default:
                   1134:                as_warn("bad relocation type: 0x%02x", fixP->fx_r_type);
                   1135:                break;
                   1136:        }
                   1137: #ifdef BYTE_SWAP
                   1138:        buf[0] = opcode;
                   1139:        buf[1] = opcode >> 8;
                   1140:        buf[2] = opcode >> 16;
                   1141:        buf[3] = opcode >> 24;
                   1142: #else
                   1143:        buf[3] = opcode;
                   1144:        buf[2] = opcode >> 8;
                   1145:        buf[1] = opcode >> 16;
                   1146:        buf[0] = opcode >> 24;
                   1147: #endif
                   1148:        return;
                   1149: }
                   1150: 
                   1151: /* should never be called for i860 */
                   1152: void
                   1153: md_convert_frag(
                   1154: fragS *fragP)
                   1155: {
                   1156:     fprintf(stderr, "i860_convert_frag\n");
                   1157:     abort();
                   1158: }
                   1159: 
                   1160: /* should never be called for i860 */
                   1161: int
                   1162: md_estimate_size_before_relax(
                   1163: fragS *fragP,
                   1164: int nsect)
                   1165: {
                   1166:     fprintf(stderr, "i860_estimate_size_before_relax\n");
                   1167:     abort();
                   1168:     return 0;
                   1169: }
                   1170: 
                   1171: #ifdef I860_DEBUG
                   1172: /* for debugging only */
                   1173: static void
                   1174: print_insn(
                   1175: struct i860_it *insn)
                   1176: {
                   1177:     char *Reloc[] = {
                   1178:     "RELOC_8",
                   1179:     "RELOC_16",
                   1180:     "RELOC_32",
                   1181:     "RELOC_DISP8",
                   1182:     "RELOC_DISP16",
                   1183:     "RELOC_DISP32",
                   1184:     "RELOC_WDISP30",
                   1185:     "RELOC_WDISP22",
                   1186:     "RELOC_HI22",
                   1187:     "RELOC_22",
                   1188:     "RELOC_13",
                   1189:     "RELOC_LO10",
                   1190:     "RELOC_SFA_BASE",
                   1191:     "RELOC_SFA_OFF13",
                   1192:     "RELOC_BASE10",
                   1193:     "RELOC_BASE13",
                   1194:     "RELOC_BASE22",
                   1195:     "RELOC_PC10",
                   1196:     "RELOC_PC22",
                   1197:     "RELOC_JMP_TBL",
                   1198:     "RELOC_SEGOFF16",
                   1199:     "RELOC_GLOB_DAT",
                   1200:     "RELOC_JMP_SLOT",
                   1201:     "RELOC_RELATIVE",
                   1202:     "NO_RELOC"
                   1203:     };
                   1204: 
                   1205:     if (insn->error) {
                   1206:        fprintf(stderr, "ERROR: %s\n");
                   1207:     }
                   1208:     fprintf(stderr, "opcode=0x%08x\n", insn->opcode);
                   1209:     fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);
                   1210:     fprintf(stderr, "exp =  {\n");
                   1211:     fprintf(stderr, "\t\tX_add_symbol = %s\n",
                   1212:        insn->exp.X_add_symbol ?
                   1213:        (insn->exp.X_add_symbol->sy_name ? 
                   1214:        insn->exp.X_add_symbol->sy_name : "???") : "0");
                   1215:     fprintf(stderr, "\t\tX_sub_symbol = %s\n",
                   1216:        insn->exp.X_subtract_symbol ?
                   1217:            (insn->exp.X_subtract_symbol->sy_name ? 
                   1218:                insn->exp.X_subtract_symbol->sy_name : "???") : "0");
                   1219:     fprintf(stderr, "\t\tX_add_number = %d\n",
                   1220:        insn->exp.X_add_number);
                   1221:     fprintf(stderr, "}\n");
                   1222:     return;
                   1223: }
                   1224: #endif /* I860_DEBUG */
                   1225: 
                   1226: int
                   1227: md_parse_option(
                   1228: char **argP,
                   1229: int *cntP,
                   1230: char ***vecP)
                   1231: {
                   1232:     return 1;
                   1233: }
                   1234: 

unix.superglobalmegacorp.com

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