|
|
1.1 ! root 1: #undef CHECK_WORD_IMMEDIATES /* bug #26863 */ ! 2: ! 3: /* m68k.c All the m68020 specific stuff in one convenient, huge, ! 4: slow to compile, easy to find file. ! 5: Copyright (C) 1987 Free Software Foundation, Inc. ! 6: ! 7: This file is part of GAS, the GNU Assembler. ! 8: ! 9: GAS is free software; you can redistribute it and/or modify ! 10: it under the terms of the GNU General Public License as published by ! 11: the Free Software Foundation; either version 1, or (at your option) ! 12: any later version. ! 13: ! 14: GAS is distributed in the hope that it will be useful, ! 15: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 16: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 17: GNU General Public License for more details. ! 18: ! 19: You should have received a copy of the GNU General Public License ! 20: along with GAS; see the file COPYING. If not, write to ! 21: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 22: ! 23: #include <stdio.h> ! 24: #include <stdlib.h> ! 25: #include <string.h> ! 26: #include <ctype.h> ! 27: #include "m68k-opcode.h" ! 28: #include "as.h" ! 29: #include "obstack.h" ! 30: #include "struc-symbol.h" ! 31: #include "flonum.h" ! 32: #include "expr.h" ! 33: #include "hash.h" ! 34: #include "frags.h" ! 35: #include "fixes.h" ! 36: #include "read.h" ! 37: #include "md.h" ! 38: #ifndef NeXT ! 39: #include "m68k.h" ! 40: #endif /* NeXT */ ! 41: #include "xmalloc.h" ! 42: #include "sections.h" ! 43: #include "messages.h" ! 44: #include "atof-ieee.h" ! 45: #include "input-scrub.h" ! 46: #include "symbols.h" ! 47: ! 48: /* ! 49: * These are the default cputype and cpusubtype for the m68k architecture. ! 50: */ ! 51: const cpu_type_t md_cputype = CPU_TYPE_MC680x0; ! 52: cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_MC680x0_ALL; ! 53: ! 54: /* This is the byte sex for the m68k architecture */ ! 55: const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX; ! 56: ! 57: /* ! 58: * This array holds the chars that always start a comment. If the ! 59: * pre-processor is disabled, these aren't very useful. ! 60: */ ! 61: const char md_comment_chars[] = "|"; ! 62: ! 63: /* ! 64: * This array holds the chars that only start a comment at the beginning of ! 65: * a line. If the line seems to have the form '# 123 filename' ! 66: * .line and .file directives will appear in the pre-processed output. ! 67: * ! 68: * Note that input_file.c hand checks for '#' at the beginning of the ! 69: * first line of the input file. This is because the compiler outputs ! 70: * #NO_APP at the beginning of its output. ! 71: * ! 72: * Also note that a '/' followed by a '*' will always start a comment. ! 73: */ ! 74: const char md_line_comment_chars[] = "#"; ! 75: ! 76: /* Chars that can be used to separate mant from exp in floating point nums. */ ! 77: const char md_EXP_CHARS[] = "eE"; ! 78: ! 79: /* ! 80: * Chars that mean this number is a floating point constant. ! 81: * As in 0f12.456 ! 82: * or 0d1.2345e12 ! 83: * ! 84: * Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be ! 85: * changed in read.c . Ideally it shouldn't have to know about it at all, ! 86: * but nothing is ideal around here. ! 87: */ ! 88: const char md_FLT_CHARS[] = "rRsSfFdDxXeEpP"; ! 89: ! 90: /* Its an arbitrary name: This means I don't approve of it */ ! 91: /* See flames below */ ! 92: static struct obstack robyn; ! 93: ! 94: /* ! 95: * These macros are used to encode a mode for the rlx_more field of the struct ! 96: * relax_typeS in the array md_relax_table below. The array is indexed by a ! 97: * TAB(x,y) value where x is one of BRANCH, FBRANCH, ... and y is BYTE, SHORT, ! 98: * ... Thus the array md_relax_table below is declared to match this use of ! 99: * indexes. The macro TABTYPE(xy) take the value and returns one of BRANCH, ! 100: * FBRANCH, ... ! 101: */ ! 102: #define TAB(x,y) (((x)<<2)+(y)) ! 103: #define TABTYPE(xy) ((xy) >> 2) ! 104: ! 105: #define BRANCH 1 ! 106: #define FBRANCH 2 ! 107: #define PCREL 3 ! 108: #define BCC68000 4 ! 109: #define DBCC 5 ! 110: ! 111: #define BYTE 0 ! 112: #define SHORT 1 ! 113: #define LONG 2 ! 114: #define SZ_UNDEF 3 ! 115: ! 116: /* ! 117: * BCC68000 is for patching in an extra jmp instruction for long offsets ! 118: * on the 68000. The 68000 doesn't support long branches with branchs. ! 119: */ ! 120: ! 121: /* ! 122: * Note that calls to frag_var need to specify the maximum expansion needed. ! 123: * This is currently 10 bytes for DBCC. ! 124: */ ! 125: ! 126: /* ! 127: * This table desribes how you change sizes for the various types of variable ! 128: * size expressions. This version only supports two kinds. ! 129: * The fields are: ! 130: * How far Forward this mode will reach: ! 131: * How far Backward this mode will reach: ! 132: * How many bytes this mode will add to the size of the frag ! 133: * Which mode to go to if the offset won't fit in this one ! 134: */ ! 135: const ! 136: relax_typeS ! 137: md_relax_table[] = { ! 138: { 1, 1, 0, 0 }, /* First entries aren't used */ ! 139: { 1, 1, 0, 0 }, /* For no good reason except */ ! 140: { 1, 1, 0, 0 }, /* that the VAX doesn't either */ ! 141: { 1, 1, 0, 0 }, ! 142: ! 143: { (127), (-128), 0, TAB(BRANCH,SHORT)}, ! 144: { (32767), (-32768), 2, TAB(BRANCH,LONG) }, ! 145: { 0, 0, 4, 0 }, ! 146: { 1, 1, 0, 0 }, ! 147: ! 148: { 1, 1, 0, 0 }, /* FBRANCH doesn't come BYTE */ ! 149: { (32767), (-32768), 2, TAB(FBRANCH,LONG)}, ! 150: { 0, 0, 4, 0 }, ! 151: { 1, 1, 0, 0 }, ! 152: ! 153: { 1, 1, 0, 0 }, /* PCREL doesn't come BYTE */ ! 154: { (32767), (-32768), 2, TAB(PCREL,LONG)}, ! 155: { 0, 0, 4, 0 }, ! 156: { 1, 1, 0, 0 }, ! 157: ! 158: { (127), (-128), 0, TAB(BCC68000,SHORT)}, ! 159: { (32767), (-32768), 2, TAB(BCC68000,LONG) }, ! 160: { 0, 0, 6, 0 }, /* jmp long space */ ! 161: { 1, 1, 0, 0 }, ! 162: ! 163: { 1, 1, 0, 0 }, /* DBCC doesn't come BYTE */ ! 164: { (32767), (-32768), 2, TAB(DBCC,LONG) }, ! 165: { 0, 0, 10, 0 }, /* bra/jmp long space */ ! 166: { 1, 1, 0, 0 }, ! 167: ! 168: }; ! 169: ! 170: static void s_even( ! 171: int value); ! 172: static void s_proc( ! 173: int value); ! 174: ! 175: /* ! 176: * These are the machine dependent pseudo-ops. These are included so ! 177: * the assembler can work on the output from the SUN C compiler, which ! 178: * generates these. ! 179: */ ! 180: ! 181: /* This table describes all the machine specific pseudo-ops the assembler ! 182: * has to support. The fields are: ! 183: * pseudo-op name without dot ! 184: * function to call to execute this pseudo-op ! 185: * Integer arg to pass to the function ! 186: */ ! 187: const pseudo_typeS md_pseudo_table[] = { ! 188: { "float", float_cons, 'f' }, ! 189: { "int", cons, 4 }, ! 190: { "word", cons, 2 }, ! 191: { "quad", big_cons, 8 }, ! 192: { "octa", big_cons, 16 }, ! 193: { "even", s_even, 0 }, ! 194: { "skip", s_space, 0 }, ! 195: { "proc", s_proc, 0 }, ! 196: { 0, 0, 0 } ! 197: }; ! 198: ! 199: #define issbyte(x) ((x)>=-128 && (x)<=127) ! 200: #define isubyte(x) ((x)>=0 && (x)<=255) ! 201: #define issword(x) ((x)>=-32768 && (x)<=32767) ! 202: #define isuword(x) ((x)>=0 && (x)<=65535) ! 203: ! 204: #define isbyte(x) ((x)>=-128 && (x)<=255) ! 205: #define isword(x) ((x)>=-32768 && (x)<=65535) ! 206: #define islong(x) (1) ! 207: ! 208: /* Operands we can parse: (And associated modes) ! 209: ! 210: numb: 8 bit num ! 211: numw: 16 bit num ! 212: numl: 32 bit num ! 213: dreg: data reg 0-7 ! 214: reg: address or data register ! 215: areg: address register ! 216: apc: address register, PC, ZPC or empty string ! 217: num: 16 or 32 bit num ! 218: num2: like num ! 219: sz: w or l if omitted, l assumed ! 220: scale: 1 2 4 or 8 if omitted, 1 assumed ! 221: ! 222: 7.4 IMMED #num --> NUM ! 223: 0.? DREG dreg --> dreg ! 224: 1.? AREG areg --> areg ! 225: 2.? AINDR areg@ --> *(areg) ! 226: 3.? AINC areg@+ --> *(areg++) ! 227: 4.? ADEC areg@- --> *(--areg) ! 228: 5.? AOFF apc@(numw) --> *(apc+numw) -- empty string and ZPC not allowed here ! 229: 6.? AINDX apc@(num,reg:sz:scale) --> *(apc+num+reg*scale) ! 230: 6.? AINDX apc@(reg:sz:scale) --> same, with num=0 ! 231: 6.? APODX apc@(num)@(num2,reg:sz:scale) --> *(*(apc+num)+num2+reg*scale) ! 232: 6.? APODX apc@(num)@(reg:sz:scale) --> same, with num2=0 ! 233: 6.? AMIND apc@(num)@(num2) --> *(*(apc+num)+num2) (previous mode without an index reg) ! 234: 6.? APRDX apc@(num,reg:sz:scale)@(num2) --> *(*(apc+num+reg*scale)+num2) ! 235: 6.? APRDX apc@(reg:sz:scale)@(num2) --> same, with num=0 ! 236: 7.0 ABSL num:sz --> *(num) ! 237: num --> *(num) (sz L assumed) ! 238: *** MSCR otherreg --> Magic ! 239: With -l option ! 240: 5.? AOFF apc@(num) --> *(apc+num) -- empty string and ZPC not allowed here still ! 241: ! 242: examples: ! 243: #foo #0x35 #12 ! 244: d2 ! 245: a4 ! 246: a3@ ! 247: a5@+ ! 248: a6@- ! 249: a2@(12) pc@(14) ! 250: a1@(5,d2:w:1) @(45,d6:l:4) ! 251: pc@(a2) @(d4) ! 252: etc . . . ! 253: ! 254: ! 255: #name@(numw) -->turn into PC rel mode ! 256: apc@(num8,reg:sz:scale) --> *(apc+num8+reg*scale) ! 257: ! 258: */ ! 259: ! 260: #define IMMED 1 ! 261: #define DREG 2 ! 262: #define AREG 3 ! 263: #define AINDR 4 ! 264: #define ADEC 5 ! 265: #define AINC 6 ! 266: #define AOFF 7 ! 267: #define AINDX 8 ! 268: #define APODX 9 ! 269: #define AMIND 10 ! 270: #define APRDX 11 ! 271: #define ABSL 12 ! 272: #define MSCR 13 ! 273: #define REGLST 14 ! 274: ! 275: #define FAIL 0 ! 276: #define OK 1 ! 277: ! 278: /* DATA and ADDR have to be contiguous, so that reg-DATA gives 0-7==data reg, ! 279: 8-15==addr reg for operands that take both types */ ! 280: #define DATA 1 /* 1- 8 == data registers 0-7 */ ! 281: #define ADDR (DATA+8) /* 9-16 == address regs 0-7 */ ! 282: #define FPREG (ADDR+8) /* 17-24 Eight FP registers */ ! 283: #define COPNUM (FPREG+8) /* 25-32 Co-processor #1-#8 */ ! 284: #undef PC ! 285: #define PC (COPNUM+8) /* 33 Program counter */ ! 286: #define ZPC (PC+1) /* 34 Hack for Program space, but 0 addressing */ ! 287: #define SR (ZPC+1) /* 35 Status Reg */ ! 288: #define CCR (SR+1) /* 36 Condition code Reg */ ! 289: ! 290: #define FPI (CCR+1) /* 37 floating-point instruction register */ ! 291: #define FPS (FPI+1) /* 38 floating-point status register */ ! 292: #define FPC (FPS+1) /* 39 floating-point condition register */ ! 293: ! 294: /* These have to be in order for the movec instruction to work. */ ! 295: /* The comment above should read: All the registers that can be in a movec ! 296: instruction must be bounded by USP and MSP (or SRP if BUILTIN_MMUS is ! 297: defined) for the 'J' kind of operand to be checked correctly in m68_ip() */ ! 298: #define USP (FPC+1) /* 40 User Stack Pointer */ ! 299: #define ISP (USP+1) /* 41 Interrupt stack pointer */ ! 300: #define SFC (ISP+1) /* 42 Source function control code register */ ! 301: #define DFC (SFC+1) /* 43 Destination function code register */ ! 302: #define CACR (DFC+1) /* 44 Cashe control register */ ! 303: #define VBR (CACR+1) /* 45 wector base register */ ! 304: #define CAAR (VBR+1) /* 46 Cashe address register */ ! 305: #define MSP (CAAR+1) /* 47 Master stack pointer */ ! 306: ! 307: #ifdef BUILTIN_MMUS ! 308: /* mc68040 mmu registers, can be used in a movec instruction */ ! 309: #define ITT0 (MSP+1) /* 48 instruction transparent translation register 0 */ ! 310: #define ITT1 (ITT0+1) /* 49 instruction transparent translation register 1 */ ! 311: #define DTT0 (ITT1+1) /* 50 data transparent translation register 0 */ ! 312: #define DTT1 (DTT0+1) /* 51 data transparent translation register 1 */ ! 313: #define URP (DTT1+1) /* 53 user root pointer */ ! 314: ! 315: /* mc68030 and mc68040 mmu registers, can be used in a movec instruction */ ! 316: #define MMUSR (URP+1) /* 52 MMU status register */ ! 317: #define TC (MMUSR+1)/* 54 MMU translation control register */ ! 318: #define SRP (TC+1) /* 55 supervisor root pointer */ ! 319: ! 320: /* mc68030 mmu registers, can't be used in a movec instruction (but rather in a ! 321: pmove instruction) */ ! 322: #define CRP (SRP+1) /* 56 cpu root pointer */ ! 323: #define TT0 (CRP+1) /* 57 transparent translation register 0 */ ! 324: #define TT1 (TT0+1) /* 58 transparent translation register 0 */ ! 325: ! 326: /* mc68040 operands to cache instructions */ ! 327: #define IC (TT1+1) /* 59 instruction cache */ ! 328: #define DC (IC+1) /* 60 data cache */ ! 329: #define BC (DC+1) /* 61 both instruction and data caches */ ! 330: #endif /* BUILTIN_MMUS */ ! 331: ! 332: #ifdef m68851 ! 333: /* ! 334: * these defines should be in m68k.c but ! 335: * i put them here to keep all the m68851 stuff ! 336: * together -rab ! 337: * JF--Make sure these #s don't clash with the ones in m68k.c ! 338: * That would be BAD. ! 339: */ ! 340: #define TC (MSP+1) /* 48 */ ! 341: #define DRP (TC+1) /* 49 */ ! 342: #define SRP (DRP+1) /* 50 */ ! 343: #define CRP (SRP+1) /* 51 */ ! 344: #define CAL (CRP+1) /* 52 */ ! 345: #define VAL (CAL+1) /* 53 */ ! 346: #define SCC (VAL+1) /* 54 */ ! 347: #define AC (SCC+1) /* 55 */ ! 348: #define BAD (AC+1) /* 56,57,58,59, 60,61,62,63 */ ! 349: #define BAC (BAD+8) /* 64,65,66,67, 68,69,70,71 */ ! 350: #define PSR (BAC+8) /* 72 */ ! 351: #define PCSR (PSR+1) /* 73 */ ! 352: #endif m68851 ! 353: ! 354: ! 355: /* Note that COPNUM==processor #1 -- COPNUM+7==#8, which stores as 000 */ ! 356: /* I think. . . */ ! 357: ! 358: #undef SP ! 359: #define SP ADDR+7 ! 360: ! 361: /* JF these tables here are for speed at the expense of size */ ! 362: /* You can replace them with the #if 0 versions if you really ! 363: need space and don't mind it running a bit slower */ ! 364: ! 365: static char mklower_table[256]; ! 366: #define mklower(c) (mklower_table[(unsigned char)(c)]) ! 367: static char notend_table[256]; ! 368: static char alt_notend_table[256]; ! 369: #define notend(s) ( !(notend_table[(unsigned char)(*s)] || (*s==':' &&\ ! 370: alt_notend_table[(unsigned char)(s[1])]))) ! 371: ! 372: #if 0 ! 373: #define mklower(c) (isupper(c) ? tolower(c) : c) ! 374: #endif ! 375: ! 376: ! 377: struct m68k_exp { ! 378: char *e_beg; ! 379: char *e_end; ! 380: expressionS e_exp; ! 381: short e_siz; /* 0== default 1==short/byte 2==word 3==long */ ! 382: }; ! 383: ! 384: /* Internal form of an operand. */ ! 385: struct m68k_op { ! 386: char *error; /* Couldn't parse it */ ! 387: int mode; /* What mode this instruction is in. */ ! 388: unsigned long int reg; /* Base register */ ! 389: struct m68k_exp *con1; ! 390: int ireg; /* Index register */ ! 391: int isiz; /* 0==unspec 1==byte(?) 2==short 3==long */ ! 392: int imul; /* Multipy ireg by this (1,2,4,or 8) */ ! 393: struct m68k_exp *con2; ! 394: }; ! 395: ! 396: /* internal form of a 68020 instruction */ ! 397: struct m68_it { ! 398: char *error; ! 399: char *args; /* list of opcode info */ ! 400: int numargs; ! 401: ! 402: #ifdef NeXT ! 403: char *cpus; ! 404: #endif /* NeXT */ ! 405: int numo; /* Number of shorts in opcode */ ! 406: short opcode[11]; ! 407: ! 408: struct m68k_op operands[6]; ! 409: ! 410: int nexp; /* number of exprs in use */ ! 411: struct m68k_exp exprs[4]; ! 412: ! 413: int nfrag; /* Number of frags we have to produce */ ! 414: struct { ! 415: int fragoff; /* Where in the current opcode[] the frag ends */ ! 416: symbolS *fadd; ! 417: long int foff; ! 418: int fragty; ! 419: } fragb[4]; ! 420: ! 421: int nrel; /* Num of reloc strucs in use */ ! 422: struct { ! 423: int n; ! 424: symbolS *add, ! 425: *sub; ! 426: long int off; ! 427: char wid; ! 428: char pcrel; ! 429: } reloc[5]; /* Five is enough??? */ ! 430: }; ! 431: ! 432: static struct m68_it the_ins; /* the instruction being assembled */ ! 433: ! 434: ! 435: /* Macros for adding things to the m68_it struct */ ! 436: ! 437: #define addword(w) the_ins.opcode[the_ins.numo++]=(w) ! 438: ! 439: /* Like addword, but goes BEFORE general operands */ ! 440: #define insop(w) {int z;\ ! 441: for(z=the_ins.numo;z>opcode->m_codenum;--z)\ ! 442: the_ins.opcode[z]=the_ins.opcode[z-1];\ ! 443: for(z=0;z<the_ins.nrel;z++)\ ! 444: the_ins.reloc[z].n+=2;\ ! 445: the_ins.opcode[opcode->m_codenum]=(w);\ ! 446: the_ins.numo++;\ ! 447: } ! 448: ! 449: ! 450: #define add_exp(beg,end) (\ ! 451: the_ins.exprs[the_ins.nexp].e_beg=(beg),\ ! 452: the_ins.exprs[the_ins.nexp].e_end=(end),\ ! 453: &the_ins.exprs[the_ins.nexp++]\ ! 454: ) ! 455: ! 456: ! 457: /* The numo+1 kludge is so we can hit the low order byte of the prev word. Blecch*/ ! 458: #define add_fix(width,exp,pc_rel) {\ ! 459: the_ins.reloc[the_ins.nrel].n= ((width)=='B') ? (the_ins.numo*2-1) : \ ! 460: (((width)=='b') ? ((the_ins.numo-1)*2) : (the_ins.numo*2));\ ! 461: the_ins.reloc[the_ins.nrel].add=adds((exp));\ ! 462: the_ins.reloc[the_ins.nrel].sub=subs((exp));\ ! 463: the_ins.reloc[the_ins.nrel].off=offs((exp));\ ! 464: the_ins.reloc[the_ins.nrel].wid=(width);\ ! 465: the_ins.reloc[the_ins.nrel++].pcrel=(pc_rel);\ ! 466: } ! 467: ! 468: #define add_frag(add,off,type) {\ ! 469: the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo;\ ! 470: the_ins.fragb[the_ins.nfrag].fadd=(add);\ ! 471: the_ins.fragb[the_ins.nfrag].foff=(off);\ ! 472: the_ins.fragb[the_ins.nfrag++].fragty=(type);\ ! 473: } ! 474: ! 475: #define isvar(exp) ((exp) && (adds(exp) || subs(exp))) ! 476: ! 477: #define seg(exp) ((exp)->e_exp.X_seg) ! 478: #define adds(exp) ((exp)->e_exp.X_add_symbol) ! 479: #define subs(exp) ((exp)->e_exp.X_subtract_symbol) ! 480: #define offs(exp) ((exp)->e_exp.X_add_number) ! 481: ! 482: ! 483: struct m68_incant { ! 484: char *m_operands; ! 485: unsigned long m_opcode; ! 486: short m_opnum; ! 487: short m_codenum; ! 488: #ifdef NeXT ! 489: char *m_cpus; ! 490: #endif /* NeXT */ ! 491: struct m68_incant *m_next; ! 492: }; ! 493: ! 494: #define getone(x) ((((x)->m_opcode)>>16)&0xffff) ! 495: #define gettwo(x) (((x)->m_opcode)&0xffff) ! 496: ! 497: /* ! 498: * Declarations static functions in this file. ! 499: */ ! 500: static int m68k_reg_parse( ! 501: char **ccp); ! 502: static int m68k_ip_op( ! 503: char *str, ! 504: struct m68k_op *opP); ! 505: static int try_index( ! 506: char **s, ! 507: struct m68k_op *opP); ! 508: static void m68_ip( ! 509: char *instring); ! 510: static int get_regs( ! 511: int i, ! 512: struct m68k_op *opP, ! 513: char *str); ! 514: static int reverse_16_bits( ! 515: int in); ! 516: static int reverse_8_bits( ! 517: int in); ! 518: static void install_operand( ! 519: int mode, ! 520: int val); ! 521: static void install_gen_operand( ! 522: int mode, ! 523: int val); ! 524: static char *crack_operand( ! 525: char *str, ! 526: struct m68k_op *opP); ! 527: static int get_num( ! 528: struct m68k_exp *exp, ! 529: int ok); ! 530: ! 531: /* JF modified this to handle cases where the first part of a symbol name ! 532: looks like a register */ ! 533: ! 534: static ! 535: int ! 536: m68k_reg_parse( ! 537: char **ccp) ! 538: { ! 539: register char c1, ! 540: c2, ! 541: c3, ! 542: c4; ! 543: #ifdef BUILTIN_MMUS ! 544: char c5; ! 545: #endif ! 546: register int n = 0, ! 547: ret = 0; ! 548: ! 549: c1=mklower(ccp[0][0]); ! 550: c2=mklower(ccp[0][1]); ! 551: c3=mklower(ccp[0][2]); ! 552: c4=mklower(ccp[0][3]); ! 553: #ifdef BUILTIN_MMUS ! 554: c5=mklower(ccp[0][4]); ! 555: #endif ! 556: ! 557: switch(c1) { ! 558: case 'a': ! 559: if(c2>='0' && c2<='7') { ! 560: n=2; ! 561: ret=ADDR+c2-'0'; ! 562: } ! 563: #ifdef m68851 ! 564: else if (c2 == 'c') { ! 565: n = 2; ! 566: ret = AC; ! 567: } ! 568: #endif ! 569: break; ! 570: #ifdef m68851 ! 571: case 'b': ! 572: if (c2 == 'a') { ! 573: if (c3 == 'd') { ! 574: if (c4 >= '0' && c4 <= '7') { ! 575: n = 4; ! 576: ret = BAD + c4 - '0'; ! 577: } ! 578: } ! 579: if (c3 == 'c') { ! 580: if (c4 >= '0' && c4 <= '7') { ! 581: n = 4; ! 582: ret = BAC + c4 - '0'; ! 583: } ! 584: } ! 585: } ! 586: break; ! 587: #endif ! 588: #ifdef BUILTIN_MMUS ! 589: case 'b': ! 590: if (c2 == 'c') { ! 591: n = 2; ! 592: ret = (BC); ! 593: } ! 594: break; ! 595: #endif ! 596: case 'c': ! 597: #ifdef m68851 ! 598: if (c2 == 'a' && c3 == 'l') { ! 599: n = 3; ! 600: ret = CAL; ! 601: } else ! 602: #endif ! 603: /* This supports both CCR and CC as the ccr reg. */ ! 604: if(c2=='c' && c3=='r') { ! 605: n=3; ! 606: ret = CCR; ! 607: } else if(c2=='c') { ! 608: n=2; ! 609: ret = CCR; ! 610: } else if(c2=='a' && (c3=='a' || c3=='c') && c4=='r') { ! 611: n=4; ! 612: ret = c3=='a' ? CAAR : CACR; ! 613: } ! 614: #if defined(m68851) || defined (BUILTIN_MMUS) ! 615: else if (c2 == 'r' && c3 == 'p') { ! 616: n = 3; ! 617: ret = (CRP); ! 618: } ! 619: #endif ! 620: break; ! 621: case 'd': ! 622: if(c2>='0' && c2<='7') { ! 623: n=2; ! 624: ret = DATA+c2-'0'; ! 625: } else if(c2=='f' && c3=='c') { ! 626: n=3; ! 627: ret = DFC; ! 628: } ! 629: #ifdef m68851 ! 630: else if (c2 == 'r' && c3 == 'p') { ! 631: n = 3; ! 632: ret = (DRP); ! 633: } ! 634: #endif ! 635: #ifdef BUILTIN_MMUS ! 636: else if (c2 == 't' && c3 == 't' && (c4 == '0' || c4 == '1')) { ! 637: n = 4; ! 638: if(c4 == '0') ! 639: ret = (DTT0); ! 640: else ! 641: ret = (DTT1); ! 642: } ! 643: else if (c2 == 'c') { ! 644: n = 2; ! 645: ret = (DC); ! 646: } ! 647: #endif ! 648: break; ! 649: case 'f': ! 650: if(c2=='p') { ! 651: if(c3>='0' && c3<='7') { ! 652: n=3; ! 653: ret = FPREG+c3-'0'; ! 654: if(c4==':') ! 655: ccp[0][3]=','; ! 656: } else if(c3=='i') { ! 657: n=3; ! 658: ret = FPI; ! 659: } else if(c3=='s') { ! 660: n= (c4 == 'r' ? 4 : 3); ! 661: ret = FPS; ! 662: } else if(c3=='c') { ! 663: n= (c4 == 'r' ? 4 : 3); ! 664: ret = FPC; ! 665: } ! 666: } ! 667: break; ! 668: case 'i': ! 669: if(c2=='s' && c3=='p') { ! 670: n=3; ! 671: ret = ISP; ! 672: } ! 673: #ifdef BUILTIN_MMUS ! 674: else if (c2 == 't' && c3 == 't' && (c4 == '0' || c4 == '1')) { ! 675: n = 4; ! 676: if(c4 == '0') ! 677: ret = (ITT0); ! 678: else ! 679: ret = (ITT1); ! 680: } ! 681: else if (c2 == 'c') { ! 682: n = 2; ! 683: ret = (IC); ! 684: } ! 685: #endif ! 686: break; ! 687: case 'm': ! 688: if(c2=='s' && c3=='p') { ! 689: n=3; ! 690: ret = MSP; ! 691: } ! 692: #ifdef BUILTIN_MMUS ! 693: if(c2=='m' && c3=='u' && c4=='s' && c5=='r') { ! 694: n=5; ! 695: ret = MMUSR; ! 696: } ! 697: #endif ! 698: break; ! 699: case 'p': ! 700: if(c2=='c') { ! 701: #ifdef m68851 ! 702: if(c3 == 's' && c4=='r') { ! 703: n=4; ! 704: ret = (PCSR); ! 705: } else ! 706: #endif ! 707: { ! 708: n=2; ! 709: ret = PC; ! 710: } ! 711: } ! 712: #ifdef m68851 ! 713: else if (c2 == 's' && c3 == 'r') { ! 714: n = 3; ! 715: ret = (PSR); ! 716: } ! 717: #endif ! 718: #ifdef BUILTIN_MMUS ! 719: else if (c2 == 's' && c3 == 'r') { ! 720: n = 3; ! 721: ret = (MMUSR); ! 722: } ! 723: #endif ! 724: break; ! 725: case 's': ! 726: #if defined(m68851) || defined(BUILTIN_MMUS) ! 727: if (c2 == 'r' && c3 == 'p') { ! 728: n = 3; ! 729: ret = (SRP); ! 730: } ! 731: #endif ! 732: #ifdef m68851 ! 733: else if (c2 == 'c' && c3 == 'c') { ! 734: n = 3; ! 735: ret = (SCC); ! 736: } ! 737: #endif ! 738: #if defined(m68851) || defined(BUILTIN_MMUS) ! 739: else ! 740: #endif ! 741: if(c2=='r') { ! 742: n=2; ! 743: ret = SR; ! 744: } else if(c2=='p') { ! 745: n=2; ! 746: ret = ADDR+7; ! 747: } else if(c2=='f' && c3=='c') { ! 748: n=3; ! 749: ret = SFC; ! 750: } ! 751: break; ! 752: #if defined(m68851) || defined(BUILTIN_MMUS) ! 753: case 't': ! 754: if(c2 == 'c') { ! 755: n=2; ! 756: ret=TC; ! 757: } ! 758: #ifdef BUILTIN_MMUS ! 759: else if (c2 == 't' && (c3 == '0' || c3 == '1')) { ! 760: n = 3; ! 761: if(c3 == '0') ! 762: ret = (TT0); ! 763: else ! 764: ret = (TT1); ! 765: } ! 766: #endif ! 767: break; ! 768: #endif ! 769: case 'u': ! 770: if(c2=='s' && c3=='p') { ! 771: n=3; ! 772: ret = USP; ! 773: } ! 774: #ifdef BUILTIN_MMUS ! 775: else if(c2=='r' && c3=='p') { ! 776: n=3; ! 777: ret = URP; ! 778: } ! 779: #endif ! 780: break; ! 781: case 'v': ! 782: #ifdef m68851 ! 783: if (c2 == 'a' && c3 == 'l') { ! 784: n = 3; ! 785: ret = (VAL); ! 786: } else ! 787: #endif ! 788: if(c2=='b' && c3=='r') { ! 789: n=3; ! 790: ret = VBR; ! 791: } ! 792: break; ! 793: case 'z': ! 794: if(c2=='p' && c3=='c') { ! 795: n=3; ! 796: ret = ZPC; ! 797: } ! 798: break; ! 799: default: ! 800: break; ! 801: } ! 802: if(n) { ! 803: if(isalnum(ccp[0][n]) || ccp[0][n]=='_') ! 804: ret=FAIL; ! 805: else ! 806: ccp[0]+=n; ! 807: } else ! 808: ret = FAIL; ! 809: return ret; ! 810: } ! 811: ! 812: #define SKIP_WHITE() { str++; if(*str==' ') str++;} ! 813: ! 814: static ! 815: int ! 816: m68k_ip_op( ! 817: char *str, ! 818: struct m68k_op *opP) ! 819: { ! 820: char *strend; ! 821: long i; ! 822: ! 823: if(*str==' ') ! 824: str++; ! 825: /* Find the end of the string */ ! 826: if(!*str) { ! 827: /* Out of gas */ ! 828: opP->error="Missing operand"; ! 829: return FAIL; ! 830: } ! 831: for(strend=str;*strend;strend++) ! 832: ; ! 833: --strend; ! 834: ! 835: /* Guess what: A constant. Shar and enjoy */ ! 836: if(*str=='#') { ! 837: str++; ! 838: opP->con1=add_exp(str,strend); ! 839: opP->mode=IMMED; ! 840: return OK; ! 841: } ! 842: i=m68k_reg_parse(&str); ! 843: if((i==FAIL || *str!='\0') && *str!='@') { ! 844: char *stmp; ! 845: ! 846: if(i!=FAIL && (*str=='/' || *str=='-')) { ! 847: opP->mode=REGLST; ! 848: return get_regs(i,opP,str); ! 849: } ! 850: if((stmp=index(str,'@'))) { ! 851: opP->con1=add_exp(str,stmp-1); ! 852: if(stmp==strend) { ! 853: opP->mode=AINDX; ! 854: return OK; ! 855: } ! 856: stmp++; ! 857: if(*stmp++!='(' || *strend--!=')') { ! 858: opP->error="Malformed operand"; ! 859: return FAIL; ! 860: } ! 861: i=try_index(&stmp,opP); ! 862: opP->con2=add_exp(stmp,strend); ! 863: if(i==FAIL) opP->mode=AMIND; ! 864: else opP->mode=APODX; ! 865: return OK; ! 866: } ! 867: opP->mode=ABSL; ! 868: opP->con1=add_exp(str,strend); ! 869: return OK; ! 870: } ! 871: opP->reg=i; ! 872: if(*str=='\0') { ! 873: if(i>=DATA+0 && i<=DATA+7) ! 874: opP->mode=DREG; ! 875: else if(i>=ADDR+0 && i<=ADDR+7) ! 876: opP->mode=AREG; ! 877: else ! 878: opP->mode=MSCR; ! 879: return OK; ! 880: } ! 881: if((i<ADDR+0 || i>ADDR+7) && i!=PC && i!=ZPC && i!=FAIL) { /* Can't indirect off non address regs */ ! 882: opP->error="Invalid indirect register"; ! 883: return FAIL; ! 884: } ! 885: if(*str!='@') ! 886: abort(); ! 887: str++; ! 888: switch(*str) { ! 889: case '\0': ! 890: opP->mode=AINDR; ! 891: return OK; ! 892: case '-': ! 893: opP->mode=ADEC; ! 894: return OK; ! 895: case '+': ! 896: opP->mode=AINC; ! 897: return OK; ! 898: case '(': ! 899: str++; ! 900: break; ! 901: default: ! 902: opP->error="Junk after indirect"; ! 903: return FAIL; ! 904: } ! 905: /* Some kind of indexing involved. Lets find out how bad it is */ ! 906: i=try_index(&str,opP); ! 907: /* Didn't start with an index reg, maybe its offset or offset,reg */ ! 908: if(i==FAIL) { ! 909: char *beg_str; ! 910: ! 911: beg_str=str; ! 912: for(i=1;i;) { ! 913: switch(*str++) { ! 914: case '\0': ! 915: opP->error="Missing )"; ! 916: return FAIL; ! 917: case ',': i=0; break; ! 918: case '(': i++; break; ! 919: case ')': --i; break; ! 920: } ! 921: } ! 922: opP->con1=add_exp(beg_str,str-2); ! 923: /* Should be offset,reg */ ! 924: if(str[-1]==',') { ! 925: i=try_index(&str,opP); ! 926: if(i==FAIL) { ! 927: opP->error="Malformed index reg"; ! 928: return FAIL; ! 929: } ! 930: } ! 931: } ! 932: /* We've now got offset) offset,reg) or reg) */ ! 933: ! 934: if(*str=='\0') { ! 935: /* Th-the-thats all folks */ ! 936: #ifdef NeXT ! 937: /* all forms using zpc must use pc@(bd,Xn) and not pc@(d16) because ! 938: you can only suppress the base register in the first form */ ! 939: if(opP->reg==FAIL || opP->reg==ZPC) opP->mode=AINDX; /* Other form of indirect */ ! 940: #else /* !defined(NeXT) */ ! 941: if(opP->reg==FAIL) opP->mode=AINDX; /* Other form of indirect */ ! 942: #endif /* NeXT */ ! 943: else if(opP->ireg==FAIL) opP->mode=AOFF; ! 944: else opP->mode=AINDX; ! 945: return OK; ! 946: } ! 947: /* Next thing had better be another @ */ ! 948: if(*str!='@' || str[1]!='(') { ! 949: opP->error="junk after indirect"; ! 950: return FAIL; ! 951: } ! 952: str+=2; ! 953: if(opP->ireg!=FAIL) { ! 954: opP->mode=APRDX; ! 955: i=try_index(&str,opP); ! 956: if(i!=FAIL) { ! 957: opP->error="Two index registers! not allowed!"; ! 958: return FAIL; ! 959: } ! 960: } else ! 961: i=try_index(&str,opP); ! 962: if(i==FAIL) { ! 963: char *beg_str; ! 964: ! 965: beg_str=str; ! 966: for(i=1;i;) { ! 967: switch(*str++) { ! 968: case '\0': ! 969: opP->error="Missing )"; ! 970: return FAIL; ! 971: case ',': i=0; break; ! 972: case '(': i++; break; ! 973: case ')': --i; break; ! 974: } ! 975: } ! 976: opP->con2=add_exp(beg_str,str-2); ! 977: if(str[-1]==',') { ! 978: if(opP->ireg!=FAIL) { ! 979: opP->error="Can't have two index regs"; ! 980: return FAIL; ! 981: } ! 982: i=try_index(&str,opP); ! 983: if(i==FAIL) { ! 984: opP->error="malformed index reg"; ! 985: return FAIL; ! 986: } ! 987: opP->mode=APODX; ! 988: } else if(opP->ireg!=FAIL) ! 989: opP->mode=APRDX; ! 990: else ! 991: opP->mode=AMIND; ! 992: } else ! 993: opP->mode=APODX; ! 994: if(*str!='\0') { ! 995: opP->error="Junk after indirect"; ! 996: return FAIL; ! 997: } ! 998: return OK; ! 999: } ! 1000: ! 1001: static ! 1002: int ! 1003: try_index( ! 1004: char **s, ! 1005: struct m68k_op *opP) ! 1006: { ! 1007: register int i; ! 1008: char *ss; ! 1009: #define SKIP_W() { ss++; if(*ss==' ') ss++;} ! 1010: ! 1011: ss= *s; ! 1012: /* SKIP_W(); */ ! 1013: i=m68k_reg_parse(&ss); ! 1014: if(!(i>=DATA+0 && i<=ADDR+7)) { /* if i is not DATA or ADDR reg */ ! 1015: *s=ss; ! 1016: return FAIL; ! 1017: } ! 1018: opP->ireg=i; ! 1019: /* SKIP_W(); */ ! 1020: if(*ss==')') { ! 1021: opP->isiz=0; ! 1022: opP->imul=1; ! 1023: SKIP_W(); ! 1024: *s=ss; ! 1025: return OK; ! 1026: } ! 1027: if(*ss!=':') { ! 1028: opP->error="Missing : in index register"; ! 1029: *s=ss; ! 1030: return FAIL; ! 1031: } ! 1032: SKIP_W(); ! 1033: if(mklower(*ss)=='w') opP->isiz=2; ! 1034: else if(mklower(*ss)=='l') opP->isiz=3; ! 1035: else { ! 1036: opP->error="Size spec not :w or :l"; ! 1037: *s=ss; ! 1038: return FAIL; ! 1039: } ! 1040: SKIP_W(); ! 1041: if(*ss==':') { ! 1042: SKIP_W(); ! 1043: switch(*ss) { ! 1044: case '1': ! 1045: case '2': ! 1046: case '4': ! 1047: case '8': ! 1048: opP->imul= *ss-'0'; ! 1049: break; ! 1050: default: ! 1051: opP->error="index multiplier not 1, 2, 4 or 8"; ! 1052: *s=ss; ! 1053: return FAIL; ! 1054: } ! 1055: SKIP_W(); ! 1056: } else opP->imul=1; ! 1057: if(*ss!=')') { ! 1058: opP->error="Missing )"; ! 1059: *s=ss; ! 1060: return FAIL; ! 1061: } ! 1062: SKIP_W(); ! 1063: *s=ss; ! 1064: return OK; ! 1065: } ! 1066: ! 1067: #ifdef TEST1 /* TEST1 tests m68k_ip_op(), which parses operands */ ! 1068: void ! 1069: main( ! 1070: int argc, ! 1071: char *argv[], ! 1072: char *envp[]) ! 1073: { ! 1074: char buf[128]; ! 1075: struct m68k_op thark; ! 1076: ! 1077: for(;;){ ! 1078: if(!gets(buf)) ! 1079: break; ! 1080: memset(&thark, '\0', sizeof(thark)); ! 1081: if(!m68k_ip_op(buf, &thark)) ! 1082: printf("FAIL:"); ! 1083: if(thark.error) ! 1084: printf("op1 error %s in %s\n",thark.error,buf); ! 1085: printf("mode %d, reg %d, ",thark.mode,thark.reg); ! 1086: if(thark.con1) ! 1087: printf("con1: '%.*s',", ! 1088: 1 + thark.con1->e_end - thark.con1->e_beg, ! 1089: thark.con1->e_beg); ! 1090: printf("ireg %d, isiz %d, imul %d ", ! 1091: thark.ireg, thark.isiz, thark.imul); ! 1092: if(thark.con2) ! 1093: printf("con2: '%.*s'", ! 1094: 1 + thark.con2->e_end - thark.con2->e_beg, ! 1095: thark.con2->e_beg); ! 1096: printf("\n"); ! 1097: } ! 1098: exit(0); ! 1099: } ! 1100: #endif /* TEST1 */ ! 1101: ! 1102: ! 1103: /* ! 1104: * Handle of the OPCODE hash table NULL means any use before m68_ip_begin() ! 1105: * will crash. ! 1106: */ ! 1107: static struct hash_control *op_hash = NULL; ! 1108: ! 1109: ! 1110: /* ! 1111: * m 6 8 _ i p ( ) ! 1112: * ! 1113: * This converts a string into a 68k instruction. ! 1114: * The string must be a bare single instruction in sun format ! 1115: * with RMS-style 68020 indirects ! 1116: * (example: ) ! 1117: * ! 1118: * It provides some error messages: at most one fatal error message (which ! 1119: * stops the scan) and at most one warning message for each operand. ! 1120: * The 68k instruction is returned in exploded form, since we have no ! 1121: * knowledge of how you parse (or evaluate) your expressions. ! 1122: * We do however strip off and decode addressing modes and operation ! 1123: * mnemonic. ! 1124: * ! 1125: * This function's value is a string. If it is not "" then an internal ! 1126: * logic error was found: read this code to assign meaning to the string. ! 1127: * No argument string should generate such an error string: ! 1128: * it means a bug in our code, not in the user's text. ! 1129: * ! 1130: * You MUST have called m86_ip_begin() once and m86_ip_end() never before using ! 1131: * this function. ! 1132: */ ! 1133: ! 1134: /* JF this function no longer returns a useful value. Sorry */ ! 1135: static ! 1136: void ! 1137: m68_ip( ! 1138: char *instring) ! 1139: { ! 1140: register char *p; ! 1141: register struct m68k_op *opP; ! 1142: register struct m68_incant *opcode; ! 1143: register char *s; ! 1144: register int tmpreg = 0, ! 1145: baseo = 0, ! 1146: outro = 0, ! 1147: nextword; ! 1148: int siz1, ! 1149: siz2; ! 1150: char c; ! 1151: int losing; ! 1152: int opsfound; ! 1153: LITTLENUM_TYPE words[6]; ! 1154: LITTLENUM_TYPE *wordp; ! 1155: ! 1156: if (*instring == ' ') ! 1157: instring++; /* skip leading whitespace */ ! 1158: ! 1159: /* Scan up to end of operation-code, which MUST end in end-of-string ! 1160: or exactly 1 space. */ ! 1161: for (p = instring; *p != '\0'; p++) ! 1162: if (*p == ' ') ! 1163: break; ! 1164: ! 1165: ! 1166: if (p == instring) { ! 1167: the_ins.error = "No operator"; ! 1168: the_ins.opcode[0] = 0; ! 1169: /* the_ins.numo=1; */ ! 1170: return; ! 1171: } ! 1172: ! 1173: /* p now points to the end of the opcode name, probably whitespace. ! 1174: make sure the name is null terminated by clobbering the whitespace, ! 1175: look it up in the hash table, then fix it back. */ ! 1176: c = *p; ! 1177: *p = '\0'; ! 1178: opcode = (struct m68_incant *)hash_find (op_hash, instring); ! 1179: *p = c; ! 1180: ! 1181: if (opcode == NULL) { ! 1182: the_ins.error = "Unknown operator"; ! 1183: the_ins.opcode[0] = 0; ! 1184: /* the_ins.numo=1; */ ! 1185: return; ! 1186: } ! 1187: ! 1188: /* found a legitimate opcode, start matching operands */ ! 1189: for(opP= &the_ins.operands[0];*p;opP++) { ! 1190: p = crack_operand (p, opP); ! 1191: if(opP->error) { ! 1192: the_ins.error=opP->error; ! 1193: return; ! 1194: } ! 1195: } ! 1196: ! 1197: opsfound=opP- &the_ins.operands[0]; ! 1198: /* This ugly hack is to support the floating pt opcodes in their standard form */ ! 1199: /* Essentially, we fake a first enty of type COP#1 */ ! 1200: if(opcode->m_operands[0]=='I') { ! 1201: int n; ! 1202: ! 1203: for(n=opsfound;n>0;--n) ! 1204: the_ins.operands[n]=the_ins.operands[n-1]; ! 1205: ! 1206: /* bcopy((char *)(&the_ins.operands[0]),(char *)(&the_ins.operands[1]),opsfound*sizeof(the_ins.operands[0])); */ ! 1207: memset((char *)(&the_ins.operands[0]), '\0', ! 1208: sizeof(the_ins.operands[0])); ! 1209: the_ins.operands[0].mode=MSCR; ! 1210: the_ins.operands[0].reg=COPNUM; /* COP #1 */ ! 1211: opsfound++; ! 1212: } ! 1213: /* We've got the operands. Find an opcode that'll ! 1214: accept them */ ! 1215: for(losing=0;;) { ! 1216: if(opsfound!=opcode->m_opnum) ! 1217: losing++; ! 1218: else for(s=opcode->m_operands,opP= &the_ins.operands[0];*s && !losing;s+=2,opP++) { ! 1219: /* Warning: this switch is huge! */ ! 1220: /* I've tried to organize the cases into this order: ! 1221: non-alpha first, then alpha by letter. lower-case goes directly ! 1222: before uppercase counterpart. */ ! 1223: /* Code with multiple case ...: gets sorted by the lowest case ... ! 1224: it belongs to. I hope this makes sense. */ ! 1225: switch(*s) { ! 1226: case '!': ! 1227: if(opP->mode==MSCR || opP->mode==IMMED || ! 1228: opP->mode==DREG || opP->mode==AREG || opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST) ! 1229: losing++; ! 1230: break; ! 1231: ! 1232: case '#': ! 1233: if(opP->mode!=IMMED) ! 1234: losing++; ! 1235: else { ! 1236: long t; ! 1237: ! 1238: t=get_num(opP->con1,80); ! 1239: if(s[1]=='b' && !isbyte(t)) ! 1240: losing++; ! 1241: #ifdef CHECK_WORD_IMMEDIATES ! 1242: else if((s[1]=='w' || s[1]=='z') && ! 1243: !isword(t)) ! 1244: losing++; ! 1245: #else ! 1246: else if(s[1]=='z' && !isword(t)) ! 1247: losing++; ! 1248: #endif ! 1249: } ! 1250: break; ! 1251: ! 1252: case '^': ! 1253: case 'T': ! 1254: if(opP->mode!=IMMED) ! 1255: losing++; ! 1256: break; ! 1257: ! 1258: case '$': ! 1259: if(opP->mode==MSCR || opP->mode==AREG || ! 1260: opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST) ! 1261: losing++; ! 1262: break; ! 1263: ! 1264: case '%': ! 1265: if(opP->mode==MSCR || opP->reg==PC || ! 1266: opP->reg==ZPC || opP->mode==REGLST) ! 1267: losing++; ! 1268: break; ! 1269: ! 1270: ! 1271: case '&': ! 1272: if(opP->mode==MSCR || opP->mode==DREG || ! 1273: opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || ! 1274: opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST) ! 1275: losing++; ! 1276: break; ! 1277: ! 1278: case '*': ! 1279: if(opP->mode==MSCR || opP->mode==REGLST) ! 1280: losing++; ! 1281: break; ! 1282: ! 1283: case '+': ! 1284: if(opP->mode!=AINC) ! 1285: losing++; ! 1286: break; ! 1287: ! 1288: case '-': ! 1289: if(opP->mode!=ADEC) ! 1290: losing++; ! 1291: break; ! 1292: ! 1293: #ifdef NeXT ! 1294: case '0': ! 1295: if(opP->mode!=AINDR) ! 1296: losing++; ! 1297: break; ! 1298: #endif /* NeXT */ ! 1299: ! 1300: case '/': ! 1301: if(opP->mode==MSCR || opP->mode==AREG || ! 1302: opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->mode==REGLST) ! 1303: losing++; ! 1304: break; ! 1305: ! 1306: case ';': ! 1307: if(opP->mode==MSCR || opP->mode==AREG || opP->mode==REGLST) ! 1308: losing++; ! 1309: break; ! 1310: ! 1311: case '?': ! 1312: if(opP->mode==MSCR || opP->mode==AREG || ! 1313: opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->reg==PC || ! 1314: opP->reg==ZPC || opP->mode==REGLST) ! 1315: losing++; ! 1316: break; ! 1317: ! 1318: case '@': ! 1319: if(opP->mode==MSCR || opP->mode==AREG || ! 1320: opP->mode==IMMED || opP->mode==REGLST) ! 1321: losing++; ! 1322: break; ! 1323: ! 1324: case '~': /* For now! (JF FOO is this right?) */ ! 1325: if(opP->mode==MSCR || opP->mode==DREG || ! 1326: opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST) ! 1327: losing++; ! 1328: break; ! 1329: ! 1330: case 'A': ! 1331: if(opP->mode!=AREG) ! 1332: losing++; ! 1333: break; ! 1334: ! 1335: case 'B': /* FOO */ ! 1336: if(opP->mode!=ABSL) ! 1337: losing++; ! 1338: break; ! 1339: ! 1340: case 'C': ! 1341: if(opP->mode!=MSCR || opP->reg!=CCR) ! 1342: losing++; ! 1343: break; ! 1344: ! 1345: case 'd': /* FOO This mode is a KLUDGE!! */ ! 1346: if(opP->mode!=AOFF && (opP->mode!=ABSL || ! 1347: opP->con1->e_beg[0]!='(' || opP->con1->e_end[0]!=')')) ! 1348: losing++; ! 1349: break; ! 1350: ! 1351: case 'D': ! 1352: if(opP->mode!=DREG) ! 1353: losing++; ! 1354: break; ! 1355: ! 1356: case 'F': ! 1357: if(opP->mode!=MSCR || opP->reg<(FPREG+0) || opP->reg>(FPREG+7)) ! 1358: losing++; ! 1359: break; ! 1360: ! 1361: case 'I': ! 1362: if(opP->mode!=MSCR || opP->reg<COPNUM || ! 1363: opP->reg>=COPNUM+7) ! 1364: losing++; ! 1365: break; ! 1366: ! 1367: case 'J': ! 1368: #ifdef BUILTIN_MMUS ! 1369: if(opP->mode!=MSCR || opP->reg<USP || opP->reg>SRP) ! 1370: #else ! 1371: if(opP->mode!=MSCR || opP->reg<USP || opP->reg>MSP) ! 1372: #endif ! 1373: losing++; ! 1374: break; ! 1375: ! 1376: case 'k': ! 1377: if(opP->mode!=IMMED) ! 1378: losing++; ! 1379: break; ! 1380: ! 1381: case 'l': ! 1382: case 'L': ! 1383: if(opP->mode==DREG || opP->mode==AREG || opP->mode==FPREG) { ! 1384: if(s[1]=='8') ! 1385: losing++; ! 1386: else { ! 1387: opP->mode=REGLST; ! 1388: opP->reg=1<<(opP->reg-DATA); ! 1389: } ! 1390: } else if(opP->mode!=REGLST) { ! 1391: losing++; ! 1392: } else if(s[1]=='8' && opP->reg&0x0FFffFF) ! 1393: losing++; ! 1394: else if(s[1]=='3' && opP->reg&0x7000000) ! 1395: losing++; ! 1396: break; ! 1397: ! 1398: case 'M': ! 1399: if(opP->mode!=IMMED) ! 1400: losing++; ! 1401: else { ! 1402: long t; ! 1403: ! 1404: t=get_num(opP->con1,80); ! 1405: #ifdef NeXT /* feature to try to make expressions absolute */ ! 1406: /* DJA -- Bug fix. allow absolute expressions */ ! 1407: if(! (issbyte(t) && seg(opP->con1)==SEG_ABSOLUTE) ) ! 1408: #else /* !defined(NeXT) */ ! 1409: if(!issbyte(t) || isvar(opP->con1)) ! 1410: #endif /* NeXT */ ! 1411: losing++; ! 1412: } ! 1413: break; ! 1414: ! 1415: case 'O': ! 1416: if(opP->mode!=DREG && opP->mode!=IMMED) ! 1417: losing++; ! 1418: break; ! 1419: ! 1420: case 'Q': ! 1421: if(opP->mode!=IMMED) ! 1422: losing++; ! 1423: else { ! 1424: long t; ! 1425: ! 1426: t=get_num(opP->con1,80); ! 1427: if(t<1 || t>8 || isvar(opP->con1)) ! 1428: losing++; ! 1429: } ! 1430: break; ! 1431: ! 1432: case 'R': ! 1433: if(opP->mode!=DREG && opP->mode!=AREG) ! 1434: losing++; ! 1435: break; ! 1436: ! 1437: case 's': ! 1438: if(opP->mode!=MSCR || !(opP->reg==FPI || opP->reg==FPS || opP->reg==FPC)) ! 1439: losing++; ! 1440: break; ! 1441: ! 1442: case 'S': ! 1443: if(opP->mode!=MSCR || opP->reg!=SR) ! 1444: losing++; ! 1445: break; ! 1446: ! 1447: case 'U': ! 1448: if(opP->mode!=MSCR || opP->reg!=USP) ! 1449: losing++; ! 1450: break; ! 1451: ! 1452: /* JF these are out of order. We could put them ! 1453: in order if we were willing to put up with ! 1454: bunches of #ifdef m68851s in the code */ ! 1455: #ifdef m68851 ! 1456: /* Memory addressing mode used by pflushr */ ! 1457: case '|': ! 1458: if(opP->mode==MSCR || opP->mode==DREG || ! 1459: opP->mode==AREG || opP->mode==REGLST) ! 1460: losing++; ! 1461: break; ! 1462: #endif ! 1463: ! 1464: #if defined(m68851) || defined(BUILTIN_MMUS) ! 1465: case 'f': ! 1466: if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC)) ! 1467: losing++; ! 1468: break; ! 1469: #endif ! 1470: ! 1471: #ifdef m68851 ! 1472: case 'P': ! 1473: if (opP->mode != MSCR || (opP->reg != TC && opP->reg != CAL && ! 1474: opP->reg != VAL && opP->reg != SCC && opP->reg != AC)) ! 1475: losing++; ! 1476: break; ! 1477: ! 1478: case 'V': ! 1479: if (opP->reg != VAL) ! 1480: losing++; ! 1481: break; ! 1482: ! 1483: case 'W': ! 1484: if (opP->mode != MSCR || (opP->reg != DRP && opP->reg != SRP && ! 1485: opP->reg != CRP)) ! 1486: losing++; ! 1487: break; ! 1488: ! 1489: case 'X': ! 1490: if (opP->mode != MSCR || ! 1491: (!(opP->reg >= BAD && opP->reg <= BAD+7) && ! 1492: !(opP->reg >= BAC && opP->reg <= BAC+7))) ! 1493: losing++; ! 1494: break; ! 1495: ! 1496: case 'Y': ! 1497: if (opP->reg != PSR) ! 1498: losing++; ! 1499: break; ! 1500: ! 1501: case 'Z': ! 1502: if (opP->reg != PCSR) ! 1503: losing++; ! 1504: break; ! 1505: #endif ! 1506: #ifdef BUILTIN_MMUS ! 1507: case 'a': ! 1508: if ((opP->mode != MSCR) || (opP->reg != SRP && ! 1509: opP->reg != CRP && opP->reg != TC)) ! 1510: losing++; ! 1511: break; ! 1512: case 'b': ! 1513: if (opP->mode != MSCR || opP->reg != MMUSR) ! 1514: losing++; ! 1515: break; ! 1516: case 'c': ! 1517: if ((opP->mode != MSCR) || (opP->reg != IC && ! 1518: opP->reg != DC && opP->reg != BC)) ! 1519: losing++; ! 1520: break; ! 1521: case 'e': ! 1522: if ((opP->mode != MSCR) || (opP->reg != TT0 && ! 1523: opP->reg != TT1)) ! 1524: losing++; ! 1525: break; ! 1526: #endif ! 1527: default: ! 1528: as_fatal("Internal error: Operand mode %c unknown",*s); ! 1529: } ! 1530: } ! 1531: if(!losing) ! 1532: break; ! 1533: opcode=opcode->m_next; ! 1534: if(!opcode) { /* Fell off the end */ ! 1535: the_ins.error="instruction/operands mismatch"; ! 1536: return; ! 1537: } ! 1538: losing=0; ! 1539: } ! 1540: the_ins.args=opcode->m_operands; ! 1541: the_ins.numargs=opcode->m_opnum; ! 1542: the_ins.numo=opcode->m_codenum; ! 1543: the_ins.opcode[0]=getone(opcode); ! 1544: the_ins.opcode[1]=gettwo(opcode); ! 1545: #ifdef NeXT ! 1546: the_ins.cpus=opcode->m_cpus; ! 1547: #endif /* NeXT */ ! 1548: ! 1549: for(s=the_ins.args,opP= &the_ins.operands[0];*s;s+=2,opP++) { ! 1550: /* This switch is a doozy. ! 1551: What the first step; its a big one! */ ! 1552: switch(s[0]) { ! 1553: ! 1554: case '*': ! 1555: case '~': ! 1556: case '%': ! 1557: case ';': ! 1558: case '@': ! 1559: case '!': ! 1560: case '&': ! 1561: case '$': ! 1562: case '?': ! 1563: case '/': ! 1564: #ifdef m68851 ! 1565: case '|': ! 1566: #endif ! 1567: switch(opP->mode) { ! 1568: case IMMED: ! 1569: tmpreg=0x3c; /* 7.4 */ ! 1570: if(index("bwzl",s[1])) ! 1571: nextword=get_num(opP->con1,80); ! 1572: else ! 1573: nextword=get_num(opP->con1,0); ! 1574: if(isvar(opP->con1)) ! 1575: add_fix(s[1],opP->con1,0); ! 1576: switch(s[1]) { ! 1577: case 'b': ! 1578: if(!isbyte(nextword)) ! 1579: opP->error="operand out of range"; ! 1580: addword(nextword); ! 1581: baseo=0; ! 1582: break; ! 1583: case 'w': ! 1584: case 'z': ! 1585: #ifdef CHECK_WORD_IMMEDIATES ! 1586: if(!isword(nextword)) ! 1587: opP->error="operand out of range"; ! 1588: #endif ! 1589: addword(nextword); ! 1590: baseo=0; ! 1591: break; ! 1592: #ifdef NeXT /* Used in the fmoveml (control) registers */ ! 1593: case 's': ! 1594: #endif /* NeXT */ ! 1595: case 'l': ! 1596: addword(nextword>>16); ! 1597: addword(nextword); ! 1598: baseo=0; ! 1599: break; ! 1600: ! 1601: case 'f': ! 1602: baseo=2; ! 1603: outro=8; ! 1604: break; ! 1605: case 'F': ! 1606: baseo=4; ! 1607: outro=11; ! 1608: break; ! 1609: case 'x': ! 1610: baseo=6; ! 1611: outro=15; ! 1612: break; ! 1613: #ifdef PACKED_IMMEDIATE ! 1614: /* This does not work. The call to gen_to_words() below does not put out ! 1615: 68k packed decimal format. */ ! 1616: case 'p': ! 1617: baseo=6; ! 1618: outro= -1; ! 1619: break; ! 1620: #endif ! 1621: default: ! 1622: as_fatal("Internal error: Can't decode %c%c",*s,s[1]); ! 1623: } ! 1624: if(!baseo) ! 1625: break; ! 1626: ! 1627: /* We gotta put out some float */ ! 1628: if(seg(opP->con1)!=SEG_BIG) { ! 1629: int_to_gen(nextword); ! 1630: gen_to_words(words,baseo,(long int)outro); ! 1631: for(wordp=words;baseo--;wordp++) ! 1632: addword(*wordp); ! 1633: break; ! 1634: } /* Its BIG */ ! 1635: if(offs(opP->con1)>0) { ! 1636: #ifndef NeXT /* fix for bug #8331 */ ! 1637: as_warn("Bignum assumed to be binary bit-pattern"); ! 1638: #endif /* NeXT */ ! 1639: if(offs(opP->con1)>baseo) { ! 1640: as_warn("Bignum too big for %c format; truncated",s[1]); ! 1641: offs(opP->con1)=baseo; ! 1642: } ! 1643: baseo-=offs(opP->con1); ! 1644: for(wordp=generic_bignum+offs(opP->con1)-1;offs(opP->con1)--;--wordp) ! 1645: addword(*wordp); ! 1646: while(baseo--) ! 1647: addword(0); ! 1648: break; ! 1649: } ! 1650: gen_to_words(words,baseo,(long int)outro); ! 1651: for(wordp=words;baseo--;wordp++) ! 1652: addword(*wordp); ! 1653: break; ! 1654: case DREG: ! 1655: tmpreg=opP->reg-DATA; /* 0.dreg */ ! 1656: break; ! 1657: case AREG: ! 1658: tmpreg=0x08+opP->reg-ADDR; /* 1.areg */ ! 1659: break; ! 1660: case AINDR: ! 1661: #ifdef NeXT ! 1662: /* fixes "pc@" operand */ ! 1663: if(opP->reg==PC){ ! 1664: tmpreg=0x3A; /* 7.2 */ ! 1665: addword(0x0000); ! 1666: } ! 1667: else ! 1668: #endif /* NeXT */ ! 1669: tmpreg=0x10+opP->reg-ADDR; /* 2.areg */ ! 1670: break; ! 1671: case ADEC: ! 1672: tmpreg=0x20+opP->reg-ADDR; /* 4.areg */ ! 1673: break; ! 1674: case AINC: ! 1675: tmpreg=0x18+opP->reg-ADDR; /* 3.areg */ ! 1676: break; ! 1677: case AOFF: ! 1678: if(opP->reg==PC) ! 1679: tmpreg=0x3A; /* 7.2 */ ! 1680: else ! 1681: tmpreg=0x28+opP->reg-ADDR; /* 5.areg */ ! 1682: nextword=get_num(opP->con1,80); ! 1683: /* Force into index mode. Hope this works */ ! 1684: if(!issword(nextword)) { ! 1685: if(opP->reg==PC) ! 1686: tmpreg=0x3B; /* 7.3 */ ! 1687: else ! 1688: tmpreg=0x30+opP->reg-ADDR; /* 6.areg */ ! 1689: /* addword(0x0171); */ ! 1690: /* 171 seems to be wrong, and I can't find the 68020 manual, so we'll try 170 ! 1691: (which is what the Sun asm seems to generate */ ! 1692: addword(0x0170); ! 1693: if(isvar(opP->con1)) ! 1694: add_fix('l',opP->con1,0); ! 1695: addword(nextword>>16); ! 1696: /* addword(nextword); */ ! 1697: } else if(isvar(opP->con1)) { ! 1698: if(!flagseen['l'] && ! 1699: flagseen['k'] && ! 1700: seg(opP->con1) != SEG_DIFFSECT) ! 1701: { ! 1702: add_fix('w',opP->con1,0); ! 1703: } else { ! 1704: if(opP->reg==PC) ! 1705: tmpreg=0x3B; /* 7.3 */ ! 1706: else ! 1707: tmpreg=0x30+opP->reg-ADDR; ! 1708: addword(0x0170); ! 1709: /* ! 1710: * If this is a pc register with ! 1711: * a SEGDIFF where the -symbol ! 1712: * is "." adjust the value of ! 1713: * of "." to include the two ! 1714: * bytes of opcode. ! 1715: */ ! 1716: if(opP->reg==PC && ! 1717: seg(opP->con1) == ! 1718: SEG_DIFFSECT && ! 1719: opP->con1-> ! 1720: e_exp.X_subtract_symbol-> ! 1721: sy_frag == frag_now && ! 1722: strcmp(opP->con1-> ! 1723: e_exp.X_subtract_symbol-> ! 1724: sy_nlist.n_un.n_name, ! 1725: "L0\001") == 0) ! 1726: opP->con1-> ! 1727: e_exp.X_subtract_symbol-> ! 1728: sy_nlist.n_value += 2; ! 1729: add_fix('l',opP->con1,0); ! 1730: addword(nextword>>16); ! 1731: } ! 1732: } ! 1733: addword(nextword); ! 1734: break; ! 1735: case AINDX: ! 1736: case APODX: ! 1737: case AMIND: ! 1738: case APRDX: ! 1739: nextword=0; ! 1740: baseo=get_num(opP->con1,80); ! 1741: outro=get_num(opP->con2,80); ! 1742: /* Figure out the 'addressing mode' */ ! 1743: /* Also turn on the BASE_DISABLE bit, if needed */ ! 1744: if(opP->reg==PC || opP->reg==ZPC) { ! 1745: tmpreg=0x3b; /* 7.3 */ ! 1746: if(opP->reg==ZPC) ! 1747: nextword|=0x80; ! 1748: } else if(opP->reg==FAIL) { ! 1749: nextword|=0x80; ! 1750: tmpreg=0x30; /* 6.garbage */ ! 1751: } else tmpreg=0x30+opP->reg-ADDR; /* 6.areg */ ! 1752: ! 1753: siz1= (opP->con1) ? opP->con1->e_siz : 0; ! 1754: siz2= (opP->con2) ? opP->con2->e_siz : 0; ! 1755: ! 1756: /* Index register stuff */ ! 1757: if(opP->ireg>=DATA+0 && opP->ireg<=ADDR+7) { ! 1758: nextword|=(opP->ireg-DATA)<<12; ! 1759: ! 1760: if(opP->isiz==0 || opP->isiz==3) ! 1761: nextword|=0x800; ! 1762: switch(opP->imul) { ! 1763: case 1: break; ! 1764: case 2: nextword|=0x200; break; ! 1765: case 4: nextword|=0x400; break; ! 1766: case 8: nextword|=0x600; break; ! 1767: default: abort(); ! 1768: } ! 1769: /* IF its simple, GET US OUT OF HERE! */ ! 1770: /* Must be INDEX, with an index register. Address register ! 1771: cannot be ZERO-PC, and either :b was forced, or we know it'll fit */ ! 1772: if(opP->mode==AINDX && ! 1773: opP->reg!=FAIL && opP->reg!=ZPC && (siz1==1 || (issbyte(baseo) && ! 1774: !isvar(opP->con1)))) { ! 1775: nextword +=baseo&0xff; ! 1776: addword(nextword); ! 1777: if(isvar(opP->con1)) ! 1778: add_fix('B',opP->con1,0); ! 1779: break; ! 1780: } ! 1781: } else ! 1782: nextword|=0x40; /* No index reg */ ! 1783: ! 1784: /* It aint simple */ ! 1785: nextword|=0x100; ! 1786: /* If the guy specified a width, we assume that ! 1787: it is wide enough. Maybe it isn't. Ifso, we lose ! 1788: */ ! 1789: switch(siz1) { ! 1790: case 0: ! 1791: if(isvar(opP->con1) || !issword(baseo)) { ! 1792: siz1=3; ! 1793: nextword|=0x30; ! 1794: } else if(baseo==0) ! 1795: nextword|=0x10; ! 1796: else { ! 1797: nextword|=0x20; ! 1798: siz1=2; ! 1799: } ! 1800: break; ! 1801: case 1: ! 1802: as_warn("Byte dispacement won't work. Defaulting to :w"); ! 1803: case 2: ! 1804: nextword|=0x20; ! 1805: break; ! 1806: case 3: ! 1807: nextword|=0x30; ! 1808: break; ! 1809: } ! 1810: ! 1811: /* Figure out innner displacement stuff */ ! 1812: if(opP->mode!=AINDX) { ! 1813: switch(siz2) { ! 1814: case 0: ! 1815: if(isvar(opP->con2) || !issword(outro)) { ! 1816: siz2=3; ! 1817: nextword|=0x3; ! 1818: } else if(outro==0) ! 1819: nextword|=0x1; ! 1820: else { ! 1821: nextword|=0x2; ! 1822: siz2=2; ! 1823: } ! 1824: break; ! 1825: case 1: ! 1826: as_warn("Byte dispacement won't work. Defaulting to :w"); ! 1827: case 2: ! 1828: nextword|=0x2; ! 1829: break; ! 1830: case 3: ! 1831: nextword|=0x3; ! 1832: break; ! 1833: } ! 1834: if(opP->mode==APODX) nextword|=0x04; ! 1835: else if(opP->mode==AMIND) nextword|=0x40; ! 1836: } ! 1837: addword(nextword); ! 1838: ! 1839: if(isvar(opP->con1)) ! 1840: add_fix(siz1==3 ? 'l' : 'w',opP->con1,0); ! 1841: if(siz1==3) ! 1842: addword(baseo>>16); ! 1843: if(siz1) ! 1844: addword(baseo); ! 1845: ! 1846: if(isvar(opP->con2)) ! 1847: add_fix(siz2==3 ? 'l' : 'w',opP->con2,0); ! 1848: if(siz2==3) ! 1849: addword(outro>>16); ! 1850: if(siz2) ! 1851: addword(outro); ! 1852: ! 1853: break; ! 1854: ! 1855: case ABSL: ! 1856: nextword=get_num(opP->con1,80); ! 1857: switch(opP->con1->e_siz) { ! 1858: case 1: /* treat like not there, fall through */ ! 1859: as_warn("ignoring :b suffix on %*s", ! 1860: (int)(opP->con1->e_end-opP->con1->e_beg), ! 1861: opP->con1->e_beg); ! 1862: case 0: ! 1863: if(!isvar(opP->con1) && ! 1864: issword(offs(opP->con1))) { ! 1865: tmpreg=0x38; /* 7.0 */ ! 1866: addword(nextword); ! 1867: break; ! 1868: } ! 1869: /* Don't generate pc relative code ! 1870: on 68010 and 68000 */ ! 1871: if(isvar(opP->con1) && ! 1872: !subs(opP->con1) && ! 1873: seg(opP->con1) == SEG_SECT && ! 1874: frchain_now->frch_nsect == ! 1875: opP->con1->e_exp.X_add_symbol-> ! 1876: sy_nlist.n_sect && ! 1877: flagseen['m'] == 0 && ! 1878: !index("~%&$?", s[0])) { ! 1879: tmpreg=0x3A; /* 7.2 */ ! 1880: add_frag(adds(opP->con1), ! 1881: offs(opP->con1), ! 1882: TAB(PCREL,SZ_UNDEF)); ! 1883: break; ! 1884: } ! 1885: case 3: /* Fall through into long */ ! 1886: if(isvar(opP->con1)) ! 1887: add_fix('l',opP->con1,0); ! 1888: ! 1889: tmpreg=0x39; /* 7.1 mode */ ! 1890: addword(nextword>>16); ! 1891: addword(nextword); ! 1892: break; ! 1893: ! 1894: case 2: /* Word */ ! 1895: if(isvar(opP->con1)) ! 1896: add_fix('w',opP->con1,0); ! 1897: ! 1898: tmpreg=0x38; /* 7.0 mode */ ! 1899: addword(nextword); ! 1900: break; ! 1901: } ! 1902: break; ! 1903: case MSCR: ! 1904: default: ! 1905: as_bad("unknown/incorrect operand"); ! 1906: /* abort(); */ ! 1907: } ! 1908: install_gen_operand(s[1],tmpreg); ! 1909: break; ! 1910: ! 1911: case '#': ! 1912: case '^': ! 1913: switch(s[1]) { /* JF: I hate floating point! */ ! 1914: case 'j': ! 1915: tmpreg=70; ! 1916: break; ! 1917: case '8': ! 1918: tmpreg=20; ! 1919: break; ! 1920: case 'C': ! 1921: tmpreg=50; ! 1922: break; ! 1923: case '3': ! 1924: default: ! 1925: tmpreg=80; ! 1926: break; ! 1927: } ! 1928: tmpreg=get_num(opP->con1,tmpreg); ! 1929: if(isvar(opP->con1)) ! 1930: add_fix(s[1],opP->con1,0); ! 1931: switch(s[1]) { ! 1932: case 'b': /* Danger: These do no check for ! 1933: certain types of overflow. ! 1934: user beware! */ ! 1935: if(!isbyte(tmpreg)) ! 1936: opP->error="out of range"; ! 1937: insop(tmpreg); ! 1938: if(isvar(opP->con1)) ! 1939: the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2; ! 1940: break; ! 1941: #ifdef NeXT ! 1942: case 'j': ! 1943: if(tmpreg < 0 || tmpreg > 0xfff) ! 1944: opP->error="out of range"; ! 1945: tmpreg&=0xFFF; ! 1946: install_operand(s[1],tmpreg); ! 1947: break; ! 1948: #endif /* NeXT */ ! 1949: case 'w': ! 1950: case 'z': ! 1951: #ifdef CHECK_WORD_IMMEDIATES ! 1952: if(!isword(tmpreg)) ! 1953: opP->error="out of range"; ! 1954: #endif ! 1955: insop(tmpreg); ! 1956: if(isvar(opP->con1)) ! 1957: the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2; ! 1958: break; ! 1959: case 'l': ! 1960: insop(tmpreg); /* Because of the way insop works, we put these two out backwards */ ! 1961: insop(tmpreg>>16); ! 1962: if(isvar(opP->con1)) ! 1963: the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2; ! 1964: break; ! 1965: case '3': ! 1966: tmpreg&=0xFF; ! 1967: #ifdef NeXT ! 1968: if (isvar(opP->con1)) ! 1969: the_ins.reloc[the_ins.nrel-1].n = ! 1970: (opcode->m_codenum) + 1; ! 1971: #endif /* NeXT */ ! 1972: case '8': ! 1973: case 'C': ! 1974: install_operand(s[1],tmpreg); ! 1975: break; ! 1976: default: ! 1977: as_fatal("Internal error: Unknown mode #%c",s[1]); ! 1978: } ! 1979: break; ! 1980: ! 1981: case '+': ! 1982: case '-': ! 1983: case 'A': ! 1984: install_operand(s[1],opP->reg-ADDR); ! 1985: break; ! 1986: ! 1987: case 'B': ! 1988: tmpreg = get_num(opP->con1, 80); ! 1989: switch(s[1]){ ! 1990: case 'g': ! 1991: /* Deal with fixed size stuff by hand */ ! 1992: if(opP->con1->e_siz){ ! 1993: switch(opP->con1->e_siz){ ! 1994: case 1: ! 1995: add_fix('B', opP->con1, 1); ! 1996: break; ! 1997: case 2: ! 1998: if(strncmp(instring, "jbsr", 4) == 0){ ! 1999: if(isvar(opP->con1)) ! 2000: add_fix('w', opP->con1, 0); ! 2001: /* force a jsr 7.0 mode (xxx):W */ ! 2002: the_ins.opcode[the_ins.numo-1] = 0x4eb8; ! 2003: addword(tmpreg); ! 2004: break; ! 2005: } ! 2006: if(strncmp(instring, "jra", 3) == 0){ ! 2007: if(isvar(opP->con1)) ! 2008: add_fix('w', opP->con1, 0); ! 2009: /* force a jmp 7.0 mode (xxx):W */ ! 2010: the_ins.opcode[the_ins.numo-1] = 0x4ef8; ! 2011: addword(tmpreg); ! 2012: break; ! 2013: } ! 2014: opP->con1->e_exp.X_add_number += 2; ! 2015: add_fix('w', opP->con1, 1); ! 2016: addword(0); ! 2017: break; ! 2018: case 3: ! 2019: the_ins.opcode[the_ins.numo-1] |= 0xff; ! 2020: opP->con1->e_exp.X_add_number += 4; ! 2021: add_fix('l', opP->con1, 1); ! 2022: addword(0); ! 2023: addword(0); ! 2024: break; ! 2025: default: ! 2026: as_fatal("Bad size for expression %d", ! 2027: opP->con1->e_siz); ! 2028: } ! 2029: } ! 2030: else if(subs(opP->con1)){ ! 2031: /* We can't relax it */ ! 2032: the_ins.opcode[the_ins.numo-1] |= 0xff; ! 2033: add_fix('l', opP->con1, 1); ! 2034: addword(0); ! 2035: addword(0); ! 2036: } ! 2037: else if(adds(opP->con1)){ ! 2038: if(flagseen['m'] && ! 2039: (the_ins.opcode[0] >= 0x6200) && ! 2040: (the_ins.opcode[0] <= 0x6f00)){ ! 2041: add_frag(adds(opP->con1), ! 2042: offs(opP->con1), ! 2043: TAB(BCC68000, SZ_UNDEF)); ! 2044: } ! 2045: else{ ! 2046: add_frag(adds(opP->con1), ! 2047: offs(opP->con1), ! 2048: TAB(BRANCH, SZ_UNDEF)); ! 2049: } ! 2050: } ! 2051: else{ ! 2052: the_ins.opcode[the_ins.numo-1] |= 0xff; ! 2053: opP->con1->e_exp.X_add_number += 4; ! 2054: add_fix('l', opP->con1, 1); ! 2055: addword(0); ! 2056: addword(0); ! 2057: } ! 2058: break; ! 2059: case 'w': ! 2060: if(isvar(opP->con1)){ ! 2061: /* check for DBcc instruction */ ! 2062: if((the_ins.opcode[0] & 0xf0f8) ==0x50c8){ ! 2063: /* size varies if patch */ ! 2064: /* needed for long form */ ! 2065: add_frag(adds(opP->con1), ! 2066: offs(opP->con1), ! 2067: TAB(DBCC, SZ_UNDEF)); ! 2068: break; ! 2069: } ! 2070: } ! 2071: opP->con1->e_exp.X_add_number += 2; ! 2072: add_fix('w', opP->con1, 1); ! 2073: addword(0); ! 2074: break; ! 2075: case 'c': ! 2076: if(opP->con1->e_siz){ ! 2077: switch(opP->con1->e_siz){ ! 2078: case 2: ! 2079: opP->con1->e_exp.X_add_number += 2; ! 2080: add_fix('w', opP->con1, 1); ! 2081: addword(0); ! 2082: break; ! 2083: case 3: ! 2084: the_ins.opcode[the_ins.numo-1] |= 0x40; ! 2085: opP->con1->e_exp.X_add_number += 4; ! 2086: add_fix('l', opP->con1, 1); ! 2087: addword(0); ! 2088: addword(0); ! 2089: break; ! 2090: default: ! 2091: as_bad("Bad size for offset, must be word " ! 2092: "or long"); ! 2093: break; ! 2094: } ! 2095: } ! 2096: else if(subs(opP->con1)){ ! 2097: /* We can't relax it */ ! 2098: the_ins.opcode[the_ins.numo-1] |= 0x40; ! 2099: add_fix('l', opP->con1, 1); ! 2100: addword(0); ! 2101: addword(0); ! 2102: } ! 2103: else if(adds(opP->con1)){ ! 2104: add_frag(adds(opP->con1), ! 2105: offs(opP->con1), ! 2106: TAB(FBRANCH, SZ_UNDEF)); ! 2107: } ! 2108: else{ ! 2109: the_ins.opcode[the_ins.numo-1] |= 0x40; ! 2110: opP->con1->e_exp.X_add_number += 4; ! 2111: add_fix('l', opP->con1, 1); ! 2112: addword(0); ! 2113: addword(0); ! 2114: } ! 2115: break; ! 2116: default: ! 2117: as_fatal("Internal error: operand type B%c unknown", ! 2118: s[1]); ! 2119: } ! 2120: break; ! 2121: ! 2122: case 'C': /* Ignore it */ ! 2123: break; ! 2124: ! 2125: case 'd': /* JF this is a kludge */ ! 2126: if(opP->mode==AOFF) { ! 2127: install_operand('s',opP->reg-ADDR); ! 2128: } else { ! 2129: char *tmpP; ! 2130: ! 2131: tmpP=opP->con1->e_end-2; ! 2132: opP->con1->e_beg++; ! 2133: opP->con1->e_end-=4; /* point to the , */ ! 2134: baseo=m68k_reg_parse(&tmpP); ! 2135: if(baseo<ADDR+0 || baseo>ADDR+7) { ! 2136: as_bad("Unknown address reg, using A0"); ! 2137: baseo=0; ! 2138: } else baseo-=ADDR; ! 2139: install_operand('s',baseo); ! 2140: } ! 2141: tmpreg=get_num(opP->con1,80); ! 2142: if(!issword(tmpreg)) { ! 2143: as_warn("Expression out of range, using 0"); ! 2144: tmpreg=0; ! 2145: } ! 2146: addword(tmpreg); ! 2147: break; ! 2148: ! 2149: case 'D': ! 2150: install_operand(s[1],opP->reg-DATA); ! 2151: break; ! 2152: ! 2153: case 'F': ! 2154: install_operand(s[1],opP->reg-FPREG); ! 2155: break; ! 2156: ! 2157: case 'I': ! 2158: tmpreg=1+opP->reg-COPNUM; ! 2159: if(tmpreg==8) ! 2160: tmpreg=0; ! 2161: install_operand(s[1],tmpreg); ! 2162: break; ! 2163: ! 2164: case 'J': /* JF foo */ ! 2165: switch(opP->reg) { ! 2166: case SFC: ! 2167: tmpreg=0; ! 2168: break; ! 2169: case DFC: ! 2170: tmpreg=0x001; ! 2171: break; ! 2172: case CACR: ! 2173: tmpreg=0x002; ! 2174: break; ! 2175: case USP: ! 2176: tmpreg=0x800; ! 2177: break; ! 2178: case VBR: ! 2179: tmpreg=0x801; ! 2180: break; ! 2181: case CAAR: ! 2182: tmpreg=0x802; ! 2183: break; ! 2184: case MSP: ! 2185: tmpreg=0x803; ! 2186: break; ! 2187: case ISP: ! 2188: tmpreg=0x804; ! 2189: break; ! 2190: #ifdef BUILTIN_MMUS ! 2191: case TC: ! 2192: tmpreg=0x003; ! 2193: break; ! 2194: case ITT0: ! 2195: tmpreg=0x004; ! 2196: break; ! 2197: case ITT1: ! 2198: tmpreg=0x005; ! 2199: break; ! 2200: case DTT0: ! 2201: tmpreg=0x006; ! 2202: break; ! 2203: case DTT1: ! 2204: tmpreg=0x007; ! 2205: break; ! 2206: case MMUSR: ! 2207: tmpreg=0x805; ! 2208: break; ! 2209: case URP: ! 2210: tmpreg=0x806; ! 2211: break; ! 2212: case SRP: ! 2213: tmpreg=0x807; ! 2214: break; ! 2215: #endif /* BUILTIN_MMUS */ ! 2216: default: ! 2217: abort(); ! 2218: } ! 2219: install_operand(s[1],tmpreg); ! 2220: break; ! 2221: #ifdef NeXT ! 2222: case '0': ! 2223: tmpreg=opP->reg-ADDR; ! 2224: install_operand(s[1],tmpreg); ! 2225: break; ! 2226: #endif /* NeXT */ ! 2227: ! 2228: case 'k': ! 2229: tmpreg=get_num(opP->con1,55); ! 2230: install_operand(s[1],tmpreg&0x7f); ! 2231: break; ! 2232: ! 2233: case 'l': ! 2234: tmpreg=opP->reg; ! 2235: if(s[1]=='w') { ! 2236: if(tmpreg&0x7FF0000) ! 2237: as_bad("Floating point register in register list"); ! 2238: insop(reverse_16_bits(tmpreg)); ! 2239: } else { ! 2240: if(tmpreg&0x700FFFF) ! 2241: as_bad("Wrong register in floating-point reglist"); ! 2242: install_operand(s[1],reverse_8_bits(tmpreg>>16)); ! 2243: } ! 2244: break; ! 2245: ! 2246: case 'L': ! 2247: tmpreg=opP->reg; ! 2248: if(s[1]=='w') { ! 2249: if(tmpreg&0x7FF0000) ! 2250: as_bad("Floating point register in register list"); ! 2251: insop(tmpreg); ! 2252: } else if(s[1]=='8') { ! 2253: if(tmpreg&0x0FFFFFF) ! 2254: as_bad("incorrect register in reglist"); ! 2255: install_operand(s[1],tmpreg>>24); ! 2256: } else { ! 2257: if(tmpreg&0x700FFFF) ! 2258: as_bad("wrong register in floating-point reglist"); ! 2259: else ! 2260: install_operand(s[1],tmpreg>>16); ! 2261: } ! 2262: break; ! 2263: ! 2264: case 'M': ! 2265: install_operand(s[1],get_num(opP->con1,60)); ! 2266: break; ! 2267: ! 2268: case 'O': ! 2269: tmpreg= (opP->mode==DREG) ! 2270: ? 0x20+opP->reg-DATA ! 2271: : (get_num(opP->con1,40)&0x1F); ! 2272: install_operand(s[1],tmpreg); ! 2273: break; ! 2274: ! 2275: case 'Q': ! 2276: tmpreg=get_num(opP->con1,10); ! 2277: if(tmpreg==8) ! 2278: tmpreg=0; ! 2279: install_operand(s[1],tmpreg); ! 2280: break; ! 2281: ! 2282: case 'R': ! 2283: /* This depends on the fact that ADDR registers are ! 2284: eight more than their corresponding DATA regs, so ! 2285: the result will have the ADDR_REG bit set */ ! 2286: install_operand(s[1],opP->reg-DATA); ! 2287: break; ! 2288: ! 2289: case 's': ! 2290: if(opP->reg==FPI) tmpreg=0x1; ! 2291: else if(opP->reg==FPS) tmpreg=0x2; ! 2292: else if(opP->reg==FPC) tmpreg=0x4; ! 2293: else abort(); ! 2294: install_operand(s[1],tmpreg); ! 2295: break; ! 2296: ! 2297: case 'S': /* Ignore it */ ! 2298: break; ! 2299: ! 2300: case 'T': ! 2301: install_operand(s[1],get_num(opP->con1,30)); ! 2302: break; ! 2303: ! 2304: case 'U': /* Ignore it */ ! 2305: break; ! 2306: ! 2307: #if defined(m68851) || defined(BUILTIN_MMUS) ! 2308: /* JF: These are out of order, I fear. */ ! 2309: case 'f': ! 2310: switch (opP->reg) { ! 2311: case SFC: ! 2312: tmpreg=0; ! 2313: break; ! 2314: case DFC: ! 2315: tmpreg=1; ! 2316: break; ! 2317: default: ! 2318: abort(); ! 2319: } ! 2320: install_operand(s[1],tmpreg); ! 2321: break; ! 2322: #endif ! 2323: ! 2324: #ifdef BUILTIN_MMUS ! 2325: case 'a': ! 2326: switch (opP->reg) { ! 2327: case SRP: ! 2328: tmpreg=2; ! 2329: break; ! 2330: case CRP: ! 2331: tmpreg=3; ! 2332: break; ! 2333: case TC: ! 2334: tmpreg=0; ! 2335: break; ! 2336: default: ! 2337: abort(); ! 2338: } ! 2339: install_operand(s[1],tmpreg); ! 2340: break; ! 2341: case 'b': ! 2342: switch (opP->reg) { ! 2343: case MMUSR: ! 2344: tmpreg=0; ! 2345: break; ! 2346: default: ! 2347: abort(); ! 2348: } ! 2349: install_operand(s[1],tmpreg); ! 2350: break; ! 2351: case 'c': ! 2352: switch (opP->reg) { ! 2353: case IC: ! 2354: tmpreg=2; ! 2355: break; ! 2356: case DC: ! 2357: tmpreg=1; ! 2358: break; ! 2359: case BC: ! 2360: tmpreg=3; ! 2361: break; ! 2362: default: ! 2363: abort(); ! 2364: } ! 2365: install_operand(s[1],tmpreg); ! 2366: break; ! 2367: case 'e': ! 2368: switch (opP->reg) { ! 2369: case TT0: ! 2370: tmpreg=2; ! 2371: break; ! 2372: case TT1: ! 2373: tmpreg=3; ! 2374: break; ! 2375: default: ! 2376: abort(); ! 2377: } ! 2378: install_operand(s[1],tmpreg); ! 2379: break; ! 2380: #endif ! 2381: ! 2382: #ifdef m68851 ! 2383: case 'P': ! 2384: switch(opP->reg) { ! 2385: case TC: ! 2386: tmpreg=0; ! 2387: break; ! 2388: case CAL: ! 2389: tmpreg=4; ! 2390: break; ! 2391: case VAL: ! 2392: tmpreg=5; ! 2393: break; ! 2394: case SCC: ! 2395: tmpreg=6; ! 2396: break; ! 2397: case AC: ! 2398: tmpreg=7; ! 2399: break; ! 2400: default: ! 2401: abort(); ! 2402: } ! 2403: install_operand(s[1],tmpreg); ! 2404: break; ! 2405: ! 2406: case 'V': ! 2407: if (opP->reg == VAL) ! 2408: break; ! 2409: abort(); ! 2410: ! 2411: case 'W': ! 2412: switch(opP->reg) { ! 2413: ! 2414: case DRP: ! 2415: tmpreg=1; ! 2416: break; ! 2417: case SRP: ! 2418: tmpreg=2; ! 2419: break; ! 2420: case CRP: ! 2421: tmpreg=3; ! 2422: break; ! 2423: default: ! 2424: abort(); ! 2425: } ! 2426: install_operand(s[1],tmpreg); ! 2427: break; ! 2428: ! 2429: case 'X': ! 2430: switch (opP->reg) { ! 2431: case BAD: case BAD+1: case BAD+2: case BAD+3: ! 2432: case BAD+4: case BAD+5: case BAD+6: case BAD+7: ! 2433: tmpreg = (4 << 10) | ((opP->reg - BAD) << 2); ! 2434: break; ! 2435: ! 2436: case BAC: case BAC+1: case BAC+2: case BAC+3: ! 2437: case BAC+4: case BAC+5: case BAC+6: case BAC+7: ! 2438: tmpreg = (5 << 10) | ((opP->reg - BAC) << 2); ! 2439: break; ! 2440: ! 2441: default: ! 2442: abort(); ! 2443: } ! 2444: install_operand(s[1], tmpreg); ! 2445: break; ! 2446: case 'Y': ! 2447: if (opP->reg == PSR) ! 2448: break; ! 2449: abort(); ! 2450: ! 2451: case 'Z': ! 2452: if (opP->reg == PCSR) ! 2453: break; ! 2454: abort(); ! 2455: #endif /* m68851 */ ! 2456: default: ! 2457: as_fatal("Internal error: Operand type %c unknown",s[0]); ! 2458: } ! 2459: } ! 2460: /* By the time whe get here (FINALLY) the_ins contains the complete ! 2461: instruction, ready to be emitted. . . */ ! 2462: } ! 2463: ! 2464: static ! 2465: int ! 2466: get_regs( ! 2467: int i, ! 2468: struct m68k_op *opP, ! 2469: char *str) ! 2470: { ! 2471: /* 26, 25, 24, 23-16, 15-8, 0-7 */ ! 2472: /* Low order 24 bits encoded fpc,fps,fpi,fp7-fp0,a7-a0,d7-d0 */ ! 2473: unsigned long int cur_regs = 0; ! 2474: int reg1, ! 2475: reg2; ! 2476: ! 2477: #define ADD_REG(x) { if(x==FPI) cur_regs|=(1<<24);\ ! 2478: else if(x==FPS) cur_regs|=(1<<25);\ ! 2479: else if(x==FPC) cur_regs|=(1<<26);\ ! 2480: else cur_regs|=(1<<(x-1)); } ! 2481: ! 2482: reg1=i; ! 2483: for(;;) { ! 2484: if(*str=='/') { ! 2485: ADD_REG(reg1); ! 2486: str++; ! 2487: } else if(*str=='-') { ! 2488: str++; ! 2489: reg2=m68k_reg_parse(&str); ! 2490: if(reg2<DATA || reg2>=FPREG+8 || reg1==FPI || reg1==FPS || reg1==FPC) { ! 2491: opP->error="unknown register in register list"; ! 2492: return FAIL; ! 2493: } ! 2494: while(reg1<=reg2) { ! 2495: ADD_REG(reg1); ! 2496: reg1++; ! 2497: } ! 2498: if(*str=='\0') ! 2499: break; ! 2500: } else if(*str=='\0') { ! 2501: ADD_REG(reg1); ! 2502: break; ! 2503: } else { ! 2504: opP->error="unknow character in register list"; ! 2505: return FAIL; ! 2506: } ! 2507: /* DJA -- Bug Fix. Did't handle d1-d2/a1 until the following instruction was added */ ! 2508: if (*str=='/') ! 2509: str ++; ! 2510: reg1=m68k_reg_parse(&str); ! 2511: if((reg1<DATA || reg1>=FPREG+8) && !(reg1==FPI || reg1==FPS || reg1==FPC)) { ! 2512: opP->error="unknown register in register list"; ! 2513: return FAIL; ! 2514: } ! 2515: } ! 2516: opP->reg=cur_regs; ! 2517: return OK; ! 2518: } ! 2519: ! 2520: static ! 2521: int ! 2522: reverse_16_bits( ! 2523: int in) ! 2524: { ! 2525: int out=0; ! 2526: int n; ! 2527: ! 2528: static int mask[16] = { ! 2529: 0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, ! 2530: 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000 ! 2531: }; ! 2532: for(n=0;n<16;n++) { ! 2533: if(in&mask[n]) ! 2534: out|=mask[15-n]; ! 2535: } ! 2536: return out; ! 2537: } ! 2538: ! 2539: static ! 2540: int ! 2541: reverse_8_bits( ! 2542: int in) ! 2543: { ! 2544: int out=0; ! 2545: int n; ! 2546: ! 2547: static int mask[8] = { ! 2548: 0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, ! 2549: }; ! 2550: ! 2551: for(n=0;n<8;n++) { ! 2552: if(in&mask[n]) ! 2553: out|=mask[7-n]; ! 2554: } ! 2555: return out; ! 2556: } ! 2557: ! 2558: static ! 2559: void ! 2560: install_operand( ! 2561: int mode, ! 2562: int val) ! 2563: { ! 2564: switch(mode) { ! 2565: case 's': ! 2566: the_ins.opcode[0]|=val & 0xFF; /* JF FF is for M kludge */ ! 2567: break; ! 2568: case 'd': ! 2569: the_ins.opcode[0]|=val<<9; ! 2570: break; ! 2571: case '1': ! 2572: the_ins.opcode[1]|=val<<12; ! 2573: break; ! 2574: case '2': ! 2575: the_ins.opcode[1]|=val<<6; ! 2576: break; ! 2577: case '3': ! 2578: the_ins.opcode[1]|=val; ! 2579: break; ! 2580: case '4': ! 2581: the_ins.opcode[2]|=val<<12; ! 2582: break; ! 2583: case '5': ! 2584: the_ins.opcode[2]|=val<<6; ! 2585: break; ! 2586: case '6': ! 2587: /* DANGER! This is a hack to force cas2l and cas2w cmds ! 2588: to be three words long! */ ! 2589: the_ins.numo++; ! 2590: the_ins.opcode[2]|=val; ! 2591: break; ! 2592: case '7': ! 2593: the_ins.opcode[1]|=val<<7; ! 2594: break; ! 2595: case '8': ! 2596: the_ins.opcode[1]|=val<<10; ! 2597: break; ! 2598: #if defined(m68851) || defined(BUILTIN_MMUS) ! 2599: case '9': ! 2600: the_ins.opcode[1]|=val<<5; ! 2601: break; ! 2602: #endif ! 2603: #ifdef BUILTIN_MMUS ! 2604: case 'S': ! 2605: the_ins.opcode[0]|=val<<6; ! 2606: break; ! 2607: #endif ! 2608: case 't': ! 2609: the_ins.opcode[1]|=(val<<10)|(val<<7); ! 2610: break; ! 2611: case 'D': ! 2612: the_ins.opcode[1]|=(val<<12)|val; ! 2613: break; ! 2614: case 'g': ! 2615: the_ins.opcode[0]|=val=0xff; ! 2616: break; ! 2617: case 'i': ! 2618: the_ins.opcode[0]|=val<<9; ! 2619: break; ! 2620: case 'C': ! 2621: the_ins.opcode[1]|=val; ! 2622: break; ! 2623: case 'j': ! 2624: the_ins.opcode[1]|=val; ! 2625: the_ins.numo++; /* What a hack */ ! 2626: break; ! 2627: case 'k': ! 2628: the_ins.opcode[1]|=val<<4; ! 2629: break; ! 2630: case 'b': ! 2631: case 'w': ! 2632: case 'l': ! 2633: break; ! 2634: case 'c': ! 2635: default: ! 2636: abort(); ! 2637: } ! 2638: } ! 2639: ! 2640: static ! 2641: void ! 2642: install_gen_operand( ! 2643: int mode, ! 2644: int val) ! 2645: { ! 2646: switch(mode) { ! 2647: case 's': ! 2648: the_ins.opcode[0]|=val; ! 2649: break; ! 2650: case 'd': ! 2651: /* This is a kludge!!! */ ! 2652: the_ins.opcode[0]|=(val&0x07)<<9|(val&0x38)<<3; ! 2653: break; ! 2654: case 'b': ! 2655: case 'w': ! 2656: case 'l': ! 2657: case 'f': ! 2658: case 'F': ! 2659: case 'x': ! 2660: case 'p': ! 2661: the_ins.opcode[0]|=val; ! 2662: break; ! 2663: /* more stuff goes here */ ! 2664: default: ! 2665: abort(); ! 2666: } ! 2667: } ! 2668: ! 2669: static ! 2670: char * ! 2671: crack_operand( ! 2672: char *str, ! 2673: struct m68k_op *opP) ! 2674: { ! 2675: register int parens; ! 2676: register int c; ! 2677: register char *beg_str; ! 2678: ! 2679: if(!str) { ! 2680: return str; ! 2681: } ! 2682: beg_str=str; ! 2683: for(parens=0;*str && (parens>0 || notend(str));str++) { ! 2684: if(*str == '"') { ! 2685: str++; ! 2686: while(*str && *str != '"') ! 2687: str++; ! 2688: if(*str != '"'){ /* ERROR */ ! 2689: opP->error="Missing \""; ! 2690: return str; ! 2691: } ! 2692: } ! 2693: else{ ! 2694: if(*str=='(') ! 2695: parens++; ! 2696: else if(*str==')') { ! 2697: if(!parens) { /* ERROR */ ! 2698: opP->error="Extra )"; ! 2699: return str; ! 2700: } ! 2701: --parens; ! 2702: } ! 2703: } ! 2704: } ! 2705: if(!*str && parens) { /* ERROR */ ! 2706: opP->error="Missing )"; ! 2707: return str; ! 2708: } ! 2709: c= *str; ! 2710: *str='\0'; ! 2711: if(m68k_ip_op(beg_str,opP)==FAIL) { ! 2712: *str=c; ! 2713: return str; ! 2714: } ! 2715: *str=c; ! 2716: if(c=='}') ! 2717: c= *++str; /* JF bitfield hack */ ! 2718: if(c) { ! 2719: c= *++str; ! 2720: if(!c) ! 2721: as_bad("Missing operand"); ! 2722: } ! 2723: return str; ! 2724: } ! 2725: ! 2726: /* See the comment up above where the #define notend(... is */ ! 2727: #if 0 ! 2728: notend(s) ! 2729: char *s; ! 2730: { ! 2731: if(*s==',') return 0; ! 2732: if(*s=='{' || *s=='}') ! 2733: return 0; ! 2734: if(*s!=':') return 1; ! 2735: /* This kludge here is for the division cmd, which is a kludge */ ! 2736: if(index("aAdD#",s[1])) return 0; ! 2737: return 1; ! 2738: } ! 2739: #endif /* 0 */ ! 2740: ! 2741: #ifdef NeXT ! 2742: static char *file_030, *file_040; ! 2743: static unsigned long line_030, line_040; ! 2744: #endif /* NeXT */ ! 2745: ! 2746: /* This is the guts of the machine-dependent assembler. STR points to a ! 2747: machine dependent instruction. This funciton is supposed to emit ! 2748: the frags/bytes it assembles to. ! 2749: */ ! 2750: void ! 2751: md_assemble( ! 2752: char *str) ! 2753: { ! 2754: char *er; ! 2755: short *fromP; ! 2756: char *toP = NULL; ! 2757: int m,n; ! 2758: char *to_beg_P; ! 2759: int shorts_this_frag; ! 2760: ! 2761: memset((char *)(&the_ins), '\0', sizeof(the_ins)); ! 2762: m68_ip(str); ! 2763: er=the_ins.error; ! 2764: if(!er) { ! 2765: for(n=the_ins.numargs;n;--n) ! 2766: if(the_ins.operands[n].error) { ! 2767: er=the_ins.operands[n].error; ! 2768: break; ! 2769: } ! 2770: } ! 2771: if(er) { ! 2772: as_bad("\"%s\" -- Statement '%s' ignored",er,str); ! 2773: return; ! 2774: } ! 2775: ! 2776: #ifdef NeXT ! 2777: if(the_ins.cpus != NULL && !force_cpusubtype_ALL){ ! 2778: if(md_cpusubtype == CPU_SUBTYPE_MC680x0_ALL){ ! 2779: switch(*the_ins.cpus){ ! 2780: case '2': ! 2781: as_bad("implementation specific instruction for the MC68020" ! 2782: " and -force_cpusubtype_ALL not specified"); ! 2783: break; ! 2784: case '3': ! 2785: if(archflag_cpusubtype == CPU_SUBTYPE_MC68040) ! 2786: as_bad("030 instruction not allowed with -arch m68040"); ! 2787: else{ ! 2788: file_030 = logical_input_file ? ! 2789: logical_input_file : physical_input_file; ! 2790: line_030 = logical_input_line ? ! 2791: logical_input_line : physical_input_line; ! 2792: md_cpusubtype = CPU_SUBTYPE_MC68030_ONLY; ! 2793: } ! 2794: break; ! 2795: case '4': ! 2796: if(archflag_cpusubtype == CPU_SUBTYPE_MC68030_ONLY) ! 2797: as_bad("040 instruction not allowed with -arch m68030"); ! 2798: else{ ! 2799: file_040 = logical_input_file ? ! 2800: logical_input_file : physical_input_file; ! 2801: line_040 = logical_input_line ? ! 2802: logical_input_line : physical_input_line; ! 2803: md_cpusubtype = CPU_SUBTYPE_MC68040; ! 2804: } ! 2805: break; ! 2806: } ! 2807: } ! 2808: else{ ! 2809: switch(*the_ins.cpus){ ! 2810: case '2': ! 2811: as_bad("implementation specific instruction for the MC68020" ! 2812: " and -force_cpusubtype_ALL not specified"); ! 2813: break; ! 2814: case '3': ! 2815: if(archflag_cpusubtype == CPU_SUBTYPE_MC68040) ! 2816: as_bad("030 instruction not allowed with -arch m68040"); ! 2817: else{ ! 2818: if(md_cpusubtype != CPU_SUBTYPE_MC680x0_ALL && ! 2819: md_cpusubtype != CPU_SUBTYPE_MC68030_ONLY) ! 2820: as_bad("more than one implementation specific " ! 2821: "instruction seen and -force_cpusubtype_ALL " ! 2822: " not specified (first 040 instruction in: " ! 2823: "%s at line %lu)", file_040, line_040); ! 2824: md_cpusubtype = CPU_SUBTYPE_MC68030_ONLY; ! 2825: } ! 2826: break; ! 2827: case '4': ! 2828: if(archflag_cpusubtype == CPU_SUBTYPE_MC68030_ONLY) ! 2829: as_bad("040 instruction not allowed with -arch m68030"); ! 2830: else{ ! 2831: if(md_cpusubtype != CPU_SUBTYPE_MC680x0_ALL && ! 2832: md_cpusubtype != CPU_SUBTYPE_MC68040) ! 2833: as_bad("more than one implementation specific " ! 2834: "instruction seen and -force_cpusubtype_ALL " ! 2835: "not specified (first 030 instruction in: " ! 2836: "%s at line %lu)", file_030, line_030); ! 2837: md_cpusubtype = CPU_SUBTYPE_MC68040; ! 2838: } ! 2839: break; ! 2840: } ! 2841: } ! 2842: } ! 2843: #endif /* NeXT */ ! 2844: ! 2845: #ifdef NeXT /* generate stabs for debugging assembly code */ ! 2846: /* ! 2847: * If the -g flag is present generate a line number stab for the ! 2848: * instruction. ! 2849: * ! 2850: * See the detailed comments about stabs in read_a_source_file() for a ! 2851: * description of what is going on here. ! 2852: */ ! 2853: if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){ ! 2854: (void)symbol_new( ! 2855: "", ! 2856: 68 /* N_SLINE */, ! 2857: text_nsect, ! 2858: logical_input_line /* n_desc, line number */, ! 2859: obstack_next_free(&frags) - frag_now->fr_literal, ! 2860: frag_now); ! 2861: } ! 2862: #endif /* NeXT */ ! 2863: ! 2864: if(the_ins.nfrag==0) { /* No frag hacking involved; just put it out */ ! 2865: toP=frag_more(2*the_ins.numo); ! 2866: fromP= &the_ins.opcode[0]; ! 2867: for(m=the_ins.numo;m;--m) { ! 2868: md_number_to_chars(toP,(long)(*fromP),2); ! 2869: toP+=2; ! 2870: fromP++; ! 2871: } ! 2872: /* put out symbol-dependent info */ ! 2873: for(m=0;m<the_ins.nrel;m++) { ! 2874: switch(the_ins.reloc[m].wid) { ! 2875: case 'B': ! 2876: n=1; ! 2877: break; ! 2878: case 'b': ! 2879: n=1; ! 2880: break; ! 2881: case '3': ! 2882: #ifdef NeXT ! 2883: /* This is a bug fix that is not in the 1.36 ! 2884: * version of GAS for this construct: ! 2885: * fmovemx #foo,a0@- ! 2886: * foo = 0xffff; ! 2887: * Where the width of the relocation should be ! 2888: * one byte (the low 8 bits of the second word) ! 2889: * for the floating point register mask. Other- * wise the next byte after this instruction ! 2890: * gets trashed by this relocation. ! 2891: */ ! 2892: n=1; ! 2893: #else /* !defined(NeXT) */ ! 2894: n=2; ! 2895: #endif /* NeXT */ ! 2896: break; ! 2897: case 'w': ! 2898: n=2; ! 2899: break; ! 2900: case 'l': ! 2901: n=4; ! 2902: break; ! 2903: default: ! 2904: as_fatal("Don't know how to figure width of %c in md_assemble()",the_ins.reloc[m].wid); ! 2905: } ! 2906: ! 2907: fix_new(frag_now, ! 2908: (toP - frag_now->fr_literal) - ! 2909: the_ins.numo * 2 + the_ins.reloc[m].n, ! 2910: n, ! 2911: the_ins.reloc[m].add, ! 2912: the_ins.reloc[m].sub, ! 2913: the_ins.reloc[m].off, ! 2914: the_ins.reloc[m].pcrel, ! 2915: 0,0); ! 2916: } ! 2917: return; ! 2918: } ! 2919: ! 2920: /* There's some frag hacking */ ! 2921: for(n=0,fromP= &the_ins.opcode[0];n<the_ins.nfrag;n++) { ! 2922: int wid; ! 2923: ! 2924: if(n==0) wid=2*the_ins.fragb[n].fragoff; ! 2925: else wid=2*(the_ins.numo-the_ins.fragb[n-1].fragoff); ! 2926: toP=frag_more(wid); ! 2927: to_beg_P=toP; ! 2928: shorts_this_frag=0; ! 2929: for(m=wid/2;m;--m) { ! 2930: md_number_to_chars(toP,(long)(*fromP),2); ! 2931: toP+=2; ! 2932: fromP++; ! 2933: shorts_this_frag++; ! 2934: } ! 2935: for(m=0;m<the_ins.nrel;m++) { ! 2936: if((the_ins.reloc[m].n)>= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */) { ! 2937: the_ins.reloc[m].n-= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */; ! 2938: break; ! 2939: } ! 2940: wid=the_ins.reloc[m].wid; ! 2941: if(wid==0) ! 2942: continue; ! 2943: the_ins.reloc[m].wid=0; ! 2944: wid = (wid=='b') ? 1 : (wid=='w') ? 2 : (wid=='l') ? 4 : 4000; ! 2945: ! 2946: fix_new(frag_now, ! 2947: (toP - frag_now->fr_literal) - ! 2948: the_ins.numo * 2 + the_ins.reloc[m].n, ! 2949: wid, ! 2950: the_ins.reloc[m].add, ! 2951: the_ins.reloc[m].sub, ! 2952: the_ins.reloc[m].off, ! 2953: the_ins.reloc[m].pcrel, ! 2954: 0,0); ! 2955: } ! 2956: know(the_ins.fragb[n].fadd); ! 2957: (void)frag_var(rs_machine_dependent,10,0,(relax_substateT)(the_ins.fragb[n].fragty), ! 2958: the_ins.fragb[n].fadd,the_ins.fragb[n].foff,to_beg_P); ! 2959: } ! 2960: n=(the_ins.numo-the_ins.fragb[n-1].fragoff); ! 2961: shorts_this_frag=0; ! 2962: if(n) { ! 2963: toP=frag_more(n*sizeof(short)); ! 2964: while(n--) { ! 2965: md_number_to_chars(toP,(long)(*fromP),2); ! 2966: toP+=2; ! 2967: fromP++; ! 2968: shorts_this_frag++; ! 2969: } ! 2970: } ! 2971: for(m=0;m<the_ins.nrel;m++) { ! 2972: int wid; ! 2973: ! 2974: wid=the_ins.reloc[m].wid; ! 2975: if(wid==0) ! 2976: continue; ! 2977: the_ins.reloc[m].wid=0; ! 2978: wid = (wid=='b') ? 1 : (wid=='w') ? 2 : (wid=='l') ? 4 : 4000; ! 2979: ! 2980: fix_new(frag_now, ! 2981: (the_ins.reloc[m].n + toP-frag_now->fr_literal) - ! 2982: /* the_ins.numo */ shorts_this_frag * 2, ! 2983: wid, ! 2984: the_ins.reloc[m].add, ! 2985: the_ins.reloc[m].sub, ! 2986: the_ins.reloc[m].off, ! 2987: the_ins.reloc[m].pcrel, ! 2988: 0,0); ! 2989: } ! 2990: } ! 2991: ! 2992: /* This function is called once, at assembler startup time. This should ! 2993: set up all the tables, etc that the MD part of the assembler needs ! 2994: */ ! 2995: void ! 2996: md_begin( ! 2997: void) ! 2998: { ! 2999: /* ! 3000: * md_begin -- set up hash tables with 68000 instructions. ! 3001: * similar to what the vax assembler does. ---phr ! 3002: */ ! 3003: /* RMS claims the thing to do is take the m68k-opcode.h table, and make ! 3004: a copy of it at runtime, adding in the information we want but isn't ! 3005: there. I think it'd be better to have an awk script hack the table ! 3006: at compile time. Or even just xstr the table and use it as-is. But ! 3007: my lord ghod hath spoken, so we do it this way. Excuse the ugly var ! 3008: names. */ ! 3009: ! 3010: register struct m68k_opcode *ins; ! 3011: register struct m68_incant *hack, ! 3012: *slak; ! 3013: register char *retval = 0; /* empty string, or error msg text */ ! 3014: register int i; ! 3015: register char c; ! 3016: ! 3017: if ((op_hash = hash_new()) == NULL) ! 3018: as_fatal("Virtual memory exhausted"); ! 3019: ! 3020: obstack_begin(&robyn,4000); ! 3021: for (ins = (struct m68k_opcode *)m68k_opcodes; ins < endop; ins++) { ! 3022: hack=slak=(struct m68_incant *)obstack_alloc(&robyn,sizeof(struct m68_incant)); ! 3023: do { ! 3024: slak->m_operands=ins->args; ! 3025: slak->m_opnum=strlen(slak->m_operands)/2; ! 3026: slak->m_opcode=ins->opcode; ! 3027: /* This is kludgey */ ! 3028: slak->m_codenum=((ins->match)&0xffffL) ? 2 : 1; ! 3029: #ifdef NeXT ! 3030: slak->m_cpus = ins->cpus; ! 3031: #endif /* NeXT */ ! 3032: if((ins+1)!=endop && !strcmp(ins->name,(ins+1)->name)) { ! 3033: slak->m_next=(struct m68_incant *) ! 3034: obstack_alloc(&robyn,sizeof(struct m68_incant)); ! 3035: ins++; ! 3036: } else ! 3037: slak->m_next=0; ! 3038: slak=slak->m_next; ! 3039: } while(slak); ! 3040: ! 3041: retval = hash_insert (op_hash, ins->name,(char *)hack); ! 3042: /* Didn't his mommy tell him about null pointers? */ ! 3043: if(retval && *retval) ! 3044: as_fatal("Internal Error: Can't hash %s: %s",ins->name,retval); ! 3045: } ! 3046: ! 3047: for (i = 0; i < sizeof(mklower_table) ; i++) ! 3048: mklower_table[i] = (isupper(c = (char) i)) ? tolower(c) : c; ! 3049: ! 3050: for (i = 0 ; i < sizeof(notend_table) ; i++) { ! 3051: notend_table[i] = 0; ! 3052: alt_notend_table[i] = 0; ! 3053: } ! 3054: notend_table[','] = 1; ! 3055: notend_table['{'] = 1; ! 3056: notend_table['}'] = 1; ! 3057: alt_notend_table['a'] = 1; ! 3058: alt_notend_table['A'] = 1; ! 3059: alt_notend_table['d'] = 1; ! 3060: alt_notend_table['D'] = 1; ! 3061: alt_notend_table['#'] = 1; ! 3062: alt_notend_table['f'] = 1; ! 3063: alt_notend_table['F'] = 1; ! 3064: } ! 3065: ! 3066: #if 0 ! 3067: #define notend(s) ((*s == ',' || *s == '}' || *s == '{' \ ! 3068: || (*s == ':' && index("aAdD#", s[1]))) \ ! 3069: ? 0 : 1) ! 3070: #endif ! 3071: ! 3072: /* This funciton is called once, before the assembler exits. It is ! 3073: supposed to do any final cleanup for this part of the assembler. ! 3074: */ ! 3075: void ! 3076: md_end( ! 3077: void) ! 3078: { ! 3079: } ! 3080: ! 3081: /* Equal to MAX_PRECISION in atof-ieee.c */ ! 3082: #define MAX_LITTLENUMS 6 ! 3083: ! 3084: /* Turn a string in input_line_pointer into a floating point constant of type ! 3085: type, and store the appropriate bytes in *litP. The number of LITTLENUMS ! 3086: emitted is stored in *sizeP . An error message is returned, or NULL on OK. ! 3087: */ ! 3088: char * ! 3089: md_atof( ! 3090: int type, ! 3091: char *litP, ! 3092: int *sizeP) ! 3093: { ! 3094: int prec; ! 3095: LITTLENUM_TYPE words[MAX_LITTLENUMS]; ! 3096: LITTLENUM_TYPE *wordP; ! 3097: char *t; ! 3098: ! 3099: switch(type) { ! 3100: case 'f': ! 3101: case 'F': ! 3102: case 's': ! 3103: case 'S': ! 3104: prec = 2; ! 3105: break; ! 3106: ! 3107: case 'd': ! 3108: case 'D': ! 3109: case 'r': ! 3110: case 'R': ! 3111: prec = 4; ! 3112: break; ! 3113: ! 3114: case 'x': ! 3115: case 'X': ! 3116: prec = 6; ! 3117: break; ! 3118: ! 3119: case 'p': ! 3120: case 'P': ! 3121: prec = 6; ! 3122: break; ! 3123: ! 3124: default: ! 3125: *sizeP=0; ! 3126: return "Bad call to MD_ATOF()"; ! 3127: } ! 3128: t=atof_ieee(input_line_pointer,type,words); ! 3129: if(t) ! 3130: input_line_pointer=t; ! 3131: ! 3132: *sizeP=prec * sizeof(LITTLENUM_TYPE); ! 3133: for(wordP=words;prec--;) { ! 3134: md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE)); ! 3135: litP+=sizeof(LITTLENUM_TYPE); ! 3136: } ! 3137: return ""; /* Someone should teach Dean about null pointers */ ! 3138: } ! 3139: ! 3140: /* Turn an integer of n bytes (in val) into a stream of bytes appropriate ! 3141: for use in the a.out file, and stores them in the array pointed to by buf. ! 3142: This knows about the endian-ness of the target machine and does ! 3143: THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) ! 3144: 2 (short) and 4 (long) Floating numbers are put out as a series of ! 3145: LITTLENUMS (shorts, here at least) ! 3146: */ ! 3147: void ! 3148: md_number_to_chars( ! 3149: char *buf, ! 3150: long val, ! 3151: int n) ! 3152: { ! 3153: switch(n) { ! 3154: case 1: ! 3155: *buf++=val; ! 3156: break; ! 3157: case 2: ! 3158: *buf++=(val>>8); ! 3159: *buf++=val; ! 3160: break; ! 3161: case 4: ! 3162: *buf++=(val>>24); ! 3163: *buf++=(val>>16); ! 3164: *buf++=(val>>8); ! 3165: *buf++=val; ! 3166: break; ! 3167: default: ! 3168: abort(); ! 3169: } ! 3170: } ! 3171: ! 3172: void ! 3173: md_number_to_imm( ! 3174: unsigned char *buf, ! 3175: long val, ! 3176: int n, ! 3177: fixS *fixP, ! 3178: int nsect) ! 3179: { ! 3180: switch(n) { ! 3181: case 1: ! 3182: *buf++=val; ! 3183: break; ! 3184: case 2: ! 3185: *buf++=(val>>8); ! 3186: *buf++=val; ! 3187: break; ! 3188: case 4: ! 3189: *buf++=(val>>24); ! 3190: *buf++=(val>>16); ! 3191: *buf++=(val>>8); ! 3192: *buf++=val; ! 3193: break; ! 3194: default: ! 3195: abort(); ! 3196: } ! 3197: } ! 3198: ! 3199: /* ! 3200: * Force truly undefined symbols to their maximum size, and generally set up ! 3201: * the frag list to be relaxed. It is the caller's responsiblity to set the ! 3202: * current section, frchain_now, to the corresponding nsect specified so that ! 3203: * calls to fix_new() will make fixes for this section. ! 3204: */ ! 3205: int ! 3206: md_estimate_size_before_relax( ! 3207: fragS *fragP, ! 3208: int nsect) ! 3209: { ! 3210: int old_fix; ! 3211: ! 3212: old_fix = fragP->fr_fix; ! 3213: ! 3214: /* ! 3215: * Handle SZ_UNDEF first, it can be changed to BYTE or SHORT. ! 3216: */ ! 3217: switch(fragP->fr_subtype){ ! 3218: case TAB(DBCC, SZ_UNDEF): ! 3219: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){ ! 3220: fragP->fr_subtype = TAB(DBCC, SHORT); ! 3221: fragP->fr_var += 2; ! 3222: break; ! 3223: } ! 3224: /* ! 3225: * Only DBcc 68000 instructions can come here. ! 3226: * Change dbcc into dbcc/jmp absl long. ! 3227: */ ! 3228: fragP->fr_opcode[2] = 0x00; /* branch offset = 4 */ ! 3229: fragP->fr_opcode[3] = 0x04; ! 3230: fragP->fr_opcode[4] = 0x60; /* put in bra pc+6 */ ! 3231: fragP->fr_opcode[5] = 0x06; ! 3232: fragP->fr_opcode[6] = 0x4e; /* put in jmp long (0x4ef9) */ ! 3233: fragP->fr_opcode[7] = 0xf9; ! 3234: fragP->fr_fix += 6; /* account for bra/jmp instructions */ ! 3235: fix_new(fragP, ! 3236: fragP->fr_fix, ! 3237: 4, ! 3238: fragP->fr_symbol, ! 3239: 0, ! 3240: fragP->fr_offset, ! 3241: 0, ! 3242: 0, ! 3243: 0); ! 3244: fragP->fr_fix += 4; /* account for jmp instruction displacement */ ! 3245: frag_wane(fragP); ! 3246: break; ! 3247: ! 3248: case TAB(BCC68000, SZ_UNDEF): ! 3249: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){ ! 3250: fragP->fr_subtype = TAB(BCC68000, BYTE); ! 3251: break; ! 3252: } ! 3253: /* ! 3254: * Only Bcc 68000 instructions can come here. ! 3255: * Change bcc into b!cc/jmp absl long. ! 3256: */ ! 3257: fragP->fr_opcode[0] ^= 0x01; /* invert bcc */ ! 3258: fragP->fr_opcode[1] = 0x6; /* branch offset = 6 */ ! 3259: fragP->fr_opcode[2] = 0x4e; /* put in jmp long (0x4ef9) */ ! 3260: fragP->fr_opcode[3] = 0xf9; ! 3261: fragP->fr_fix += 2; /* account for jmp instruction */ ! 3262: fix_new(fragP, ! 3263: fragP->fr_fix, ! 3264: 4, ! 3265: fragP->fr_symbol, ! 3266: 0, ! 3267: fragP->fr_offset, ! 3268: 0, ! 3269: 0, ! 3270: 0); ! 3271: fragP->fr_fix += 4; /* account for jmp instruction displacement */ ! 3272: frag_wane(fragP); ! 3273: break; ! 3274: ! 3275: case TAB(BRANCH, SZ_UNDEF): ! 3276: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){ ! 3277: /* ! 3278: * The NeXT linker has the ability to scatter blocks of ! 3279: * sections between labels. This requires that brances to ! 3280: * labels that survive to the link phase must be able to ! 3281: * be relocated. ! 3282: */ ! 3283: if(fragP->fr_symbol->sy_name[0] != 'L' || flagseen ['L']){ ! 3284: fix_new(fragP, ! 3285: fragP->fr_fix, ! 3286: 4, ! 3287: fragP->fr_symbol, ! 3288: 0, ! 3289: fragP->fr_offset + 4, ! 3290: 1, ! 3291: 1, ! 3292: 0); ! 3293: fragP->fr_fix += 4; ! 3294: fragP->fr_opcode[1] = 0xff; ! 3295: frag_wane(fragP); ! 3296: break; ! 3297: } ! 3298: else ! 3299: fragP->fr_subtype = TAB(BRANCH, BYTE); ! 3300: break; ! 3301: } ! 3302: else if(flagseen['m']){ ! 3303: if(fragP->fr_opcode[0] == 0x61){ ! 3304: fragP->fr_opcode[0] = 0x4E; ! 3305: fragP->fr_opcode[1] = 0xB9; /* JBSR with ABSL LONG offset */ ! 3306: fix_new(fragP, ! 3307: fragP->fr_fix, ! 3308: 4, ! 3309: fragP->fr_symbol, ! 3310: 0, ! 3311: fragP->fr_offset, ! 3312: 0, ! 3313: 0, ! 3314: 0); ! 3315: fragP->fr_fix += 4; ! 3316: frag_wane(fragP); ! 3317: } ! 3318: else if(fragP->fr_opcode[0] == 0x60){ ! 3319: fragP->fr_opcode[0] = 0x4E; ! 3320: fragP->fr_opcode[1] = 0xF9; /* JMP with ABSL LONG offset */ ! 3321: fix_new(fragP, ! 3322: fragP->fr_fix, ! 3323: 4, ! 3324: fragP->fr_symbol, ! 3325: 0, ! 3326: fragP->fr_offset, ! 3327: 0, ! 3328: 0, ! 3329: 0); ! 3330: fragP->fr_fix += 4; ! 3331: frag_wane(fragP); ! 3332: } ! 3333: else{ ! 3334: as_warn("Long branch offset to extern symbol not " ! 3335: "supported."); ! 3336: } ! 3337: break; ! 3338: } ! 3339: else{ ! 3340: /* Symbol is still undefined. Make it simple */ ! 3341: fix_new(fragP, ! 3342: fragP->fr_fix, ! 3343: 4, ! 3344: fragP->fr_symbol, ! 3345: 0, ! 3346: fragP->fr_offset + 4, ! 3347: 1, ! 3348: 1, ! 3349: 0); ! 3350: fragP->fr_fix += 4; ! 3351: fragP->fr_opcode[1] = 0xff; ! 3352: frag_wane(fragP); ! 3353: break; ! 3354: } ! 3355: break; ! 3356: ! 3357: case TAB(FBRANCH, SZ_UNDEF): ! 3358: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){ ! 3359: /* ! 3360: * The NeXT linker has the ability to scatter blocks of ! 3361: * sections between labels. This requires that brances to ! 3362: * labels that survive to the link phase must be able to ! 3363: * be relocated. ! 3364: */ ! 3365: if(fragP->fr_symbol->sy_name[0] != 'L' || flagseen ['L']) { ! 3366: fix_new(fragP, ! 3367: fragP->fr_fix, ! 3368: 4, ! 3369: fragP->fr_symbol, ! 3370: 0, ! 3371: fragP->fr_offset + 4, ! 3372: 1, ! 3373: 1, ! 3374: 0); ! 3375: fragP->fr_fix += 4; ! 3376: fragP->fr_opcode[1] |= 0x40; ! 3377: frag_wane(fragP); ! 3378: break; ! 3379: } ! 3380: else{ ! 3381: fragP->fr_subtype = TAB(FBRANCH, SHORT); ! 3382: fragP->fr_var += 2; ! 3383: } ! 3384: } ! 3385: else { ! 3386: /* Symbol is still undefined. Make it long */ ! 3387: fix_new(fragP, ! 3388: fragP->fr_fix, ! 3389: 4, ! 3390: fragP->fr_symbol, ! 3391: 0, ! 3392: fragP->fr_offset + 4, ! 3393: 1, ! 3394: 1, ! 3395: 0); ! 3396: fragP->fr_fix += 4; ! 3397: fragP->fr_opcode[1] |= 0x40; ! 3398: frag_wane(fragP); ! 3399: break; ! 3400: } ! 3401: break; ! 3402: ! 3403: case TAB(PCREL, SZ_UNDEF): ! 3404: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){ ! 3405: /* ! 3406: * The NeXT linker has the ability to scatter blocks of ! 3407: * sections between labels. This requires that brances to ! 3408: * labels that survive to the link phase must be able to ! 3409: * be relocated. ! 3410: */ ! 3411: if(fragP->fr_symbol->sy_name[0] != 'L' || flagseen ['L']) { ! 3412: /* ! 3413: * The thing to do here is force it to ABSOLUTE LONG, since ! 3414: * PCREL is really trying to shorten an ABSOLUTE address ! 3415: * anyway. ! 3416: */ ! 3417: if((fragP->fr_opcode[1] & 0x3F) != 0x3A) ! 3418: as_bad("Internal error (long PC-relative operand) for " ! 3419: "insn 0x%04x at 0x%lx", fragP->fr_opcode[0], ! 3420: fragP->fr_address); ! 3421: fragP->fr_opcode[1] &= ~0x3F; ! 3422: fragP->fr_opcode[1] |= 0x39; /* Mode 7.1 */ ! 3423: fix_new(fragP, ! 3424: fragP->fr_fix, ! 3425: 4, ! 3426: fragP->fr_symbol, ! 3427: 0, ! 3428: fragP->fr_offset, ! 3429: 0, ! 3430: 0, ! 3431: 0); ! 3432: fragP->fr_fix += 4; ! 3433: frag_wane(fragP); ! 3434: } ! 3435: else{ ! 3436: fragP->fr_subtype = TAB(PCREL, SHORT); ! 3437: fragP->fr_var += 2; ! 3438: } ! 3439: } ! 3440: else { ! 3441: /* Symbol is still undefined. Make it long */ ! 3442: if((fragP->fr_opcode[1] & 0x3F) != 0x3A) ! 3443: as_bad("Internal error (long PC-relative operand) for " ! 3444: "insn 0x%04x at 0x%lx", fragP->fr_opcode[0], ! 3445: fragP->fr_address); ! 3446: fragP->fr_opcode[1] &= ~0x3F; ! 3447: fragP->fr_opcode[1] |= 0x39; /* Mode 7.1 */ ! 3448: fix_new(fragP, ! 3449: fragP->fr_fix, ! 3450: 4, ! 3451: fragP->fr_symbol, ! 3452: 0, ! 3453: fragP->fr_offset, ! 3454: 1, ! 3455: 1, ! 3456: 0); ! 3457: fragP->fr_fix += 4; ! 3458: frag_wane(fragP); ! 3459: break; ! 3460: } ! 3461: break; ! 3462: ! 3463: default: ! 3464: break; ! 3465: } ! 3466: ! 3467: /* ! 3468: * Now that SZ_UNDEF are taken care of, check others ! 3469: */ ! 3470: switch(fragP->fr_subtype) { ! 3471: case TAB(BCC68000, BYTE): ! 3472: case TAB(BRANCH, BYTE): ! 3473: /* ! 3474: * We can't do a short jump to the next instruction, ! 3475: * so we force word mode. ! 3476: */ ! 3477: if(fragP->fr_symbol != NULL && ! 3478: fragP->fr_symbol->sy_value == 0 && ! 3479: fragP->fr_symbol->sy_frag == fragP->fr_next) { ! 3480: fragP->fr_subtype = TAB(TABTYPE(fragP->fr_subtype), SHORT); ! 3481: fragP->fr_var += 2; ! 3482: } ! 3483: break; ! 3484: default: ! 3485: break; ! 3486: } ! 3487: return(fragP->fr_var + fragP->fr_fix - old_fix); ! 3488: } ! 3489: ! 3490: /* ! 3491: * *fragP has been relaxed to its final size, and now needs to have ! 3492: * the bytes inside it modified to conform to the new size. There is UGLY ! 3493: * MAGIC here interms of changing the addressing mode of some instructions ! 3494: * and using other instructions in place of the original in the case of the ! 3495: * 68000 and 68010 where long pc-relative forms don't exist. ! 3496: */ ! 3497: void ! 3498: md_convert_frag( ! 3499: fragS *fragP) ! 3500: { ! 3501: long disp; ! 3502: long ext; ! 3503: char *buffer_address; ! 3504: int object_address; ! 3505: ! 3506: ext = 0; ! 3507: ! 3508: /* Address in gas core of the place to store the displacement. */ ! 3509: buffer_address = fragP->fr_fix + fragP->fr_literal; ! 3510: ! 3511: /* Address in object code of the displacement. */ ! 3512: object_address = fragP->fr_fix + fragP->fr_address; ! 3513: ! 3514: know(fragP->fr_symbol); ! 3515: ! 3516: /* The displacement of the address, from current location. */ ! 3517: disp = (fragP->fr_symbol->sy_value + fragP->fr_offset) - object_address; ! 3518: ! 3519: switch(fragP->fr_subtype){ ! 3520: case TAB(BCC68000, BYTE): ! 3521: case TAB(BRANCH, BYTE): ! 3522: know(issbyte(disp)); ! 3523: if(disp == 0){ ! 3524: /* Replace this with a nop. */ ! 3525: fragP->fr_opcode[0] = 0x4e; ! 3526: fragP->fr_opcode[1] = 0x71; ! 3527: } ! 3528: else{ ! 3529: fragP->fr_opcode[1] = disp; ! 3530: } ! 3531: ext = 0; ! 3532: break; ! 3533: ! 3534: case TAB(DBCC, SHORT): ! 3535: know(issword(disp)); ! 3536: ext=2; ! 3537: break; ! 3538: ! 3539: case TAB(BCC68000, SHORT): ! 3540: case TAB(BRANCH, SHORT): ! 3541: know(issword(disp)); ! 3542: fragP->fr_opcode[1] = 0x00; ! 3543: ext = 2; ! 3544: break; ! 3545: ! 3546: case TAB(BRANCH,LONG): ! 3547: if(flagseen['m']){ ! 3548: if(fragP->fr_opcode[0] == 0x61){ ! 3549: fragP->fr_opcode[0] = 0x4E; ! 3550: fragP->fr_opcode[1] = 0xB9; /* JBSR with ABSL LONG offset */ ! 3551: fix_new(fragP, ! 3552: fragP->fr_fix, ! 3553: 4, ! 3554: fragP->fr_symbol, ! 3555: 0, ! 3556: fragP->fr_offset, ! 3557: 0, ! 3558: 0, ! 3559: 0); ! 3560: fragP->fr_fix += 4; ! 3561: ext = 0; ! 3562: } ! 3563: else if(fragP->fr_opcode[0] == 0x60){ ! 3564: fragP->fr_opcode[0]= 0x4E; ! 3565: fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */ ! 3566: fix_new(fragP, ! 3567: fragP->fr_fix, ! 3568: 4, ! 3569: fragP->fr_symbol, ! 3570: 0, ! 3571: fragP->fr_offset, ! 3572: 0, ! 3573: 0, ! 3574: 0); ! 3575: fragP->fr_fix += 4; ! 3576: ext = 0; ! 3577: } ! 3578: else{ ! 3579: as_bad("Long branch offset not supported."); ! 3580: } ! 3581: } ! 3582: else{ ! 3583: fragP->fr_opcode[1] = 0xff; ! 3584: ext = 4; ! 3585: } ! 3586: break; ! 3587: ! 3588: case TAB(BCC68000, LONG): ! 3589: /* ! 3590: * Only Bcc 68000 instructions can come here. ! 3591: * Change bcc into b!cc/jmp absl long. ! 3592: */ ! 3593: fragP->fr_opcode[0] ^= 0x01; /* invert bcc */ ! 3594: fragP->fr_opcode[1] = 0x6; /* branch offset = 6 */ ! 3595: fragP->fr_opcode[2] = 0x4e; /* put in jmp long (0x4ef9) */ ! 3596: fragP->fr_opcode[3] = 0xf9; ! 3597: fragP->fr_fix += 2; /* account for jmp instruction */ ! 3598: fix_new(fragP, ! 3599: fragP->fr_fix, ! 3600: 4, ! 3601: fragP->fr_symbol, ! 3602: 0, ! 3603: fragP->fr_offset, ! 3604: 0, ! 3605: 0, ! 3606: 0); ! 3607: fragP->fr_fix += 4; /* account for jmp instruction's displacement */ ! 3608: ext = 0; ! 3609: break; ! 3610: ! 3611: case TAB(DBCC, LONG): ! 3612: /* ! 3613: * Only DBcc 68000 instructions can come here. ! 3614: * Change dbcc into dbcc/jmp absl long. ! 3615: */ ! 3616: fragP->fr_opcode[2] = 0x00; /* branch offset = 4 */ ! 3617: fragP->fr_opcode[3] = 0x04; ! 3618: fragP->fr_opcode[4] = 0x60; /* put in bra pc+6 */ ! 3619: fragP->fr_opcode[5] = 0x06; ! 3620: fragP->fr_opcode[6] = 0x4e; /* put in jmp long (0x4ef9) */ ! 3621: fragP->fr_opcode[7] = 0xf9; ! 3622: fragP->fr_fix += 6; /* account for bra/jmp instructions */ ! 3623: fix_new(fragP, ! 3624: fragP->fr_fix, ! 3625: 4, ! 3626: fragP->fr_symbol, ! 3627: 0, ! 3628: fragP->fr_offset, ! 3629: 0, ! 3630: 0, ! 3631: 0); ! 3632: fragP->fr_fix += 4; /* account for jmp instruction's displacement */ ! 3633: ext = 0; ! 3634: break; ! 3635: ! 3636: case TAB(FBRANCH, SHORT): ! 3637: know((fragP->fr_opcode[1] & 0x40) == 0); ! 3638: ext = 2; ! 3639: break; ! 3640: ! 3641: case TAB(FBRANCH, LONG): ! 3642: fragP->fr_opcode[1] |= 0x40; /* Turn on LONG bit */ ! 3643: ext = 4; ! 3644: break; ! 3645: ! 3646: case TAB(PCREL,SHORT): ! 3647: ext = 2; ! 3648: break; ! 3649: ! 3650: case TAB(PCREL,LONG): ! 3651: /* ! 3652: * The thing to do here is force it to ABSOLUTE LONG, since ! 3653: * PCREL is really trying to shorten an ABSOLUTE address anyway. ! 3654: */ ! 3655: if((fragP->fr_opcode[1] & 0x3F) != 0x3A) ! 3656: as_bad("Internal error (long PC-relative operand) for insn " ! 3657: "0x%04x at 0x%lx", fragP->fr_opcode[0], ! 3658: fragP->fr_address); ! 3659: fragP->fr_opcode[1] &= ~0x3F; ! 3660: fragP->fr_opcode[1] |= 0x39; /* Mode 7.1 */ ! 3661: fix_new(fragP, ! 3662: fragP->fr_fix, ! 3663: 4, ! 3664: fragP->fr_symbol, ! 3665: 0, ! 3666: fragP->fr_offset, ! 3667: 0, ! 3668: 0, ! 3669: 0); ! 3670: fragP->fr_fix += 4; /* account for the instruction's displacement */ ! 3671: ext = 0; ! 3672: break; ! 3673: ! 3674: default: ! 3675: break; ! 3676: } ! 3677: ! 3678: if(ext != 0){ ! 3679: md_number_to_chars(buffer_address, (long)disp, (int)ext); ! 3680: fragP->fr_fix += ext; ! 3681: } ! 3682: } ! 3683: ! 3684: /* Different values of OK tell what its OK to return. Things that aren't OK are an error (what a shock, no?) ! 3685: ! 3686: 0: Everything is OK ! 3687: 10: Absolute 1:8 only ! 3688: 20: Absolute 0:7 only ! 3689: 30: absolute 0:15 only ! 3690: 40: Absolute 0:31 only ! 3691: 50: absolute 0:127 only ! 3692: 55: absolute -64:63 only ! 3693: 60: absolute -128:127 only ! 3694: 70: absolute 0:4095 only ! 3695: 80: No bignums ! 3696: ! 3697: */ ! 3698: static ! 3699: int ! 3700: get_num( ! 3701: struct m68k_exp *exp, ! 3702: int ok) ! 3703: { ! 3704: #ifdef TEST2 ! 3705: long l = 0; ! 3706: ! 3707: if(!exp->e_beg) ! 3708: return 0; ! 3709: if(*exp->e_beg=='0') { ! 3710: if(exp->e_beg[1]=='x') ! 3711: sscanf(exp->e_beg+2,"%x",&l); ! 3712: else ! 3713: sscanf(exp->e_beg+1,"%O",&l); ! 3714: return l; ! 3715: } ! 3716: return atol(exp->e_beg); ! 3717: #else /* !defined(TEST2) */ ! 3718: char *save_in; ! 3719: char c_save; ! 3720: ! 3721: if(!exp) { ! 3722: /* Can't do anything */ ! 3723: return 0; ! 3724: } ! 3725: if(!exp->e_beg || !exp->e_end) { ! 3726: seg(exp)=SEG_ABSOLUTE; ! 3727: adds(exp)=0; ! 3728: subs(exp)=0; ! 3729: offs(exp)= (ok==10) ? 1 : 0; ! 3730: as_warn("Null expression defaults to %ld",offs(exp)); ! 3731: return 0; ! 3732: } ! 3733: ! 3734: exp->e_siz=0; ! 3735: if(/* ok!=80 && */exp->e_end[-1]==':' && (exp->e_end-exp->e_beg)>=2) { ! 3736: switch(exp->e_end[0]) { ! 3737: case 's': ! 3738: case 'b': ! 3739: exp->e_siz=1; ! 3740: break; ! 3741: case 'w': ! 3742: exp->e_siz=2; ! 3743: break; ! 3744: case 'l': ! 3745: exp->e_siz=3; ! 3746: break; ! 3747: default: ! 3748: as_bad("Unknown size for expression \"%c\"",exp->e_end[0]); ! 3749: } ! 3750: exp->e_end-=2; ! 3751: } ! 3752: c_save=exp->e_end[1]; ! 3753: exp->e_end[1]='\0'; ! 3754: save_in=input_line_pointer; ! 3755: input_line_pointer=exp->e_beg; ! 3756: #ifdef NeXT /* feature to try to make expressions absolute */ ! 3757: (void) expression (&(exp->e_exp)); ! 3758: /* DJA -- we will try to make an absolute number here */ ! 3759: switch(try_to_make_absolute(&(exp->e_exp))) { ! 3760: #else /* !defined(NeXT) */ ! 3761: switch(expression(&(exp->e_exp))) { ! 3762: #endif /* NeXT */ ! 3763: case SEG_NONE: ! 3764: /* Do the same thing the VAX asm does */ ! 3765: seg(exp)=SEG_ABSOLUTE; ! 3766: adds(exp)=0; ! 3767: subs(exp)=0; ! 3768: offs(exp)=0; ! 3769: if(ok==10) { ! 3770: as_warn("expression out of range: defaulting to 1"); ! 3771: offs(exp)=1; ! 3772: } ! 3773: break; ! 3774: case SEG_ABSOLUTE: ! 3775: switch(ok) { ! 3776: case 10: ! 3777: if(offs(exp)<1 || offs(exp)>8) { ! 3778: as_warn("expression out of range: defaulting to 1"); ! 3779: offs(exp)=1; ! 3780: } ! 3781: break; ! 3782: case 20: ! 3783: if(offs(exp)<0 || offs(exp)>7) ! 3784: goto outrange; ! 3785: break; ! 3786: case 30: ! 3787: if(offs(exp)<0 || offs(exp)>15) ! 3788: goto outrange; ! 3789: break; ! 3790: case 40: ! 3791: if(offs(exp)<0 || offs(exp)>32) ! 3792: goto outrange; ! 3793: break; ! 3794: case 50: ! 3795: if(offs(exp)<0 || offs(exp)>127) ! 3796: goto outrange; ! 3797: break; ! 3798: case 55: ! 3799: if(offs(exp)<-64 || offs(exp)>63) ! 3800: goto outrange; ! 3801: break; ! 3802: case 60: ! 3803: if(offs(exp)<-128 || offs(exp)>127) ! 3804: goto outrange; ! 3805: break; ! 3806: case 70: ! 3807: if(offs(exp)<0 || offs(exp)>4095) { ! 3808: outrange: ! 3809: as_warn("expression out of range: defaulting to 0"); ! 3810: offs(exp)=0; ! 3811: } ! 3812: break; ! 3813: default: ! 3814: break; ! 3815: } ! 3816: break; ! 3817: case SEG_SECT: ! 3818: case SEG_UNKNOWN: ! 3819: case SEG_DIFFSECT: ! 3820: if(ok>=10 && ok<=70) { ! 3821: seg(exp)=SEG_ABSOLUTE; ! 3822: adds(exp)=0; ! 3823: subs(exp)=0; ! 3824: offs(exp)= (ok==10) ? 1 : 0; ! 3825: as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp)); ! 3826: } ! 3827: break; ! 3828: case SEG_BIG: ! 3829: #ifndef NeXT /* fix for bug #8331 */ /* This hack is already done by expr */ ! 3830: if(ok==80 && offs(exp)<0) { /* HACK! Turn it into a long */ ! 3831: LITTLENUM_TYPE words[6]; ! 3832: ! 3833: gen_to_words(words,2,8L);/* These numbers are magic! */ ! 3834: seg(exp)=SEG_ABSOLUTE; ! 3835: adds(exp)=0; ! 3836: subs(exp)=0; ! 3837: offs(exp)=words[1]|(words[0]<<16); ! 3838: } else if(ok!=0) { ! 3839: #else /* defined(NeXT) */ ! 3840: if(ok!=0) { ! 3841: #endif /* NeXT */ ! 3842: seg(exp)=SEG_ABSOLUTE; ! 3843: adds(exp)=0; ! 3844: subs(exp)=0; ! 3845: offs(exp)= (ok==10) ? 1 : 0; ! 3846: as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp)); ! 3847: } ! 3848: break; ! 3849: default: ! 3850: abort(); ! 3851: } ! 3852: if(input_line_pointer!=exp->e_end+1) ! 3853: as_bad("Ignoring junk after expression"); ! 3854: exp->e_end[1]=c_save; ! 3855: input_line_pointer=save_in; ! 3856: if(exp->e_siz) { ! 3857: switch(exp->e_siz) { ! 3858: case 1: ! 3859: if(!isbyte(offs(exp))) ! 3860: as_warn("expression doesn't fit in BYTE"); ! 3861: break; ! 3862: case 2: ! 3863: if(!isword(offs(exp))) ! 3864: as_warn("expression doesn't fit in WORD"); ! 3865: break; ! 3866: } ! 3867: } ! 3868: return offs(exp); ! 3869: ! 3870: #endif /* !defined(TEST2) */ ! 3871: } ! 3872: ! 3873: /* These are the back-ends for the various machine dependent pseudo-ops. */ ! 3874: void demand_empty_rest_of_line(); /* Hate those extra verbose names */ ! 3875: ! 3876: static ! 3877: void ! 3878: s_even( ! 3879: int value) ! 3880: { ! 3881: register int temp; ! 3882: register long int temp_fill; ! 3883: ! 3884: temp = 1; /* JF should be 2? */ ! 3885: temp_fill = get_absolute_expression (); ! 3886: frag_align(temp, (int)temp_fill); ! 3887: /* ! 3888: * If this alignment is larger than any previous alignment then this ! 3889: * becomes the section's alignment. ! 3890: */ ! 3891: if(frchain_now->frch_section.align < temp) ! 3892: frchain_now->frch_section.align = temp; ! 3893: demand_empty_rest_of_line(); ! 3894: } ! 3895: ! 3896: static ! 3897: void ! 3898: s_proc( ! 3899: int value) ! 3900: { ! 3901: demand_empty_rest_of_line(); ! 3902: } ! 3903: ! 3904: /* s_space is defined in read.c .skip is simply an alias to it. */ ! 3905: ! 3906: int ! 3907: md_parse_option( ! 3908: char **argP, ! 3909: int *cntP, ! 3910: char ***vecP) ! 3911: { ! 3912: switch(**argP) { ! 3913: case 'l': /* -l means keep external to 32 bit offset ! 3914: rather than 16 bit one */ ! 3915: break; ! 3916: ! 3917: case 'm': ! 3918: /* Gas simply ignores this option! */ ! 3919: (*argP)++; ! 3920: if(**argP=='c') ! 3921: (*argP)++; ! 3922: if(!strcmp(*argP,"68000")) ! 3923: flagseen['m']=2; ! 3924: else if(!strcmp(*argP,"68010")) { ! 3925: flagseen['m']=1; ! 3926: } else if(!strcmp(*argP,"68020")) ! 3927: flagseen['m']=0; ! 3928: else ! 3929: as_warn("Unknown -m option ignored"); ! 3930: while(**argP) ! 3931: (*argP)++; ! 3932: break; ! 3933: ! 3934: default: ! 3935: return 0; ! 3936: } ! 3937: return 1; ! 3938: } ! 3939: ! 3940: ! 3941: #ifdef TEST2 ! 3942: ! 3943: /* TEST2: Test md_assemble() */ ! 3944: ! 3945: static ! 3946: int ! 3947: is_label( ! 3948: char *str) ! 3949: { ! 3950: while(*str == ' ') ! 3951: str++; ! 3952: while(*str && *str != ' ') ! 3953: str++; ! 3954: if(str[-1] == ':' || str[1] == '=') ! 3955: return(1); ! 3956: return(0); ! 3957: } ! 3958: ! 3959: void ! 3960: main( ! 3961: int argc, ! 3962: char *argv[], ! 3963: char *envp[]) ! 3964: { ! 3965: char buf[120]; ! 3966: char *cp; ! 3967: int n; ! 3968: ! 3969: m68_ip_begin(); ! 3970: for(;;){ ! 3971: if(!gets(buf) || !*buf) ! 3972: break; ! 3973: if(buf[0] == '|' || buf[1] == '.') ! 3974: continue; ! 3975: for(cp = buf; *cp; cp++) ! 3976: if(*cp == '\t') ! 3977: *cp = ' '; ! 3978: if(is_label(buf)) ! 3979: continue; ! 3980: memset(&the_ins, '\0', sizeof(the_ins)); ! 3981: m68_ip(buf); ! 3982: if(the_ins.error){ ! 3983: printf("Error %s in %s\n", the_ins.error, buf); ! 3984: } ! 3985: else{ ! 3986: printf("Opcode(%d.%s): ", the_ins.numo, the_ins.args); ! 3987: for(n = 0; n < the_ins.numo; n++) ! 3988: printf(" 0x%x", the_ins.opcode[n] & 0xffff); ! 3989: printf(" "); ! 3990: print_the_insn(&the_ins.opcode[0], stdout); ! 3991: (void)putchar('\n'); ! 3992: } ! 3993: for(n = 0; n < strlen(the_ins.args) / 2; n++){ ! 3994: if(the_ins.operands[n].error){ ! 3995: printf("op%d Error %s in %s\n", ! 3996: n, the_ins.operands[n].error, buf); ! 3997: continue; ! 3998: } ! 3999: printf("mode %d, reg %d, ", ! 4000: the_ins.operands[n].mode, the_ins.operands[n].reg); ! 4001: if(the_ins.operands[n].con1) ! 4002: printf("con1: '%.*s', ", ! 4003: 1 + the_ins.operands[n].con1->e_end - ! 4004: the_ins.operands[n].con1->e_beg, ! 4005: the_ins.operands[n].con1->e_beg); ! 4006: printf("ireg %d, isiz %d, imul %d, ", ! 4007: the_ins.operands[n].ireg, ! 4008: the_ins.operands[n].isiz, ! 4009: the_ins.operands[n].imul); ! 4010: if(the_ins.operands[n].con2) ! 4011: printf("con2: '%.*s',", ! 4012: 1 + the_ins.operands[n].con2->e_end - ! 4013: the_ins.operands[n].con2->e_beg, ! 4014: the_ins.operands[n].con2->e_beg); ! 4015: (void)putchar('\n'); ! 4016: } ! 4017: } ! 4018: m68_ip_end(); ! 4019: } ! 4020: #endif /* TEST2 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.