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

1.1       root        1: #include <ctype.h>
                      2: #include <string.h>
                      3: #include <mach-o/m98k/reloc.h>
                      4: #include "m98k-opcode.h"
                      5: #include "as.h"
                      6: #include "flonum.h"
                      7: #include "expr.h"
                      8: #include "hash.h"
                      9: #include "read.h"
                     10: #include "md.h"
                     11: #include "obstack.h"
                     12: #include "symbols.h"
                     13: #include "messages.h"
                     14: #include "atof-ieee.h"
                     15: #include "input-scrub.h"
                     16: #include "sections.h"
                     17: 
                     18: 
                     19: /*
                     20:  * These are the default cputype and cpusubtype for the m98k architecture.
                     21:  */
                     22: const cpu_type_t md_cputype = CPU_TYPE_MC98000;
                     23: cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_MC98000_ALL;
                     24: 
                     25: /* This is the byte sex for the m98k architecture */
                     26: const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX;
                     27: 
                     28: /* These characters start a comment anywhere on the line */
                     29: const char md_comment_chars[] = ";";
                     30: 
                     31: /* These characters only start a comment at the beginning of a line */
                     32: const char md_line_comment_chars[] = "#";
                     33: 
                     34: /*
                     35:  * These characters can be used to separate mantissa decimal digits from 
                     36:  * exponent decimal digits in floating point numbers.
                     37:  */
                     38: const char md_EXP_CHARS[] = "eE";
                     39: 
                     40: /*
                     41:  * The characters after a leading 0 that means this number is a floating point
                     42:  * constant as in 0f123.456 or 0d1.234E-12 (see md_EXP_CHARS above).
                     43:  */
                     44: const char md_FLT_CHARS[] = "dDfF";
                     45: 
                     46: /*
                     47:  * This is the machine dependent pseudo opcode table for this target machine.
                     48:  */
                     49: static void s_reg(
                     50:     int reg);
                     51: const pseudo_typeS md_pseudo_table[] =
                     52: {
                     53:     {"greg", s_reg, 'r' },
                     54:     {0} /* end of table marker */
                     55: };
                     56: 
                     57: #define RT(x)           (((x) >> 21) & 0x1f)
                     58: #define RA(x)           (((x) >> 16) & 0x1f)
                     59: 
                     60: struct m98k_insn {
                     61:     unsigned long opcode;
                     62:     expressionS exp;
                     63:     enum reloc_type_m98k reloc;
                     64:     long pcrel;
                     65:     long pcrel_reloc;
                     66: };
                     67: 
                     68: /*
                     69:  * The pointer to the opcode hash table built by md_begin() and used by
                     70:  * md_assemble() to look up opcodes.
                     71:  */
                     72: static struct hash_control *op_hash = NULL;
                     73: 
                     74: /*
                     75:  * These aid in the printing of better error messages for parameter syntax
                     76:  * errors when there is only one mnemonic in the tables.
                     77:  */
                     78: static unsigned long error_param_count = 0;
                     79: static char *error_param_message = NULL;
                     80: 
                     81: /*
                     82:  * These are name names of the known special registers and the numbers assigned
                     83:  * to them.
                     84:  */
                     85: struct special_register {
                     86:     unsigned long number;
                     87:     char *name;
                     88: };
                     89: static const struct special_register special_registers[] = {
                     90:     { 0,   "mq" }, /* 601 only */
                     91:     { 1,   "xer" },
                     92:     { 4,   "rtcu" },
                     93:     { 5,   "rtcl" },
                     94:     { 8,   "lr" },
                     95:     { 9,   "ctr" },
                     96:     { 18,  "dsisr" },
                     97:     { 19,  "dar" },
                     98:     { 22,  "dec" },
                     99:     { 25,  "sdr1" },
                    100:     { 26,  "srr0" },
                    101:     { 27,  "srr1" },
                    102:     { 272, "sprg0" },
                    103:     { 273, "sprg1" },
                    104:     { 274, "sprg2" },
                    105:     { 275, "sprg3" },
                    106:     { 280, "asr" },
                    107:     { 281, "rtcd" },
                    108:     { 282, "rtci" },
                    109:     { 287, "pvr" },
                    110:     { 528, "ibat0u" },
                    111:     { 529, "ibat0l" },
                    112:     { 530, "ibat1u" },
                    113:     { 531, "ibat1l" },
                    114:     { 532, "ibat2u" },
                    115:     { 533, "ibat2l" },
                    116:     { 534, "ibat3u" },
                    117:     { 535, "ibat3l" },
                    118:     { 528, "bat0u" }, /* 601 only */
                    119:     { 529, "bat0l" }, /* 601 only */
                    120:     { 530, "bat1u" }, /* 601 only */
                    121:     { 531, "bat1l" }, /* 601 only */
                    122:     { 532, "bat2u" }, /* 601 only */
                    123:     { 533, "bat2l" }, /* 601 only */
                    124:     { 534, "bat3u" }, /* 601 only */
                    125:     { 535, "bat3l" }, /* 601 only */
                    126:     { 536, "dbat0u" },
                    127:     { 537, "dbat0l" },
                    128:     { 538, "dbat1u" },
                    129:     { 539, "dbat1l" },
                    130:     { 540, "dbat2u" },
                    131:     { 541, "dbat2l" },
                    132:     { 542, "dbat3u" },
                    133:     { 543, "dbat3l" },
                    134:     { 1008,"hid0" }, /* 601 only */
                    135:     { 1009,"hid1" }, /* 601 only */
                    136:     { 1010,"hid2" }, /* 601 only */
                    137:     { 1013,"hid5" }, /* 601 only */
                    138:     { 1013,"dabr" }, /* 601 only */
                    139:     { 1022,"fpecr" },
                    140:     { 1023,"pid" }, /* 601 only */
                    141:     { 0, "" } /* end of table marker */
                    142: };
                    143: 
                    144: /*
                    145:  * These are name names of the condition field special registers and the
                    146:  * numbers assigned to them.
                    147:  */
                    148: struct condition_symbol {
                    149:     unsigned long value;
                    150:     char *name;
                    151: };
                    152: static const struct condition_symbol condition_symbols[] = {
                    153:     { 0, "lt" }, /* less than */
                    154:     { 1, "gt" }, /* greater than */
                    155:     { 2, "eq" }, /* equal */
                    156:     { 3, "so" }, /* summary overflow */
                    157:     { 3, "un" }, /* unordered */
                    158:     { 0, "" } /* end of table marker */
                    159: };
                    160: 
                    161: struct CR_field {
                    162:     unsigned long value;
                    163:     char *name;
                    164: };
                    165: static const struct CR_field CR_fields[] = {
                    166:     { 0,  "cr0" }, /* CR field 0 */
                    167:     { 4,  "cr1" }, /* CR field 1 */
                    168:     { 8,  "cr2" }, /* CR field 2 */
                    169:     { 12, "cr3" }, /* CR field 3 */
                    170:     { 16, "cr4" }, /* CR field 4 */
                    171:     { 20, "cr5" }, /* CR field 5 */
                    172:     { 24, "cr6" }, /* CR field 6 */
                    173:     { 28, "cr7" }, /* CR field 7 */
                    174:     { 0, "" } /* end of table marker */
                    175: };
                    176: 
                    177: /*
                    178:  * These are built in macros because they are trivial to implement as macros
                    179:  * which otherwise be less obvious to do special entries for them.
                    180:  */
                    181: struct macros {
                    182:     char *name;
                    183:     char *body;
                    184: };
                    185: static const struct macros m98k_macros[] = {
                    186:     { "extldi\n",  "rldicr $0,$1,$3,$2-1\n" },
                    187:     { "extldi.\n", "rldicr. $0,$1,$3,$2-1\n" },
                    188:     { "extrdi\n",  "rldicl $0,$1,$2+$3,64-$2\n" },
                    189:     { "extrdi.\n", "rldicl. $0,$1,$2+$3,64-$2\n" },
                    190:     { "insrdi\n",  "rldimi $0,$1,64-($3+$2),$3\n" },
                    191:     { "insrdi.\n", "rldimi. $0,$1,64-($3+$2),$3\n" },
                    192:     { "rotldi\n",  "rldicl $0,$1,$2,0\n" },
                    193:     { "rotldi.\n", "rldicl. $0,$1,$2,0\n" },
                    194:     { "rotrdi\n",  "rldicl $0,$1,64-$2,0\n" },
                    195:     { "rotrdi.\n", "rldicl. $0,$1,64-$2,0\n" },
                    196:     { "rotld\n",   "rldcl $0,$1,$2,0\n" },
                    197:     { "rotld.\n",  "rldcl. $0,$1,$2,0\n" },
                    198:     { "sldi\n",    "rldicr $0,$1,$2,63-$2\n" },
                    199:     { "sldi.\n",   "rldicr. $0,$1,$2,63-$2\n" },
                    200:     { "srdi\n",    "rldicl $0,$1,64-$2,$2\n" },
                    201:     { "srdi.\n",   "rldicl. $0,$1,64-$2,$2\n" },
                    202:     { "clrldi\n",  "rldicl $0,$1,0,$2\n" },
                    203:     { "clrldi.\n", "rldicl. $0,$1,0,$2\n" },
                    204:     { "clrrdi\n",  "rldicl $0,$1,0,63-$2\n" },
                    205:     { "clrrdi.\n", "rldicl. $0,$1,0,63-$2\n" },
                    206:     { "clrlsldi\n","rldic $0,$1,$3,$2-$3\n" },
                    207:     { "clrlsldi.\n","rldic. $0,$1,$3,$2-$3\n" },
                    208: 
                    209:     { "extlwi\n",  "rlwinm $0,$1,$3,0,$2-1\n" },
                    210:     { "extlwi.\n", "rlwinm. $0,$1,$3,0,$2-1\n" },
                    211:     { "extrwi\n",  "rlwinm $0,$1,$2+$3,32-$2,31\n" },
                    212:     { "extrwi.\n", "rlwinm. $0,$1,$2+$3,32-$2,31\n" },
                    213:     { "inslwi\n",  "rlwimi $0,$1,32-$3,$3,($3+$2)-1\n" },
                    214:     { "inslwi.\n", "rlwimi. $0,$1,32-$3,$3,($3+$2)-1\n" },
                    215:     { "insrwi\n",  "rlwimi $0,$1,32-($3+$2),$3,($3+$2)-1\n" },
                    216:     { "insrwi.\n", "rlwimi. $0,$1,32-($3+$2),$3,($3+$2)-1\n" },
                    217:     { "rotlwi\n",  "rlwinm $0,$1,$2,0,31\n" },
                    218:     { "rotlwi.\n", "rlwinm. $0,$1,$2,0,31\n" },
                    219:     { "rotrwi\n",  "rlwinm $0,$1,32-$2,0,31\n" },
                    220:     { "rotrwi.\n", "rlwinm. $0,$1,32-$2,0,31\n" },
                    221:     { "rotlw\n",   "rlwnm $0,$1,$2,0,31\n" },
                    222:     { "rotlw.\n",  "rlwnm. $0,$1,$2,0,31\n" },
                    223:     { "slwi\n",    "rlwinm $0,$1,$2,0,31-$2\n" },
                    224:     { "slwi.\n",   "rlwinm. $0,$1,$2,0,31-$2\n" },
                    225:     { "srwi\n",    "rlwinm $0,$1,32-$2,$2,31\n" },
                    226:     { "srwi.\n",   "rlwinm. $0,$1,32-$2,$2,31\n" },
                    227:     { "clrlwi\n",  "rlwinm $0,$1,0,$2,31\n" },
                    228:     { "clrlwi.\n", "rlwinm. $0,$1,0,$2,31\n" },
                    229:     { "clrrwi\n",  "rlwinm $0,$1,0,0,31-$2\n" },
                    230:     { "clrrwi.\n", "rlwinm. $0,$1,0,0,31-$2\n" },
                    231:     { "clrlslwi\n","rlwinm $0,$1,$3,$2-$3,31-$2\n" },
                    232:     { "clrlslwi.\n","rlwinm. $0,$1,$3,$2-$3,31-$2\n" },
                    233: 
                    234:     { "mtxer\n",   "mtspr 1,$0\n"},
                    235:     { "mfxer\n",   "mfspr $0,1\n"},
                    236:     { "mtlr\n",    "mtspr 8,$0\n"},
                    237:     { "mflr\n",    "mfspr $0,8\n"},
                    238:     { "mtctr\n",   "mtspr 9,$0\n"},
                    239:     { "mfctr\n",   "mfspr $0,9\n"},
                    240:     { "mtdsisr\n", "mtspr 18,$0\n"},
                    241:     { "mfdsisr\n", "mfspr $0,18\n"},
                    242:     { "mtdar\n",   "mtspr 19,$0\n"},
                    243:     { "mfdar\n",   "mfspr $0,19\n"},
                    244:     { "mtdec\n",   "mtspr 22,$0\n"},
                    245:     { "mfdec\n",   "mfspr $0,22\n"},
                    246:     { "mtsdr1\n",  "mtspr 25,$0\n"},
                    247:     { "mfsdr1\n",  "mfspr $0,25\n"},
                    248:     { "mtsrr0\n",  "mtspr 26,$0\n"},
                    249:     { "mfsrr0\n",  "mfspr $0,26\n"},
                    250:     { "mtsrr1\n",  "mtspr 27,$0\n"},
                    251:     { "mfsrr1\n",  "mfspr $0,27\n"},
                    252:     { "mtsprg\n",  "mtspr 272+$0,$1\n"},
                    253:     { "mfsprg\n",  "mfspr $0,272+$1\n"},
                    254:     { "mtasr\n",   "mtspr 280,$0\n"},
                    255:     { "mfasr\n",   "mfspr $0,280\n"},
                    256:     { "mtrtcd\n",  "mtspr 281,$0\n"},
                    257:     { "mfrtcd\n",  "mfspr $0,281\n"},
                    258:     { "mtrtci\n",  "mtspr 282,$0\n"},
                    259:     { "mfrtci\n",  "mfspr $0,282\n"},
                    260:     { "mfpvr\n",   "mfspr $0,287\n"},
                    261:     { "mtibatu\n", "mtspr 528+2*$0,$1\n"},
                    262:     { "mfibatu\n", "mfspr $0,528+2*$1\n"},
                    263:     { "mtibatl\n", "mtspr 529+2*$0,$1\n"},
                    264:     { "mfibatl\n", "mfspr $0,529+2*$1\n"},
                    265:     { "mtdbatu\n", "mtspr 536+2*$0,$1\n"},
                    266:     { "mfdbatu\n", "mfspr $0,536+2*$1\n"},
                    267:     { "mtdbatl\n", "mtspr 537+2*$0,$1\n"},
                    268:     { "mfdbatl\n", "mfspr $0,537+2*$1\n"},
                    269: 
                    270:     { "mtbatu\n",  "mtspr 528+2*$0,$1\n"},
                    271:     { "mfbatu\n",  "mfspr $0,528+2*$1\n"},
                    272:     { "mtbatl\n",  "mtspr 529+2*$0,$1\n"},
                    273:     { "mfbatl\n",  "mfspr $0,529+2*$1\n"},
                    274: 
                    275:     { "subi\n",    "addi $0,$1,-($2)\n"},
                    276:     { "subis\n",   "addis $0,$1,-($2)\n"},
                    277:     { "subic\n",   "addic $0,$1,-($2)\n"},
                    278:     { "subic.\n",  "addic. $0,$1,-($2)\n"},
                    279: 
                    280:     {  "", "" } /* end of table marker */
                    281: };
                    282: 
                    283: static int calcop(
                    284:     struct m98k_opcode *format,
                    285:     char *param,
                    286:     struct m98k_insn *insn,
                    287:     char *op,
                    288:     char prediction);
                    289: static char *parse_branch(
                    290:     char *param,
                    291:     struct m98k_insn *insn,
                    292:     struct m98k_opcode *format,
                    293:     int parcnt);
                    294: static char *parse_displacement(
                    295:     char *param,
                    296:     struct m98k_insn *insn,
                    297:     struct m98k_opcode *format,
                    298:     int parcnt);
                    299: static char *parse_immediate(
                    300:     char *param,
                    301:     struct m98k_insn *insn,
                    302:     struct m98k_opcode *format,
                    303:     int parcnt);
                    304: static char *parse_reg(
                    305:     char *reg_name,
                    306:     char *param,
                    307:     struct m98k_insn *insn,
                    308:     struct m98k_opcode *format,
                    309:     unsigned long parcnt);
                    310: static char *parse_spreg(
                    311:     char *param,
                    312:     struct m98k_insn *insn,
                    313:     struct m98k_opcode *format,
                    314:     unsigned long parcnt);
                    315: static char *parse_bcnd(
                    316:     char *param,
                    317:     struct m98k_insn *insn,
                    318:     struct m98k_opcode *format,
                    319:     unsigned long parcnt);
                    320: static char *parse_crf(
                    321:     char *param,
                    322:     struct m98k_insn *insn,
                    323:     struct m98k_opcode *format,
                    324:     unsigned long parcnt);
                    325: static char *parse_num(
                    326:     char *param,
                    327:     struct m98k_insn *insn,
                    328:     struct m98k_opcode *format,
                    329:     unsigned long parcnt,
                    330:     long max_width_zero);
                    331: static char *parse_sh(
                    332:     char *param,
                    333:     struct m98k_insn *insn,
                    334:     struct m98k_opcode *format,
                    335:     unsigned long parcnt);
                    336: static char *parse_mb(
                    337:     char *param,
                    338:     struct m98k_insn *insn,
                    339:     struct m98k_opcode *format,
                    340:     unsigned long parcnt);
                    341: 
                    342: /*
                    343:  * md_begin() is called from main() in as.c before assembly begins.  It is used
                    344:  * to allow target machine dependent initialization.
                    345:  */
                    346: void
                    347: md_begin(void)
                    348: {
                    349:     unsigned long i;
                    350:     char *name, *retval;
                    351: 
                    352:        /* initialize the opcode hash table */
                    353:        op_hash = hash_new();
                    354:        if(op_hash == NULL)
                    355:            as_fatal("Could not initialize the opcode hash table");
                    356: 
                    357:        /* loop until you see the end of the list */
                    358:        i = 0;
                    359:        while(*m98k_opcodes[i].name){
                    360:            name = m98k_opcodes[i].name;
                    361: 
                    362:            /* hash each mnemonic and record its position */
                    363:            retval = hash_insert(op_hash, name, (char *)&m98k_opcodes[i]);
                    364:            if(retval != NULL && *retval != '\0')
                    365:                as_fatal("Can't hash instruction '%s':%s",
                    366:                         m98k_opcodes[i].name, retval);
                    367: 
                    368:            /* skip to next unique mnemonic or end of list */
                    369:            for(i++; strcmp(m98k_opcodes[i].name, name) == 0; i++)
                    370:                ;
                    371:        }
                    372: 
                    373:        /*
                    374:         * Load the builtin macros for extended mnemonics for rotate and
                    375:         * shift mnemonics.
                    376:         */
                    377:        for(i = 0; *m98k_macros[i].name != '\0'; i++){
                    378:            input_line_pointer = m98k_macros[i].name;
                    379:            s_macro(0);
                    380:            add_to_macro_definition(m98k_macros[i].body);
                    381:            s_endmacro(0);
                    382:        }
                    383: }
                    384: 
                    385: /*
                    386:  * md_end() is called from main() in as.c after assembly ends.  It is used
                    387:  * to allow target machine dependent clean up.
                    388:  */
                    389: void
                    390: md_end(void)
                    391: {
                    392: }
                    393: 
                    394: /*
                    395:  * md_parse_option() is called from main() in as.c to parse target machine
                    396:  * dependent command line options.  This routine returns 0 if it is passed an
                    397:  * option that is not recognized non-zero otherwise.
                    398:  */
                    399: int
                    400: md_parse_option(
                    401: char **argP,
                    402: int *cntP,
                    403: char ***vecP)
                    404: {
                    405:        return(0);
                    406: }
                    407: 
                    408: /*
                    409:  * s_reg() is used to implement ".greg symbol,exp" and ".xreg symbol,exp"
                    410:  * which set symbol to 1 or 0 depending on if the expression is a general
                    411:  * register or extended register respectfully.  These are intended for use in
                    412:  * macros.
                    413:  */
                    414: static
                    415: void
                    416: s_reg(
                    417: int reg)
                    418: {
                    419:        char *name, *end_name, delim;
                    420:        symbolS *symbolP;
                    421:        unsigned long n_value, val;
                    422: 
                    423:        if( * input_line_pointer == '"')
                    424:          name = input_line_pointer + 1;
                    425:        else
                    426:          name = input_line_pointer;
                    427:        delim = get_symbol_end();
                    428:        end_name = input_line_pointer;
                    429:        *end_name = delim;
                    430:        SKIP_WHITESPACE();
                    431:        if ( * input_line_pointer != ',' ) {
                    432:                *end_name = 0;
                    433:                as_warn("Expected comma after name \"%s\"", name);
                    434:                *end_name = delim;
                    435:                ignore_rest_of_line();
                    436:                return;
                    437:        }
                    438:        input_line_pointer ++;
                    439:        *end_name = 0;
                    440: 
                    441:        SKIP_WHITESPACE();
                    442:        n_value = 0;
                    443:        if (*input_line_pointer == reg || *input_line_pointer == toupper(reg)){
                    444:            input_line_pointer++;
                    445:            if(isdigit(*input_line_pointer)){
                    446:                val = 0;
                    447:                while (isdigit(*input_line_pointer)){
                    448:                    if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
                    449:                        break;
                    450:                }
                    451:                SKIP_WHITESPACE();
                    452:                if(val <= 31 &&
                    453:                   (*input_line_pointer == '\n' || *input_line_pointer == '@'))
                    454:                    n_value = 1;
                    455:            }
                    456:        }
                    457: 
                    458:        symbolP = symbol_find_or_make (name);
                    459:        symbolP -> sy_type = N_ABS;
                    460:        symbolP -> sy_other = 0; /* NO_SECT */
                    461:        symbolP -> sy_value = n_value;
                    462:        symbolP -> sy_frag = & zero_address_frag;
                    463: 
                    464:        *end_name = delim;
                    465:        totally_ignore_line();
                    466: }
                    467: 
                    468: /*
                    469:  * md_assemble() is passed a pointer to a string that should be a assembly
                    470:  * statement for the target machine.
                    471:  */
                    472: void
                    473: md_assemble(
                    474: char *op)
                    475: {
                    476:     char *param, *thisfrag, prediction;
                    477:     struct m98k_opcode *format;
                    478:     struct m98k_insn insn;
                    479:     unsigned long retry;
                    480: 
                    481:        /*
                    482:         * Pick up the instruction and any trailing branch prediction character
                    483:         * (a trailing '+' or '-' on the instruction).
                    484:         */
                    485:        prediction = '\0';
                    486:        for(param = op; !isspace(*param) && *param != '\0' ; param++)
                    487:            prediction = *param;
                    488:        if(prediction == '+' || prediction == '-')
                    489:            param[-1] = '\0';
                    490:        else
                    491:            prediction = '\0';
                    492:        if(*param != '\0')
                    493:            *param++ = '\0';
                    494: 
                    495:        /* try to find the instruction in the hash table */
                    496:        if((format = (struct m98k_opcode *)hash_find(op_hash, op)) == NULL){
                    497:            as_warn("Invalid mnemonic '%s'", op);
                    498:            return;
                    499:        }
                    500: 
                    501:        /* try parsing this instruction into insn */
                    502:        retry = 0;
                    503:        error_param_count = 0;
                    504:        error_param_message = NULL;
                    505:        while(calcop(format, param, &insn, op, prediction) == 0){
                    506:            /* if it doesn't parse try the next instruction */
                    507:            if(strcmp(format->name, format[1].name) == 0){
                    508:                format++;
                    509:                retry = 1;
                    510:            }
                    511:            else{
                    512:                if(retry == 0){
                    513:                    if(error_param_message != NULL)
                    514:                        as_warn(error_param_message, error_param_count + 1);
                    515:                    else
                    516:                        as_warn("Parameter syntax error (parameter %lu)",
                    517:                                error_param_count + 1);
                    518:                }
                    519:                else
                    520:                    as_warn("Parameter syntax error");
                    521:                return;
                    522:            }
                    523:        }
                    524: 
                    525:        /*
                    526:         * Check for invalid forms of instructions.  For the following
                    527:         * instructions: lbzu, lbzux, lhzu, lhzux, lhau, lhaux, lwzu, lwzux,
                    528:         * lwaux, ldu, ldux
                    529:         * if RA == 0 or RA == RT the instruction form is invalid.
                    530:         */
                    531:        if((insn.opcode & 0xfc000000) == 0x8c000000 || /* lbzu */
                    532:           (insn.opcode & 0xfc0007fe) == 0x7c0000ee || /* lbzux */
                    533:           (insn.opcode & 0xfc000000) == 0xa4000000 || /* lhzu */
                    534:           (insn.opcode & 0xfc0007fe) == 0x7c00026e || /* lbzux */
                    535:           (insn.opcode & 0xfc000000) == 0xac000000 || /* lhau */
                    536:           (insn.opcode & 0xfc0007fe) == 0x7c0002ee || /* lhaux */
                    537:           (insn.opcode & 0xfc000000) == 0x84000000 || /* lwzu */
                    538:           (insn.opcode & 0xfc0007fe) == 0x7c00006e || /* lwzux */
                    539:           (insn.opcode & 0xfc0007fe) == 0x7c0002ea || /* lwaux */
                    540:           (insn.opcode & 0xfc000000) == 0xe8000000 || /* ldu */
                    541:           (insn.opcode & 0xfc0007fe) == 0x7c00006a){  /* ldux */
                    542:            if(RA(insn.opcode) == 0)
                    543:                as_warn("Invalid form of the instruction (RA must not be 0)");
                    544:            if(RA(insn.opcode) == RT(insn.opcode))
                    545:                as_warn("Invalid form of the instruction (RA must not the same "
                    546:                        "as RT)");
                    547:        }
                    548:        /*
                    549:         * For the following instructions: stbu, stbux, sthu, sthux, stwu,
                    550:         * stwux, stdu, stdux, lfsu, lfsux, lfdu, lfdux, stfsu, stfsux, stfdu,
                    551:         * stfdux
                    552:         * if RA == 0 the instruction form is invalid.
                    553:         */
                    554:        if((insn.opcode & 0xfc000000) == 0x9c000000 || /* stbu */
                    555:           (insn.opcode & 0xfc0007fe) == 0x7c0001ee || /* stbux */
                    556:           (insn.opcode & 0xfc000000) == 0xb4000000 || /* sthu */
                    557:           (insn.opcode & 0xfc0007fe) == 0x7c00036e || /* sthux */
                    558:           (insn.opcode & 0xfc000000) == 0x94000000 || /* stwu */
                    559:           (insn.opcode & 0xfc0007fe) == 0x7c00016e || /* stwux */
                    560:           (insn.opcode & 0xfc000003) == 0xf8000001 || /* stdu */
                    561:           (insn.opcode & 0xfc0007fe) == 0x7c00016a || /* stdux */
                    562:           (insn.opcode & 0xfc000000) == 0xc4000000 || /* lfsu */
                    563:           (insn.opcode & 0xfc0007fe) == 0x7c00046e || /* lfsux */
                    564:           (insn.opcode & 0xfc000000) == 0xcc000000 || /* lfdu */
                    565:           (insn.opcode & 0xfc0007fe) == 0x7c0004ee || /* lfdux */
                    566:           (insn.opcode & 0xfc000000) == 0xd4000000 || /* stfsu */
                    567:           (insn.opcode & 0xfc0007fe) == 0x7c00056e || /* stfsux */
                    568:           (insn.opcode & 0xfc000000) == 0xdc000000 || /* stfdu */
                    569:           (insn.opcode & 0xfc0007fe) == 0x7c0005ee){  /* stfdux */
                    570:            if(RA(insn.opcode) == 0)
                    571:                as_warn("Invalid form of the instruction (RA must not be 0)");
                    572:        }
                    573:        /*
                    574:         * For the following instructions: lmw, lmd, lswi, lswx
                    575:         * if RA is in the range of registers to be loaded or RT == RA == 0
                    576:         * the instruction form is invalid.  WHAT does this mean?
                    577:         */
                    578:        if((insn.opcode & 0xfc000000) == 0xb8000000 || /* lmw */
                    579:           (insn.opcode & 0xfc000003) == 0xe8000003 || /* lmw */
                    580:           (insn.opcode & 0xfc0007fe) == 0x7c0004aa || /* lswi */
                    581:           (insn.opcode & 0xfc0007fe) == 0x7c00042a){  /* lswx */
                    582:        }
                    583: 
                    584:        /* grow the current frag and plop in the opcode */
                    585:        thisfrag = frag_more(4);
                    586:        md_number_to_chars(thisfrag, insn.opcode, 4);
                    587: 
                    588:        /*
                    589:         * If the -g flag is present generate a line number stab for the
                    590:         * instruction.
                    591:         * 
                    592:         * See the detailed comments about stabs in read_a_source_file() for a
                    593:         * description of what is going on here.
                    594:         */
                    595:        if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){
                    596:            (void)symbol_new(
                    597:                  "",
                    598:                  68 /* N_SLINE */,
                    599:                  text_nsect,
                    600:                  logical_input_line /* n_desc, line number */,
                    601:                  obstack_next_free(&frags) - frag_now->fr_literal,
                    602:                  frag_now);
                    603:        }
                    604: 
                    605:        /* if this instruction requires labels mark it for later */
                    606:        switch(insn.reloc){
                    607:        case NO_RELOC:
                    608:            break;
                    609:        case M98K_RELOC_HI16:
                    610:        case M98K_RELOC_LO16:
                    611:        case M98K_RELOC_HA16:
                    612:        case M98K_RELOC_LO14:
                    613:            fix_new(frag_now,
                    614:                    thisfrag - frag_now->fr_literal,
                    615:                    4,
                    616:                    insn.exp.X_add_symbol,
                    617:                    insn.exp.X_subtract_symbol,
                    618:                    insn.exp.X_add_number,
                    619:                    0, 0,
                    620:                    insn.reloc);
                    621:            break;
                    622:        case M98K_RELOC_BR14:
                    623:            fix_new(frag_now,
                    624:                    thisfrag - frag_now->fr_literal,
                    625:                    4,
                    626:                    insn.exp.X_add_symbol,
                    627:                    insn.exp.X_subtract_symbol,
                    628:                    insn.exp.X_add_number,
                    629:                    insn.pcrel,
                    630:                    insn.pcrel_reloc,
                    631:                    insn.reloc);
                    632:            break;
                    633: 
                    634:        case M98K_RELOC_BR24:
                    635:            fix_new(frag_now,
                    636:                    thisfrag - frag_now->fr_literal,
                    637:                    4,
                    638:                    insn.exp.X_add_symbol,
                    639:                    insn.exp.X_subtract_symbol,
                    640:                    insn.exp.X_add_number,
                    641:                    insn.pcrel,
                    642:                    insn.pcrel_reloc,
                    643:                    insn.reloc);
                    644:            break;
                    645:        default:
                    646:            as_warn("Unknown relocation type");
                    647:            break;
                    648:        }
                    649: }
                    650: 
                    651: static
                    652: int
                    653: calcop(
                    654: struct m98k_opcode *format,
                    655: char *param,
                    656: struct m98k_insn *insn,
                    657: char *op,
                    658: char prediction)
                    659: {
                    660:     unsigned long parcnt;
                    661: 
                    662:        /* initial the passed structure */
                    663:        memset(insn, '\0', sizeof(struct m98k_insn));
                    664:        insn->opcode = format->opcode;
                    665:        insn->reloc = NO_RELOC;
                    666: 
                    667:        /* parse all parameters */
                    668:        for(parcnt = 0; parcnt < 5 &&
                    669:                        format->ops[parcnt].type != NONE; parcnt++){
                    670:            error_param_count = parcnt;
                    671: 
                    672:            switch(format->ops[parcnt].type){
                    673:            case PCREL:
                    674:            case BADDR:
                    675:                param = parse_branch(param, insn, format, parcnt);
                    676:                break;
                    677:            case D:
                    678:            case DS:
                    679:                param = parse_displacement(param, insn, format, parcnt);
                    680:                break;
                    681:            case SI:
                    682:            case UI:
                    683:                param = parse_immediate(param, insn, format, parcnt);
                    684:                break;
                    685:            case GREG:
                    686:            case G0REG:
                    687:                param = parse_reg("r", param, insn, format, parcnt);
                    688:                break;
                    689:            case FREG:
                    690:                param = parse_reg("f", param, insn, format, parcnt);
                    691:                break;
                    692:            case SGREG:
                    693:                param = parse_reg("sr", param, insn, format, parcnt);
                    694:                break;
                    695:            case SPREG:
                    696:                param = parse_spreg(param, insn, format, parcnt);
                    697:                break;
                    698:            case BCND:
                    699:                param = parse_bcnd(param, insn, format, parcnt);
                    700:                break;
                    701:            case CRF:
                    702:            case CRFONLY:
                    703:                param = parse_crf(param, insn, format, parcnt);
                    704:                break;
                    705:            case NUM:
                    706:                param = parse_num(param, insn, format, parcnt, 0);
                    707:                break;
                    708:            case NUM0:
                    709:                param = parse_num(param, insn, format, parcnt, 1);
                    710:                break;
                    711:            case sh:
                    712:                param = parse_sh(param, insn, format, parcnt);
                    713:                break;
                    714:            case mb:
                    715:                param = parse_mb(param, insn, format, parcnt);
                    716:                break;
                    717:            default:
                    718:                as_fatal("Unknown parameter type");
                    719:            }
                    720: 
                    721:            /* see if parser failed or not */
                    722:            if (param == NULL)
                    723:                return(0);
                    724:        }
                    725:        if(format->ops[0].type == NONE && *param != '\0'){
                    726:            error_param_message = "too many parameters";
                    727:            return(0);
                    728:        }
                    729: 
                    730:        if(IS_BRANCH_CONDITIONAL(insn->opcode)){
                    731:            if(prediction != '\0'){
                    732:                /*
                    733:                 * Set the Y_BIT assuming the displacement is non-negitive.
                    734:                 * If the displacement is negitive then the Y_BIT is flipped
                    735:                 * in md_number_to_imm().
                    736:                 */
                    737:                if(prediction == '+')
                    738:                    insn->opcode |= Y_BIT;
                    739:                else{ /* prediction == '-' */
                    740:                    if((insn->opcode & Y_BIT) != 0)
                    741:                        as_warn("branch prediction ('-') ignored (specified "
                    742:                                "operand has prediction bit set)");
                    743:                    else
                    744:                        insn->opcode &= ~(Y_BIT);
                    745:                }
                    746:            }
                    747:        }
                    748:        else{
                    749:            if(prediction != '\0')
                    750:                as_warn("branch prediction ignored (instruction is not a "
                    751:                        "conditional branch)");
                    752:        }
                    753:        return(1);
                    754: }
                    755: 
                    756: static
                    757: char *
                    758: parse_displacement(
                    759: char *param,
                    760: struct m98k_insn *insn,
                    761: struct m98k_opcode *format,
                    762: int parcnt)
                    763: {
                    764:     unsigned long val;
                    765:     char *end, *saveptr, *saveparam;
                    766:     segT seg;
                    767: 
                    768: 
                    769:        if(parcnt != 1 || format->ops[2].type != G0REG)
                    770:             as_fatal("internal error, bad table entry for instruction %s "
                    771:                      "(displacement operand not second operand or general "
                    772:                      "register not third operand)", format->name);
                    773: 
                    774:        /*
                    775:         * There must be "(rX)" (where X is a number between 0-31) or "(0)"
                    776:         * at the end of the parameter string.  To know out where the
                    777:         * displacement expression ends determine the begining the "(rX)"
                    778:         * by looking for the last '(' in the string.  The parsing of this
                    779:         * trailing string will be done in another routine.
                    780:         */
                    781:        end = strrchr(param, '(');
                    782:        if(end == NULL)
                    783:            return(NULL);
                    784:        *end = '\0';
                    785: 
                    786:        /*
                    787:         * The expression may have one of the following: hi16(exp), ha16(exp),
                    788:         * or lo16(exp) around the expression which determines the relocation
                    789:         * type.
                    790:         */
                    791:        if(strncmp(param,"hi16(",5) == 0){
                    792:            insn->reloc = M98K_RELOC_HI16;
                    793:            param += 5;
                    794:        }
                    795:        else if(strncmp(param,"ha16(",5) == 0){
                    796:            insn->reloc = M98K_RELOC_HA16;
                    797:            param += 5;
                    798:        }
                    799:        else if(strncmp(param,"lo16(",5) == 0){
                    800:            if(format->ops[parcnt].type == DS)
                    801:                insn->reloc = M98K_RELOC_LO14;
                    802:            else
                    803:                insn->reloc = M98K_RELOC_LO16;
                    804:            param += 5;
                    805:        }
                    806: 
                    807:        saveptr = input_line_pointer;
                    808:        input_line_pointer = param;
                    809: 
                    810:        seg = expression(&insn->exp);
                    811:        try_to_make_absolute(&insn->exp);
                    812:        seg = insn->exp.X_seg;
                    813: 
                    814:        saveparam = input_line_pointer;
                    815:        input_line_pointer = saveptr;
                    816:        *end = '(';
                    817: 
                    818:        if(insn->reloc != NO_RELOC){
                    819:            if(*saveparam != ')' || ++saveparam != end)
                    820:                return(NULL);
                    821:        }
                    822:        else{
                    823:            if(saveparam != end)
                    824:                return(NULL);
                    825:            val = insn->exp.X_add_number;
                    826:            if(seg != SEG_ABSOLUTE){
                    827:                error_param_message = "Parameter error: expression must be "
                    828:                                      "absolute (parameter %lu)";
                    829:                return(NULL);
                    830:            }
                    831:            if(val & 0x8000){
                    832:                if((val & 0xffff0000) != 0xffff0000){
                    833:                    error_param_message = "Parameter error: expression out of "
                    834:                                          "range (parameter %lu)";
                    835:                    return(NULL);
                    836:                }
                    837:                val = val & 0xffff;
                    838:            }
                    839:            else{
                    840:                if((val & 0xffff0000) != 0){
                    841:                    error_param_message = "Parameter error: expression out of "
                    842:                                          "range (parameter %lu)";
                    843:                    return(NULL);
                    844:                }
                    845:            }
                    846:            if(format->ops[parcnt].type == DS){
                    847:                if((val & 0x3) != 0){
                    848:                    error_param_message = "Parameter error: expression must be "
                    849:                                          "a multiple of 4 (parameter %lu)";
                    850:                    return(NULL);
                    851:                }
                    852:                val >>= 2;
                    853:            }
                    854:            insn->opcode |= val << format->ops[parcnt].offset;
                    855:        }
                    856:        return(saveparam);
                    857: }
                    858: 
                    859: static
                    860: char *
                    861: parse_immediate(
                    862: char *param,
                    863: struct m98k_insn *insn,
                    864: struct m98k_opcode *format,
                    865: int parcnt)
                    866: {
                    867:     unsigned long val;
                    868:     char *saveptr, *saveparam;
                    869:     segT seg;
                    870: 
                    871:        /*
                    872:         * The expression may have one of the following: hi16(exp), ha16(exp),
                    873:         * or lo16(exp) around the expression which determines the relocation
                    874:         * type.
                    875:         */
                    876:        if(strncmp(param,"hi16(",5) == 0){
                    877:            insn->reloc = M98K_RELOC_HI16;
                    878:            param += 5;
                    879:        }
                    880:        else if(strncmp(param,"ha16(",5) == 0){
                    881:            insn->reloc = M98K_RELOC_HA16;
                    882:            param += 5;
                    883:        }
                    884:        else if(strncmp(param,"lo16(",5) == 0){
                    885:            if(format->ops[parcnt].type == DS)
                    886:                insn->reloc = M98K_RELOC_LO14;
                    887:            else
                    888:                insn->reloc = M98K_RELOC_LO16;
                    889:            param += 5;
                    890:        }
                    891: 
                    892:        saveptr = input_line_pointer;
                    893:        input_line_pointer = param;
                    894: 
                    895:        seg = expression(&insn->exp);
                    896:        try_to_make_absolute(&insn->exp);
                    897:        seg = insn->exp.X_seg;
                    898: 
                    899:        saveparam = input_line_pointer;
                    900:        input_line_pointer = saveptr;
                    901: 
                    902:        if(insn->reloc != NO_RELOC){
                    903:            if(*saveparam != ')')
                    904:                return(NULL);
                    905:            saveparam++;
                    906:            if(*saveparam == '\0'){
                    907:                if(parcnt == 4 || format->ops[parcnt+1].type == NONE)
                    908:                    return(saveparam);
                    909:                else
                    910:                    return(NULL);
                    911:            }
                    912:            else if(*saveparam == ','){
                    913:                if(parcnt != 4 && format->ops[parcnt+1].type != NONE)
                    914:                    return(saveparam+1);
                    915:                else
                    916:                    return(NULL);
                    917:            }
                    918:            else
                    919:                return(NULL);
                    920:        }
                    921:        else{
                    922:            val = insn->exp.X_add_number;
                    923:            if(seg != SEG_ABSOLUTE){
                    924:                error_param_message = "Parameter error: expression must be "
                    925:                                      "absolute (parameter %lu)";
                    926:                return(NULL);
                    927:            }
                    928:            if(format->ops[parcnt].type == SI){
                    929:                if(val & 0x8000){
                    930:                    if((val & 0xffff0000) != 0xffff0000){
                    931:                        error_param_message = "Parameter error: expression out "
                    932:                                              "of range (parameter %lu)";
                    933:                        return(NULL);
                    934:                    }
                    935:                    val = val & 0xffff;
                    936:                }
                    937:                else{
                    938:                    if((val & 0xffff0000) != 0){
                    939:                        error_param_message = "Parameter error: expression out "
                    940:                                              "of range (parameter %lu)";
                    941:                        return(NULL);
                    942:                    }
                    943:                }
                    944:            }
                    945:            else{
                    946:                if((val & 0xffff0000) != 0){
                    947:                    error_param_message = "Parameter error: expression out "
                    948:                                          "of range (parameter %lu)";
                    949:                    return(NULL);
                    950:                }
                    951:            }
                    952:            if(*saveparam == '\0'){
                    953:                if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
                    954:                    insn->opcode |= val << format->ops[parcnt].offset;
                    955:                    return(saveparam);
                    956:                }
                    957:                else
                    958:                    return(NULL);
                    959:            }
                    960:            else if(*saveparam == ','){
                    961:                if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
                    962:                    insn->opcode |= val << format->ops[parcnt].offset;
                    963:                    return(saveparam+1);
                    964:                }
                    965:                else
                    966:                    return(NULL);
                    967:            }
                    968:            else
                    969:                return(NULL);
                    970:        }
                    971:        return(saveparam);
                    972: }
                    973: 
                    974: static
                    975: char *
                    976: parse_branch(
                    977: char *param,
                    978: struct m98k_insn *insn,
                    979: struct m98k_opcode *format,
                    980: int parcnt)
                    981: {
                    982:     char *saveptr, *saveparam;
                    983:     segT seg;
                    984: 
                    985:        saveptr = input_line_pointer;
                    986:        input_line_pointer = param;
                    987: 
                    988:        seg = expression(&insn->exp);
                    989:        try_to_make_absolute(&insn->exp);
                    990:        seg = insn->exp.X_seg;
                    991: 
                    992:        saveparam = input_line_pointer;
                    993:        input_line_pointer = saveptr;
                    994: 
                    995:        insn->pcrel = 0;
                    996:        insn->pcrel_reloc = 0;
                    997:        if(format->ops[parcnt].type == PCREL){
                    998:            /*
                    999:             * The NeXT linker has the ability to scatter blocks of
                   1000:             * sections between labels.  This requires that brances to
                   1001:             * labels that survive to the link phase must be able to
                   1002:             * be relocated.
                   1003:             */
                   1004:            if(insn->exp.X_add_symbol != NULL &&
                   1005:               (insn->exp.X_add_symbol->sy_name[0] != 'L' || flagseen ['L']))
                   1006:                insn->pcrel_reloc = 1;
                   1007:            else
                   1008:                insn->pcrel_reloc = 0;
                   1009:            insn->pcrel = 1;
                   1010:        }
                   1011:        switch(format->ops[parcnt].width){
                   1012:        case 14:
                   1013:            insn->reloc = M98K_RELOC_BR14;
                   1014:            break;
                   1015:        case 24:
                   1016:            insn->reloc = M98K_RELOC_BR24;
                   1017:            break;
                   1018:        default:
                   1019:            as_fatal("Unknown branch instruction width %d",
                   1020:                    format->ops[parcnt].width);
                   1021:            break;
                   1022:        }
                   1023:        return(saveparam);
                   1024: }
                   1025: 
                   1026: static
                   1027: char *
                   1028: parse_reg(
                   1029: char *reg_name,
                   1030: char *param,
                   1031: struct m98k_insn *insn,
                   1032: struct m98k_opcode *format,
                   1033: unsigned long parcnt)
                   1034: {
                   1035:     unsigned long val, d;
                   1036: 
                   1037:        d = 0;
                   1038:        if(*param == '(' && parcnt == 2 &&
                   1039:           (format->ops[1].type == D || format->ops[1].type == DS)){
                   1040:            d = 1;
                   1041:            param++;
                   1042:        }
                   1043: 
                   1044:        if(format->ops[parcnt].type == G0REG && *param == '0'){
                   1045:            val = 0;
                   1046:            param++;
                   1047:        }
                   1048:        else{
                   1049:            val = 0;
                   1050:            while(*reg_name){
                   1051:                if(*param++ != *reg_name++)
                   1052:                    return(NULL);
                   1053:            }
                   1054:            if(!isdigit(*param))
                   1055:                return(NULL);
                   1056: 
                   1057:            while(isdigit(*param))
                   1058:                if((val = val * 10 + *param++ - '0') >=
                   1059:                   1 << format->ops[parcnt].width)
                   1060:                return(NULL);
                   1061: 
                   1062:            if(format->ops[parcnt].type == G0REG && val == 0){
                   1063:                error_param_message = "Parameter error: r0 not allowed "
                   1064:                                      "for parameter %lu (code as 0 not r0)";
                   1065:                return(NULL);
                   1066:            }
                   1067:        }
                   1068: 
                   1069:        if(*param == '\0'){
                   1070:            if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
                   1071:                insn->opcode |= val << format->ops[parcnt].offset;
                   1072:                return(param);
                   1073:            }
                   1074:            else
                   1075:                return(NULL);
                   1076:        }
                   1077:        else if(*param == ','){
                   1078:            if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
                   1079:                insn->opcode |= val << format->ops[parcnt].offset;
                   1080:                return(param+1);
                   1081:            }
                   1082:            else
                   1083:                return(NULL);
                   1084:        }
                   1085:        else if(d == 1 && *param == ')' && param[1] == '\0'){
                   1086:            if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
                   1087:                insn->opcode |= val << format->ops[parcnt].offset;
                   1088:                return(++param);
                   1089:            }
                   1090:            else
                   1091:                return(NULL);
                   1092:        }
                   1093:        return(NULL);
                   1094: }
                   1095: 
                   1096: static
                   1097: char *
                   1098: parse_spreg(
                   1099: char *param,
                   1100: struct m98k_insn *insn,
                   1101: struct m98k_opcode *format,
                   1102: unsigned long parcnt)
                   1103: {
                   1104:     int val;
                   1105:     unsigned long i;
                   1106:     char *saveptr, save_c;
                   1107:     expressionS exp;
                   1108:     segT seg;
                   1109: 
                   1110:        saveptr = input_line_pointer;
                   1111:        input_line_pointer = param;
                   1112:        while(*param != ',' && *param != '\0')
                   1113:                param++;
                   1114:        save_c = *param;
                   1115:        *param = '\0';
                   1116: 
                   1117:        seg = SEG_ABSOLUTE;
                   1118:        val = 0;
                   1119:        for(i = 0; *special_registers[i].name != '\0'; i++){
                   1120:            if(strcmp(input_line_pointer, special_registers[i].name) == 0){
                   1121:                val = special_registers[i].number;
                   1122:                break;
                   1123:            }
                   1124:        }
                   1125:        if(*special_registers[i].name == '\0'){
                   1126:            seg = expression(&exp);
                   1127:            try_to_make_absolute(&exp);
                   1128:            seg = exp.X_seg;
                   1129:            val = exp.X_add_number;
                   1130:        }
                   1131:        *param = save_c;
                   1132:        input_line_pointer = saveptr;
                   1133: 
                   1134:        if(seg != SEG_ABSOLUTE){
                   1135:            error_param_message = "Parameter error: expression must be "
                   1136:                                  "absolute (parameter %lu)";
                   1137:            return(NULL);
                   1138:        }
                   1139:        if(val > 1024 || val < 0){
                   1140:            error_param_message = "Parameter error: expression out "
                   1141:                                  "of range (parameter %lu)";
                   1142:            return(NULL);
                   1143:        }
                   1144: 
                   1145:        val = ((val & 0x1f) << 5) | ((val >> 5) & 0x1f);
                   1146: 
                   1147:        if(*param == '\0'){
                   1148:            if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
                   1149:                insn->opcode |= val << format->ops[parcnt].offset;
                   1150:                return(param);
                   1151:            }
                   1152:            else
                   1153:                return(NULL);
                   1154:        }
                   1155:        else if(*param == ','){
                   1156:            if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
                   1157:                insn->opcode |= val << format->ops[parcnt].offset;
                   1158:                return(param+1);
                   1159:            }
                   1160:            else
                   1161:                return(NULL);
                   1162:        }
                   1163:        return(NULL);
                   1164: }
                   1165: 
                   1166: static
                   1167: char *
                   1168: parse_bcnd(
                   1169: char *param,
                   1170: struct m98k_insn *insn,
                   1171: struct m98k_opcode *format,
                   1172: unsigned long parcnt)
                   1173: {
                   1174:     int val;
                   1175:     unsigned long i, j;
                   1176:     char *saveptr, save_c, *plus, save_plus;
                   1177:     expressionS exp;
                   1178:     segT seg;
                   1179: 
                   1180:        saveptr = input_line_pointer;
                   1181:        input_line_pointer = param;
                   1182:        while(*param != ',' && *param != '\0')
                   1183:            param++;
                   1184:        save_c = *param;
                   1185:        *param = '\0';
                   1186: 
                   1187:        /*
                   1188:         * look for "[CR_field+]condition_symbol".
                   1189:         */
                   1190:        val = -1;
                   1191:        for(plus = input_line_pointer; *plus != '+' && *plus != '\0'; plus++)
                   1192:            ;
                   1193:        if(*plus == '+'){
                   1194:            save_plus = *plus;
                   1195:            *plus = '\0';
                   1196:            for(i = 0; *CR_fields[i].name != '\0'; i++)
                   1197:                if(strcmp(input_line_pointer, CR_fields[i].name) == 0)
                   1198:                    break;
                   1199:            *plus = save_plus;
                   1200:            if(*CR_fields[i].name != '\0'){
                   1201:                for(j = 0; *condition_symbols[j].name != '\0'; j++)
                   1202:                    if(strcmp(plus+1, condition_symbols[j].name) == 0)
                   1203:                        break;
                   1204:                if(*condition_symbols[j].name != '\0'){
                   1205:                    val = CR_fields[i].value + condition_symbols[j].value;
                   1206:                }
                   1207:            }
                   1208:        }
                   1209:        else{
                   1210:            for(i = 0; *condition_symbols[i].name != '\0'; i++)
                   1211:                if(strcmp(input_line_pointer, condition_symbols[i].name) == 0)
                   1212:                    break;
                   1213:            if(*condition_symbols[i].name != '\0')
                   1214:                val = condition_symbols[i].value;
                   1215:        }
                   1216:        if(val == -1){
                   1217:            seg = expression(&exp);
                   1218:            try_to_make_absolute(&exp);
                   1219:            seg = exp.X_seg;
                   1220:            val = exp.X_add_number;
                   1221:            if(seg != SEG_ABSOLUTE){
                   1222:                error_param_message = "Parameter error: expression must be "
                   1223:                                      "absolute (parameter %lu)";
                   1224:                *param = save_c;
                   1225:                input_line_pointer = saveptr;
                   1226:                return(NULL);
                   1227:            }
                   1228:            if(val >= (1 << format->ops[parcnt].width) || val < 0){
                   1229:                error_param_message = "Parameter error: expression out "
                   1230:                                      "of range (parameter %lu)";
                   1231:                *param = save_c;
                   1232:                input_line_pointer = saveptr;
                   1233:                return(NULL);
                   1234:            }
                   1235:        }
                   1236: 
                   1237:        *param = save_c;
                   1238:        input_line_pointer = saveptr;
                   1239: 
                   1240: 
                   1241:        if(*param == '\0'){
                   1242:            if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
                   1243:                insn->opcode |= val << format->ops[parcnt].offset;
                   1244:                return(param);
                   1245:            }
                   1246:            else
                   1247:                return(NULL);
                   1248:        }
                   1249:        else if(*param == ','){
                   1250:            if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
                   1251:                insn->opcode |= val << format->ops[parcnt].offset;
                   1252:                return(param+1);
                   1253:            }
                   1254:            else
                   1255:                return(NULL);
                   1256:        }
                   1257:        return(NULL);
                   1258: 
                   1259: }
                   1260: 
                   1261: static
                   1262: char *
                   1263: parse_crf(
                   1264: char *param,
                   1265: struct m98k_insn *insn,
                   1266: struct m98k_opcode *format,
                   1267: unsigned long parcnt)
                   1268: {
                   1269:     int val;
                   1270:     unsigned long i;
                   1271:     char *saveptr, save_c;
                   1272:     expressionS exp;
                   1273:     segT seg;
                   1274: 
                   1275:        saveptr = input_line_pointer;
                   1276:        input_line_pointer = param;
                   1277:        while(*param != ',' && *param != '\0')
                   1278:            param++;
                   1279:        save_c = *param;
                   1280:        *param = '\0';
                   1281:        val = -1;
                   1282:        for(i = 0; *CR_fields[i].name != '\0'; i++){
                   1283:            if(strcmp(input_line_pointer, CR_fields[i].name) == 0){
                   1284:                val = CR_fields[i].value;
                   1285:                break;
                   1286:            }
                   1287:        }
                   1288:        if(val == -1){
                   1289:            if(format->ops[parcnt].type == CRFONLY){
                   1290:                *param = save_c;
                   1291:                input_line_pointer = saveptr;
                   1292:                return(NULL);
                   1293:            }
                   1294:            seg = expression(&exp);
                   1295:            try_to_make_absolute(&exp);
                   1296:            seg = exp.X_seg;
                   1297:            val = exp.X_add_number;
                   1298:            if(seg != SEG_ABSOLUTE){
                   1299:                error_param_message = "Parameter error: expression must be "
                   1300:                                      "absolute (parameter %lu)";
                   1301:                *param = save_c;
                   1302:                input_line_pointer = saveptr;
                   1303:                return(NULL);
                   1304:            }
                   1305:            if(val >= (1 << format->ops[parcnt].width) || val < 0){
                   1306:                error_param_message = "Parameter error: expression out "
                   1307:                                      "of range (parameter %lu)";
                   1308:                *param = save_c;
                   1309:                input_line_pointer = saveptr;
                   1310:                return(NULL);
                   1311:            }
                   1312:        }
                   1313:        *param = save_c;
                   1314:        input_line_pointer = saveptr;
                   1315: 
                   1316:        if(*param == '\0'){
                   1317:            if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
                   1318:                insn->opcode |= val << format->ops[parcnt].offset;
                   1319:                return(param);
                   1320:            }
                   1321:            else
                   1322:                return(NULL);
                   1323:        }
                   1324:        else if(*param == ','){
                   1325:            if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
                   1326:                insn->opcode |= val << format->ops[parcnt].offset;
                   1327:                return(param+1);
                   1328:            }
                   1329:            else
                   1330:                return(NULL);
                   1331:        }
                   1332:        return(NULL);
                   1333: }
                   1334: 
                   1335: static
                   1336: char *
                   1337: parse_num(
                   1338: char *param,
                   1339: struct m98k_insn *insn,
                   1340: struct m98k_opcode *format,
                   1341: unsigned long parcnt,
                   1342: long max_width_zero)
                   1343: {
                   1344:     int val;
                   1345:     char *saveptr, save_c;
                   1346:     expressionS exp;
                   1347:     segT seg;
                   1348: 
                   1349:        saveptr = input_line_pointer;
                   1350:        input_line_pointer = param;
                   1351:        while(*param != ',' && *param != '\0')
                   1352:                param++;
                   1353:        save_c = *param;
                   1354:        *param = '\0';
                   1355:        seg = expression(&exp);
                   1356:        try_to_make_absolute(&exp);
                   1357:        seg = exp.X_seg;
                   1358:        *param = save_c;
                   1359:        input_line_pointer = saveptr;
                   1360: 
                   1361:        val = exp.X_add_number;
                   1362:        if(seg != SEG_ABSOLUTE){
                   1363:            error_param_message = "Parameter error: expression must be "
                   1364:                                  "absolute (parameter %lu)";
                   1365:            return(NULL);
                   1366:        }
                   1367:        if(max_width_zero){
                   1368:            if(val == (1 << format->ops[parcnt].width))
                   1369:                val = 0;
                   1370:        }
                   1371:        if(val >= (1 << format->ops[parcnt].width) || val < 0){
                   1372:            error_param_message = "Parameter error: expression out "
                   1373:                                  "of range (parameter %lu)";
                   1374:            return(NULL);
                   1375:        }
                   1376: 
                   1377:        if(*param == '\0'){
                   1378:            if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
                   1379:                insn->opcode |= val << format->ops[parcnt].offset;
                   1380:                return(param);
                   1381:            }
                   1382:            else
                   1383:                return(NULL);
                   1384:        }
                   1385:        else if(*param == ','){
                   1386:            if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
                   1387:                insn->opcode |= val << format->ops[parcnt].offset;
                   1388:                return(param+1);
                   1389:            }
                   1390:            else
                   1391:                return(NULL);
                   1392:        }
                   1393:        return(NULL);
                   1394: 
                   1395: }
                   1396: 
                   1397: static
                   1398: char *
                   1399: parse_sh(
                   1400: char *param,
                   1401: struct m98k_insn *insn,
                   1402: struct m98k_opcode *format,
                   1403: unsigned long parcnt)
                   1404: {
                   1405:     int val;
                   1406:     char *saveptr, save_c;
                   1407:     expressionS exp;
                   1408:     segT seg;
                   1409: 
                   1410:        saveptr = input_line_pointer;
                   1411:        input_line_pointer = param;
                   1412:        while(*param != ',' && *param != '\0')
                   1413:                param++;
                   1414:        save_c = *param;
                   1415:        *param = '\0';
                   1416:        seg = expression(&exp);
                   1417:        try_to_make_absolute(&exp);
                   1418:        seg = exp.X_seg;
                   1419:        *param = save_c;
                   1420:        input_line_pointer = saveptr;
                   1421: 
                   1422:        val = exp.X_add_number;
                   1423:        if(seg != SEG_ABSOLUTE){
                   1424:            error_param_message = "Parameter error: expression must be "
                   1425:                                  "absolute (parameter %lu)";
                   1426:            return(NULL);
                   1427:        }
                   1428:        if(val == 64)
                   1429:            val = 0;
                   1430:        if(val >= 64 || val < 0){
                   1431:            error_param_message = "Parameter error: expression out "
                   1432:                                  "of range (parameter %lu)";
                   1433:            return(NULL);
                   1434:        }
                   1435: 
                   1436:        if(*param == '\0'){
                   1437:            if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
                   1438:                insn->opcode |= (val & 0x1f) << 11;
                   1439:                insn->opcode |= ((val >> 5) & 0x1) << 1;
                   1440:                return(param);
                   1441:            }
                   1442:            else
                   1443:                return(NULL);
                   1444:        }
                   1445:        else if(*param == ','){
                   1446:            if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
                   1447:                insn->opcode |= (val & 0x1f) << 11;
                   1448:                insn->opcode |= ((val >> 5) & 0x1) << 1;
                   1449:                return(param+1);
                   1450:            }
                   1451:            else
                   1452:                return(NULL);
                   1453:        }
                   1454:        return(NULL);
                   1455: 
                   1456: }
                   1457: 
                   1458: static
                   1459: char *
                   1460: parse_mb(
                   1461: char *param,
                   1462: struct m98k_insn *insn,
                   1463: struct m98k_opcode *format,
                   1464: unsigned long parcnt)
                   1465: {
                   1466:     int val;
                   1467:     char *saveptr, save_c;
                   1468:     expressionS exp;
                   1469:     segT seg;
                   1470: 
                   1471:        saveptr = input_line_pointer;
                   1472:        input_line_pointer = param;
                   1473:        while(*param != ',' && *param != '\0')
                   1474:                param++;
                   1475:        save_c = *param;
                   1476:        *param = '\0';
                   1477:        seg = expression(&exp);
                   1478:        try_to_make_absolute(&exp);
                   1479:        seg = exp.X_seg;
                   1480:        *param = save_c;
                   1481:        input_line_pointer = saveptr;
                   1482: 
                   1483:        val = exp.X_add_number;
                   1484:        if(seg != SEG_ABSOLUTE){
                   1485:            error_param_message = "Parameter error: expression must be "
                   1486:                                  "absolute (parameter %lu)";
                   1487:            return(NULL);
                   1488:        }
                   1489:        if(val > 64 || val < 0){
                   1490:            error_param_message = "Parameter error: expression out "
                   1491:                                  "of range (parameter %lu)";
                   1492:            return(NULL);
                   1493:        }
                   1494: 
                   1495:        if(*param == '\0'){
                   1496:            if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
                   1497:                insn->opcode |= (val & 0x1f) << 6;
                   1498:                insn->opcode |= ((val >> 5) & 0x1) << 5;
                   1499:                return(param);
                   1500:            }
                   1501:            else
                   1502:                return(NULL);
                   1503:        }
                   1504:        else if(*param == ','){
                   1505:            if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
                   1506:                insn->opcode |= (val & 0x1f) << 6;
                   1507:                insn->opcode |= ((val >> 5) & 0x1) << 5;
                   1508:                return(param+1);
                   1509:            }
                   1510:            else
                   1511:                return(NULL);
                   1512:        }
                   1513:        return(NULL);
                   1514: 
                   1515: }
                   1516: 
                   1517: /*
                   1518:  * md_number_to_chars() is the target machine dependent routine that puts out
                   1519:  * a binary value of size 4, 2, or 1 bytes into the specified buffer.  This is
                   1520:  * done in the target machine's byte sex.  In this case the byte order is
                   1521:  * big endian.
                   1522:  */
                   1523: void
                   1524: md_number_to_chars(
                   1525: char *buf,
                   1526: long val,
                   1527: int nbytes)
                   1528: {
                   1529:        switch(nbytes){
                   1530:        case 4:
                   1531:            *buf++ = val >> 24;
                   1532:            *buf++ = val >> 16;
                   1533:        case 2:
                   1534:            *buf++ = val >> 8;
                   1535:        case 1:
                   1536:            *buf = val;
                   1537:            break;
                   1538: 
                   1539:        default:
                   1540:            abort();
                   1541:        }
                   1542: }
                   1543: 
                   1544: /*
                   1545:  * md_number_to_imm() is the target machine dependent routine that puts out
                   1546:  * a binary value of size 4, 2, or 1 bytes into the specified buffer with
                   1547:  * reguard to a possible relocation entry (the fixP->fx_r_type field in the fixS
                   1548:  * structure pointed to by fixP) for the section with the ordinal nsect.  This
                   1549:  * is done in the target machine's byte sex using it's relocation types.
                   1550:  * In this case the byte order is big endian.
                   1551:  */
                   1552: void
                   1553: md_number_to_imm(
                   1554: unsigned char *buf,
                   1555: long val,
                   1556: int nbytes,
                   1557: fixS *fixP,
                   1558: int nsect)
                   1559: {
                   1560:     unsigned long opcode;
                   1561: 
                   1562:        if(fixP->fx_r_type == NO_RELOC ||
                   1563:           fixP->fx_r_type == M98K_RELOC_VANILLA){
                   1564:            switch(nbytes){
                   1565:            case 4:
                   1566:                *buf++ = val >> 24;
                   1567:                *buf++ = val >> 16;
                   1568:            case 2:
                   1569:                *buf++ = val >> 8;
                   1570:            case 1:
                   1571:                *buf = val;
                   1572:                break;
                   1573: 
                   1574:            default:
                   1575:                abort();
                   1576:            }
                   1577:            return;
                   1578:        }
                   1579:        switch(fixP->fx_r_type){
                   1580:        case M98K_RELOC_HI16:
                   1581:            buf[2] = val >> 24;
                   1582:            buf[3] = val >> 16;
                   1583:            break;
                   1584: 
                   1585:        case M98K_RELOC_LO16:
                   1586:            buf[2] = val >> 8;
                   1587:            buf[3] = val;
                   1588:            break;
                   1589: 
                   1590:        case M98K_RELOC_HA16:
                   1591:            val += 0x00008000;
                   1592:            buf[2] = val >> 24;
                   1593:            buf[3] = val >> 16;
                   1594:            break;
                   1595: 
                   1596:        case M98K_RELOC_LO14:
                   1597:            buf[2] = val >> 8;
                   1598:            buf[3] = val & 0xfc;
                   1599:            break;
                   1600: 
                   1601:        case M98K_RELOC_BR14:
                   1602:            if((val & 0x00008000) != 0){
                   1603:                opcode = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
                   1604:                if(((opcode) & 0x03e00000) != 0x02800000){
                   1605:                    opcode ^= Y_BIT;
                   1606:                    buf[0] = opcode >> 24;
                   1607:                    buf[1] = opcode >> 16;
                   1608:                    buf[2] = opcode >> 8;
                   1609:                    buf[3] = opcode;
                   1610:                }
                   1611:            }
                   1612:            if(fixP->fx_pcrel)
                   1613:                val += 4;
                   1614:            buf[2] = val >> 8;
                   1615:            buf[3] |= val & 0xfc;
                   1616:            break;
                   1617: 
                   1618:        case M98K_RELOC_BR24:
                   1619:            if(fixP->fx_pcrel)
                   1620:                val += 4;
                   1621:            buf[0] |= (val >> 24) & 0x03;
                   1622:            buf[1] = val >> 16;
                   1623:            buf[2] = val >> 8;
                   1624:            buf[3] |= val & 0xfc;
                   1625:            break;
                   1626: 
                   1627:        default:
                   1628:            as_warn("Bad relocation type");
                   1629:            break;
                   1630:        }
                   1631: }
                   1632: 
                   1633: /*
                   1634:  * md_atof() turns a string pointed to by input_line_pointer into a floating
                   1635:  * point constant of type type, and store the appropriate bytes in *litP.
                   1636:  * The number of LITTLENUMS emitted is stored indirectly through *sizeP.
                   1637:  * An error message is returned, or a string containg only a '\0' for OK.
                   1638:  * For this machine only IEEE single and IEEE double floating-point formats
                   1639:  * are allowed.
                   1640:  */
                   1641: char *
                   1642: md_atof(
                   1643: int type,
                   1644: char *litP,
                   1645: int *sizeP)
                   1646: {
                   1647:     int        prec;
                   1648:     LITTLENUM_TYPE words[6];
                   1649:     LITTLENUM_TYPE *wordP;
                   1650:     char *t;
                   1651: 
                   1652:        switch(type){
                   1653:        case 'f':
                   1654:        case 'F':
                   1655:        case 's':
                   1656:        case 'S':
                   1657:            prec = 2;
                   1658:            break;
                   1659: 
                   1660:        case 'd':
                   1661:        case 'D':
                   1662:        case 'r':
                   1663:        case 'R':
                   1664:            prec = 4;
                   1665:            break;
                   1666: 
                   1667:        default:
                   1668:            *sizeP = 0;
                   1669:            return("Bad call to MD_ATOF()");
                   1670:        }
                   1671:        t = atof_ieee(input_line_pointer, type, words);
                   1672:        if(t != NULL)
                   1673:            input_line_pointer = t;
                   1674: 
                   1675:        *sizeP = prec * sizeof(LITTLENUM_TYPE);
                   1676:        for(wordP = words; prec--; ){
                   1677:            md_number_to_chars(litP, (long)(*wordP++), sizeof(LITTLENUM_TYPE));
                   1678:            litP += sizeof(LITTLENUM_TYPE);
                   1679:        }
                   1680:        return ""; /* OK */
                   1681: }
                   1682: 
                   1683: int
                   1684: md_estimate_size_before_relax(
                   1685: fragS *fragP,
                   1686: int segment_type)
                   1687: {
                   1688:        as_warn("Relaxation should never occur");
                   1689:        return(sizeof(long));
                   1690: }
                   1691: 
                   1692: const relax_typeS md_relax_table[] = {0};
                   1693: 
                   1694: void
                   1695: md_convert_frag(
                   1696: fragS *fragP)
                   1697: {
                   1698:        as_warn("Relaxation should never occur");
                   1699: }

unix.superglobalmegacorp.com

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