|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.