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