--- /dev/null
+/* @(#)mach0.c 1.5 */
+/*
+ * Motorola 68020 options
+ */
+#undef BITMAX
+#define BITMAX 20000
+
+#define THREE_PASS /* branch and offset optimization */
+#define BYTES_REVERSED /* high order byte has lowest address */
+#define WORDS_REVERSED /* high order word has lowest address */
+#define LISTING /* enable listing facilities */
+#define RELOCATION /* generate relocatable code */
+#define DEBUG 1
+
+#undef valu_t
+#define valu_t long
+#undef addr_t
+#define addr_t long
+
+#undef ASC_LPAR
+#define ASC_LPAR '{'
+#undef ASC_RPAR
+#define ASC_RPAR '}'
+
+#undef ALIGNWORD
+#define ALIGNWORD 2
+#undef ALIGNSECT
+#define ALIGNSECT 2
+
+#undef VALWIDTH
+#define VALWIDTH 8
+
+#define ASLD
--- /dev/null
+/* @(#)mach1.c 1.8 */
+/*
+ * Motorola 68020 dependent C declarations
+ */
+
+#define low3(z) ((short)(z) & 07)
+#define low4(z) ((short)(z) & 017)
+#define low5(z) ((short)(z) & 037)
+#define low6(z) ((short)(z) & 077)
+
+#define fit3(z) ((((z)-1) & ~07) == 0)
+#define fit4(z) (((z) & ~017) == 0)
+#define fit5(z) (((z) & ~037) == 0)
+#define fit6(z) (((z) & ~077) == 0)
+#define fit8(z) (((z) & ~0xFF) == 0)
+#define fit16(z) (((z) & ~0xFFFF) == 0)
+
+#define SIZE_B 0000
+#define SIZE_W 0100
+#define SIZE_L 0200
+#define SIZE_NON 0300
+#define SIZE_DEF SIZE_W
+
+extern int mrg_1,mrg_2; /* Mode and ReGister */
+extern short ffew_1, ffew_2; /* Full Format Extension Word */
+extern expr_t bd_1,bd_2,od_1,od_2; /* base and outer displacements */
+#ifndef ASLD
+extern valu_t bd_rel1,bd_rel2,od_rel1,od_rel2;
+#endif
+
+#ifdef RELOCATION
+#ifdef ASLD
+#define T_EMIT2(a,b,c,d) t_emit2(a,b,c,0)
+#define T_EMIT4(a,b,c,d) t_emit4(a,b,c,0)
+#else ALSD
+#define T_EMIT2(a,b,c,d) t_emit2(a,b,c,d)
+#define T_EMIT4(a,b,c,d) t_emit4(a,b,c,d)
+#endif ASLD
+#else
+#define T_EMIT2(a,b,c,d) t_emit2(a)
+#define T_EMIT4(a,b,c,d) t_emit4(a)
+#endif
+
+struct instr_t {
+ short i_word; /* word to be emitted */
+#ifdef RELOCATION
+ short i_relotype;
+ int i_reloinfo;
+ valu_t i_relonami;
+#endif
+};
+typedef struct instr_t instr_t;
+instr_t instr[30]; /* temporary area for instructions */
+instr_t *instrp; /* index into instr[] */
+int dot_offset;
+
+/* flags used when reading effective addresses */
+#define INDEX 0300
+#define PRE_INDEX 0100
+#define POST_INDEX 0200
+#define DBL_INDEX 0300
+#define PC_MODE 0400
+
+/* addressing mode bits */
+#define DTA 0x01
+#define MEM 0x02
+#define CTR 0x04
+#define ALT 0x08
+#define FITB 0x10
+#define FITW 0x20
+#define PUTW 0x40
+#define PUTL 0x80
+
+#ifndef extern
+extern short eamode[];
+#else
+short eamode[] = {
+/* 00A */ DTA |ALT,
+/* 01A */ ALT,
+/* 02A */ DTA|MEM|CTR|ALT,
+/* 03A */ DTA|MEM |ALT,
+/* 04A */ DTA|MEM |ALT,
+/* 05A */ DTA|MEM|CTR|ALT|FITW|PUTW, /* if relocation wanted, use 06A */
+/* 06A */ DTA|MEM|CTR|ALT |PUTW, /* relocation handled by ea_1() */
+/* 07x */ 0,
+/* 070 */ DTA|MEM|CTR|ALT|FITW|PUTW | (RELO2)<<8,
+/* 071 */ DTA|MEM|CTR|ALT |PUTL | (RELO4)<<8,
+/* 072 */ DTA|MEM|CTR |FITW|PUTW, /* if relocation wanted, use 073 */
+/* 073 */ DTA|MEM|CTR |PUTW, /* relocation handled by ea_1() */
+/* 074x */ 0,
+/* 074B */ DTA|MEM |FITB|PUTW | (RELO1)<<8,
+/* 074W */ DTA|MEM |FITW|PUTW | (RELO2)<<8,
+/* 074L */ DTA|MEM |PUTL | (RELO4)<<8,
+};
+ /* RELO2 had to go with mode 070, because the assembly
+ * language programmer can use addresses like
+ * '(expression).w', which still have to be relocatable.
+ */
+#endif
--- /dev/null
+/* @(#)mach2.c 1.5 */
+/*
+ * Motorola 68020 tokens
+ */
+
+%token <y_word> SIZE
+%token <y_word> DREG
+%token <y_word> AREG
+%token <y_word> PC
+%token <y_word> ZPC
+%token <y_word> CREG
+%token <y_word> SPEC
+%token <y_word> ABCD
+%token <y_word> ADDX
+%token <y_word> ADD
+%token <y_word> AND
+%token <y_word> BITOP
+%token <y_word> BITFIELD
+%token <y_word> BF_TO_D
+%token <y_word> BFINS
+%token <y_word> SHIFT
+%token <y_word> SZ_EA
+%token <y_word> OP_EA
+%token <y_word> OP_NOOP
+%token <y_word> LEA
+%token <y_word> DBR
+%token <y_word> BR
+%token <y_word> OP_EXT
+%token <y_word> OP_RANGE
+%token <y_word> TRAPCC
+%token <y_word> PACK
+%token <y_word> RTM
+%token <y_word> CHK
+%token <y_word> DIVMUL
+%token <y_word> DIVL
+%token <y_word> CMP
+%token <y_word> MOVE
+%token <y_word> MOVEP
+%token <y_word> MOVEM
+%token <y_word> MOVEC
+%token <y_word> MOVES
+%token <y_word> SWAP
+%token <y_word> LINK
+%token <y_word> UNLK
+%token <y_word> TRAP
+%token <y_word> STOP
+%token <y_word> EXG
+%token <y_word> RTD
+%token <y_word> BKPT
+%token <y_word> CALLM
+%token <y_word> CAS
+%token <y_word> CAS2
+%token <y_word> CP
+%token <y_word> CPBCC
+%token <y_word> CPDBCC
+%token <y_word> CPGEN
+%token <y_word> CPRESTORE
+%token <y_word> CPSAVE
+%token <y_word> CPSCC
+%token <y_word> CPTRAPCC
+
+%type <y_word> bcdx op_ea regs rrange
+%type <y_word> reg sizedef sizenon creg
+%type <y_word> off_width abs31 bd_areg_index
+%type <y_word> areg_index areg scale cp_cond
--- /dev/null
+/* @(#)mach3.c 1.4 */
+/*
+ * Motorola 68020 keywords
+ */
+
+0, SIZE, SIZE_B, ".b",
+0, SIZE, SIZE_W, ".w",
+0, SIZE, SIZE_L, ".l",
+
+0, DREG, 00, "d0",
+0, DREG, 01, "d1",
+0, DREG, 02, "d2",
+0, DREG, 03, "d3",
+0, DREG, 04, "d4",
+0, DREG, 05, "d5",
+0, DREG, 06, "d6",
+0, DREG, 07, "d7",
+
+0, AREG, 00, "a0",
+0, AREG, 01, "a1",
+0, AREG, 02, "a2",
+0, AREG, 03, "a3",
+0, AREG, 04, "a4",
+0, AREG, 05, "a5",
+0, AREG, 06, "a6",
+0, AREG, 07, "a7",
+0, AREG, 07, "sp",
+
+0, PC, 0, "pc",
+0, ZPC, 0, "zpc",
+
+0, CREG, 04001, "vbr",
+0, CREG, 0, "sfc",
+0, CREG, 00001, "dfc",
+0, CREG, 00002, "cacr",
+0, CREG, 04002, "caar",
+0, CREG, 04003, "msp",
+0, CREG, 04004, "isp",
+
+0, SPEC, 075, "usp",
+0, SPEC, 076, "ccr",
+0, SPEC, 077, "sr",
+
+0, ABCD, 0140400, "abcd",
+0, ABCD, 0100400, "sbcd",
+
+0, ADDX, 0150400, "addx",
+0, ADDX, 0110400, "subx",
+
+0, ADD, 0153300, "add",
+0, ADD, 0112700, "sub",
+
+0, AND, 0141000, "and",
+0, AND, 0135000, "eor",
+0, AND, 0100000, "or",
+
+0, BITOP, 0000, "btst",
+0, BITOP, 0100, "bchg",
+0, BITOP, 0200, "bclr",
+0, BITOP, 0300, "bset",
+
+0, BITFIELD, 0164300, "bftst",
+0, BITFIELD, 0165300, "bfchg",
+0, BITFIELD, 0166300, "bfclr",
+0, BITFIELD, 0167300, "bfset",
+0, BF_TO_D, 0164700, "bfextu",
+0, BF_TO_D, 0164700, "bfexts",
+0, BF_TO_D, 0164700, "bfffo",
+0, BFINS, 0167700, "bfins",
+
+0, SHIFT, 0160340, "asr",
+0, SHIFT, 0160740, "asl",
+0, SHIFT, 0161350, "lsr",
+0, SHIFT, 0161750, "lsl",
+0, SHIFT, 0162360, "roxr",
+0, SHIFT, 0162760, "roxl",
+0, SHIFT, 0163370, "ror",
+0, SHIFT, 0163770, "rol",
+
+0, SZ_EA, 041000|DTA|ALT, "clr",
+0, SZ_EA, 042000|DTA|ALT, "neg",
+0, SZ_EA, 040000|DTA|ALT, "negx",
+0, SZ_EA, 043000|DTA|ALT, "not",
+0, SZ_EA, 045000|DTA, "tst",
+
+0, OP_EA, 044000|DTA|ALT, "nbcd",
+0, OP_EA, 045300|DTA|ALT, "tas",
+0, OP_EA, 047200|CTR, "jsr",
+0, OP_EA, 047300|CTR, "jmp",
+0, OP_EA, 044100|CTR, "pea",
+
+0, OP_EA, 050300, "st",
+0, OP_EA, 050700, "sf",
+0, OP_EA, 051300, "shi",
+0, OP_EA, 051700, "sls",
+0, OP_EA, 052300, "scc",
+0, OP_EA, 052700, "scs",
+0, OP_EA, 053300, "sne",
+0, OP_EA, 053700, "seq",
+0, OP_EA, 054300, "svc",
+0, OP_EA, 054700, "svs",
+0, OP_EA, 055300, "spl",
+0, OP_EA, 055700, "smi",
+0, OP_EA, 056300, "sge",
+0, OP_EA, 056700, "slt",
+0, OP_EA, 057300, "sgt",
+0, OP_EA, 057700, "sle",
+
+0, OP_NOOP, 047160, "reset",
+0, OP_NOOP, 047161, "nop",
+0, OP_NOOP, 047163, "rte",
+0, OP_NOOP, 047165, "rts",
+0, OP_NOOP, 047166, "trapv",
+0, OP_NOOP, 047167, "rtr",
+0, OP_NOOP, 045374, "illegal",
+
+0, PACK, 0100500, "pack",
+0, PACK, 0100600, "unpk",
+
+0, DIVMUL, 0100, "divu",
+0, DIVMUL, 0101, "divs",
+0, DIVMUL, 0000, "mulu",
+0, DIVMUL, 0001, "muls",
+
+0, DIVL, 046100, "divul",
+0, DIVL, 046101, "divsl",
+
+0, BR, 060000, "bra",
+0, BR, 060400, "bsr",
+0, BR, 061000, "bhi",
+0, BR, 061400, "bls",
+0, BR, 062000, "bcc",
+0, BR, 062400, "bcs",
+0, BR, 063000, "bne",
+0, BR, 063400, "beq",
+0, BR, 064000, "bvc",
+0, BR, 064400, "bvs",
+0, BR, 065000, "bpl",
+0, BR, 065400, "bmi",
+0, BR, 066000, "bge",
+0, BR, 066400, "blt",
+0, BR, 067000, "bgt",
+0, BR, 067400, "ble",
+
+0, DBR, 050310, "dbt",
+0, DBR, 050710, "dbf",
+0, DBR, 050710, "dbra",
+0, DBR, 051310, "dbhi",
+0, DBR, 051710, "dbls",
+0, DBR, 052310, "dbcc",
+0, DBR, 052710, "dbcs",
+0, DBR, 053310, "dbne",
+0, DBR, 053710, "dbeq",
+0, DBR, 054310, "dbvc",
+0, DBR, 054710, "dbvs",
+0, DBR, 055310, "dbpl",
+0, DBR, 055710, "dbmi",
+0, DBR, 056310, "dbge",
+0, DBR, 056710, "dblt",
+0, DBR, 057310, "dbgt",
+0, DBR, 057710, "dble",
+
+0, OP_EXT, 044000, "ext",
+0, OP_EXT, 044400, "extb",
+
+0, OP_RANGE, 04000, "chk2",
+0, OP_RANGE, 0, "cmp2",
+
+0, TRAPCC, 050370, "trapt",
+0, TRAPCC, 050770, "trapf",
+0, TRAPCC, 051370, "traphi",
+0, TRAPCC, 051770, "trapls",
+0, TRAPCC, 052370, "trapcc",
+0, TRAPCC, 052770, "trapcs",
+0, TRAPCC, 053370, "trapeq",
+0, TRAPCC, 053770, "trapvc",
+0, TRAPCC, 054370, "trapvs",
+0, TRAPCC, 054770, "trappl",
+0, TRAPCC, 055370, "trapmi",
+0, TRAPCC, 055770, "trapge",
+0, TRAPCC, 056370, "traplt",
+0, TRAPCC, 056770, "trapgt",
+0, TRAPCC, 057370, "traple",
+0, TRAPCC, 057770, "trapne",
+
+0, CMP, 0, "cmp",
+
+0, MOVE, 0, "move",
+0, MOVEP, 0, "movep",
+0, MOVEM, 0, "movem",
+0, MOVES, 0, "moves",
+0, MOVEC, 0, "movec",
+
+0, SWAP, 0, "swap",
+
+0, LINK, 0, "link",
+
+0, UNLK, 0, "unlk",
+
+0, TRAP, 0, "trap",
+
+0, STOP, 0, "stop",
+
+0, CHK, 0, "chk",
+
+0, RTM, 0, "rtm",
+
+0, EXG, 0, "exg",
+
+0, LEA, 0, "lea",
+
+0, RTD, 0, "rtd",
+
+0, BKPT, 0, "bkpt",
+
+0, CALLM, 0, "callm",
+
+0, CAS, 0, "cas",
+
+0, CAS2, 0, "cas2",
+
+0, CP, 00000, "c0",
+0, CP, 01000, "c1",
+0, CP, 02000, "c2",
+0, CP, 03000, "c3",
+0, CP, 04000, "c4",
+0, CP, 05000, "c5",
+0, CP, 06000, "c6",
+0, CP, 07000, "c7",
+
+0, CPGEN, 0170000, ".gen",
+0, CPSCC, 0170100, ".s",
+0, CPDBCC, 0170110, ".db",
+0, CPTRAPCC, 0170170, ".trap",
+0, CPBCC, 0170200, ".br", /* 'r' to distinguish from SIZE_B
+ */
+0, CPSAVE, 0170400, ".save",
+0, CPRESTORE, 0170500, ".restore",
--- /dev/null
+/* @(#)mach4.c 1.11 */
+/*
+ * Motorola 68020 syntax rules
+ */
+
+operation
+ : { instrp = instr;
+ dot_offset = 0;
+ }
+ instruction
+ { emit_instr();
+ }
+ ;
+instruction
+ : bcdx DREG ',' DREG
+ { T_EMIT2($1 | $2 | $4<<9,0,0,0);}
+ | bcdx '-' '(' AREG ')' ',' '-' '(' AREG ')'
+ { T_EMIT2($1 | $4 | $9<<9 | 010,0,0,0);}
+ | ADD sizedef ea_ea
+ { add($1, $2);}
+ | AND sizenon ea_ea
+ { and($1, $2);}
+ | SHIFT sizedef ea_ea
+ { shift_op($1, $2);}
+ | SHIFT sizedef ea /* This syntax is also allowed */
+ { checksize($2, 2);
+ T_EMIT2(($1 & 0177700) | mrg_2,0,0,0);
+ ea_2(SIZE_W, MEM|ALT);
+ }
+ | BR expr
+ { branch($1, $2);}
+ | DBR DREG ',' expr
+ { T_EMIT2($1 | $2,0,0,0);
+ $4.val -= (DOTVAL+dot_offset);
+ fit(fitw($4.val));
+ T_EMIT2(loww($4.val), $4.typ,
+ RELPC|RELO2, relonami);
+ }
+ | BITOP ea_ea
+ { bitop($1);}
+ | BITFIELD ea off_width
+ { bitfield($1, $3);}
+ | BF_TO_D ea off_width ',' DREG
+ { bitfield($1, $3 | $5<<12);}
+ | BFINS DREG ',' ea off_width
+ { bitfield($1, $5 | $2<<12);}
+ | DIVMUL sizedef ea ',' DREG
+ { checksize($2, 2|4);
+ if ($2 == SIZE_W) {
+ T_EMIT2((0140300^($1<<8))|mrg_2|$5<<9,
+ 0, 0, 0);
+ ea_2(SIZE_W, DTA);
+ }
+ else { /* 32 bit dividend or product */
+ T_EMIT2((016000 | ($1 & ~1)) | mrg_2,
+ 0, 0, 0);
+ T_EMIT2(($1&1)<<11 | $5<<12 | $5,
+ 0, 0, 0);
+ ea_2(SIZE_L, DTA);
+ }
+ }
+ | DIVMUL sizedef ea ',' DREG ':' DREG
+ { /* 64 bit dividend or product */
+ checksize($2, 4);
+ T_EMIT2((016000 | ($1 & ~1)) | mrg_2, 0, 0, 0);
+ T_EMIT2(($1&1)<<11 | $7<<12 | $5 | 02000,0,0,0);
+ ea_2(SIZE_L, DTA);
+ }
+ | DIVL sizedef ea ',' DREG ':' DREG
+ { /* 32 bit long division with remainder */
+ checksize($2, 4);
+ T_EMIT2(($1 & ~1) | mrg_2, 0, 0, 0);
+ T_EMIT2(($1 & 1)<<11 | $7<<12 | $5, 0, 0, 0);
+ ea_2(SIZE_L, DTA);
+ }
+ | LEA ea ',' AREG
+ { T_EMIT2(040700 | mrg_2 | $4<<9,0,0,0);
+ ea_2(SIZE_L, CTR);
+ }
+ | op_ea ea
+ { if (mrg_2==074)
+ serror("bad adressing category");
+ T_EMIT2(($1&0177700) | mrg_2,0,0,0);
+ ea_2($1&0300, $1&017);
+ }
+ | OP_NOOP
+ { T_EMIT2($1,0,0,0);}
+ | OP_EXT SIZE DREG
+ { checksize($2, ($1 & 0400) ? 4 : (2|4));
+ T_EMIT2($1 | $2+0100 | $3,0,0,0);
+ }
+ | OP_RANGE sizedef ea ',' reg
+ { T_EMIT2(0300 | ($2<<3) | mrg_2,0,0,0);
+ T_EMIT2($1 | ($5<<12),0,0,0);
+ ea_2($2, CTR);
+ }
+ | TRAPCC SIZE imm
+ { checksize($2, 2|4);
+ T_EMIT2($1 | ($2>>6)+1,0,0,0);
+ ea_2($2, 0);
+ }
+ | TRAPCC { T_EMIT2($1 | 4,0,0,0);}
+ | PACK '-' '(' AREG ')' ',' '-' '(' AREG ')' ',' imm
+ { T_EMIT2($1 | 1 | $4 | $9<<9, 0, 0, 0);
+ ea_2(SIZE_W, 0);
+ }
+ | PACK DREG ',' DREG ',' imm
+ { T_EMIT2($1 | $2 | $4<<9, 0, 0, 0);
+ ea_2(SIZE_W, 0);
+ }
+ | CMP sizedef ea_ea
+ { cmp($2);}
+ | CHK sizedef ea ',' DREG
+ { checksize($2, 2|4);
+ T_EMIT2(040000 | mrg_2 | $5<<9 |
+ ($2==SIZE_W ? 0600 : 0400),
+ 0, 0, 0);
+ ea_2($2, DTA);
+ }
+ | MOVE sizenon ea_ea
+ { move($2);}
+ | MOVEP sizedef ea_ea
+ { movep($2);}
+ | MOVEM sizedef regs ',' notimmreg
+ { movem(0, $2, $3);}
+ | MOVEM sizedef notimmreg ',' regs
+ { movem(1, $2, $5);}
+ | MOVES sizedef ea_ea
+ { if (mrg_1 <= 017) {
+ T_EMIT2(007000 | $2 | mrg_2,0,0,0);
+ T_EMIT2(mrg_1 << 12 | 04000,0,0,0);
+ ea_2($2,ALT|MEM);
+ } else if (mrg_2 <= 017) {
+ T_EMIT2(007000 | $2 | mrg_1,0,0,0);
+ T_EMIT2(mrg_2 << 12,0,0,0);
+ ea_1($2,ALT|MEM);
+ } else
+ badoperand();
+ }
+ | MOVEC creg ',' reg
+ { T_EMIT2(047172,0,0,0);
+ T_EMIT2($2 | $4<<12,0,0,0);
+ }
+ | MOVEC reg ',' creg
+ { T_EMIT2(047173,0,0,0);
+ T_EMIT2($4 | $2<<12,0,0,0);
+ }
+ | EXG reg ',' reg
+ { if (($2 & 010) == 0)
+ T_EMIT2(
+ (0140500|$4|$2<<9)
+ +
+ (($4&010)<<3)
+ ,0,0,0);
+ else
+ T_EMIT2(
+ (0140600|$2|($4&07)<<9)
+ -
+ (($4&010)<<3)
+ ,0,0,0);
+ }
+ | SWAP DREG
+ { T_EMIT2(044100 | $2,0,0,0);}
+ | STOP imm
+ { T_EMIT2(047162, 0, 0, 0);
+ ea_2(SIZE_W, 0);
+ }
+ | LINK sizenon AREG ',' imm
+ { link($2, $3);}
+ | UNLK AREG
+ { T_EMIT2(047130 | $2,0,0,0);}
+ | TRAP '#' absexp
+ { fit(fit4($3));
+ T_EMIT2(047100|low4($3),0,0,0);
+ }
+ | RTD imm
+ { T_EMIT2(047164,0,0,0);
+ ea_2(SIZE_W, 0);
+ }
+ | BKPT '#' absexp
+ { fit(($3 & ~07) == 0);
+ T_EMIT2(044110 | low3($3),0,0,0);
+ }
+ | CALLM '#' absexp ',' ea
+ { fit(fitb($3));
+ T_EMIT2(03300 | mrg_2,0,0,0);
+ T_EMIT2($3,0,0,0);
+ ea_2(SIZE_L, CTR);
+ }
+ | RTM reg
+ { T_EMIT2(03300 | $2, 0, 0, 0);}
+ | CAS sizedef DREG ',' DREG ',' ea
+ { T_EMIT2(04300 | (($2+0100)<<3) | mrg_2,0,0,0);
+ T_EMIT2($5 | ($3<<6),0,0,0);
+ ea_2($2, MEM|ALT);
+ }
+ | CAS2 sizedef DREG ':' DREG ',' DREG ':' DREG ','
+ '(' reg ')' ':' '(' reg ')'
+ { checksize($2 , 2|4);
+ T_EMIT2(04374 | (($2+0100)<<3),0,0,0);
+ T_EMIT2($3 | ($7<<6) | ($12<<12),0,0,0);
+ T_EMIT2($5 | ($9<<6) | ($16<<12),0,0,0);
+ }
+ | /* Coprocessor instructions; syntax may be changed (please).
+ * No coprocessor defined extension words are emitted.
+ */
+ CP CPBCC cp_cond expr
+ { cpbcc($2 | $1 | $3, $4);
+ }
+ | CP CPDBCC cp_cond DREG ',' expr
+ { T_EMIT2($2 | $1 | $4,0,0,0);
+ $6.val -= (DOTVAL+dot_offset);
+ fit(fitw($6.val));
+ T_EMIT2(loww($6.val), $6.typ,
+ RELPC|RELO2, relonami);
+ }
+ | CP CPGEN
+ { T_EMIT2($2 | $1,0,0,0);
+ /* NO COMMAND WORD IS EMITTED;
+ * THIS INSTRUCTIONS IS (STILL) ONE BIG RIDDLE.
+ * NO EFFECTIVE ADDRESS IS CALCULATED (SYNTAX ?)
+ */
+ }
+ | CP CPRESTORE ea
+ { T_EMIT2($2 | $1 | mrg_2,0,0,0);
+ ea_2(SIZE_W, (mrg_2 & 070)==030 ? 0 : CTR);
+ }
+ | CP CPSAVE ea
+ { T_EMIT2($2 | $1 | mrg_2,0,0,0);
+ ea_2(SIZE_W,(mrg_2 & 070)==020 ? 0 : CTR|ALT);
+ }
+ | CP CPSCC cp_cond ea
+ { T_EMIT2($2 | $1 | mrg_2,0,0,0);
+ T_EMIT2($3,0,0,0);
+ ea_2(SIZE_B,DTA|ALT);
+ }
+ | CP CPTRAPCC cp_cond SIZE imm
+ { checksize($4,2|4);
+ T_EMIT2($2 | $1 | ($4>>6)+1,0,0,0);
+ T_EMIT2($3,0,0,0);
+ ea_2($4, 0);
+ }
+ | CP TRAPCC cp_cond
+ { T_EMIT2($2 | $1 | 4,0,0,0);
+ T_EMIT2($3,0,0,0);
+ }
+ ;
+cp_cond : '.' absexp
+ { fit(fit6($2));
+ $$ = low6($2);
+ }
+ ;
+bcdx : ABCD
+ | ADDX sizedef
+ { $$ = $1 | $2;}
+ ;
+creg : CREG
+ | SPEC { if ($1 != 075)
+ badoperand();
+ $$ = 04000;
+ }
+ ;
+off_width /* note: these should be curly brackets, but that would
+ * leave us without brackets for expressions.
+ */
+ : '[' abs31 ':' abs31 ']'
+ { $$ = ($2<<6) | $4;
+ }
+ ;
+abs31 : DREG { $$ = 040 | $1;}
+ | absexp { fit(fit5($1));
+ $$ = low5($1);
+ }
+ ;
+op_ea : OP_EA
+ | SZ_EA sizedef
+ { $$ = $1 | $2;}
+ ;
+regs : rrange
+ | regs '/' rrange
+ { $$ = $1 | $3;}
+ ;
+rrange : reg
+ { $$ = 1<<$1;}
+ | reg '-' reg
+ { if ($1 > $3)
+ badoperand();
+ for ($$ = 0; $1 <= $3; $1++)
+ $$ |= (1<<$1);
+ }
+ ;
+ea : DREG
+ { mrg_2 = $1;}
+ | AREG
+ { mrg_2 = 010 | $1;}
+ | SPEC
+ { mrg_2 = $1;}
+ | { mrg_2 = 0; ffew_2 = 0400; /* initialization */}
+ notimmreg
+ | imm
+ ;
+notimmreg
+ : '(' AREG ')'
+ { mrg_2 = 020 | $2;}
+ | '(' AREG ')' '+'
+ { mrg_2 = 030 | $2;}
+ | '-' '(' AREG ')'
+ { mrg_2 = 040 | $3;}
+ | '(' expr ')' sizenon
+ { bd_2 = $2; ea7071($4);
+ RELOMOVE(bd_rel2, relonami);
+ }
+ | '(' bd_areg_index ')'
+ { if ((mrg_2 & INDEX) == 0)
+ ffew_2 |= 0100; /* suppress index */
+ if ( !(mrg_2 & PC_MODE) &&
+ (ffew_2 & 0300) == 0100 &&
+ bd_2.typ==S_ABS && fitw(bd_2.val)
+ )
+ mrg_2 = (loww(bd_2.val)?050:020) | $2;
+ else {
+ mrg_2 = (mrg_2&PC_MODE)?073:(060 | $2);
+ ffew_2 |= 060; /* long displacement */
+ }
+ }
+ | '(' '[' bd_areg_index ']' index_od ')'
+ { switch(mrg_2 & INDEX) {
+ case 0:
+ ffew_2 |= 0163; /* suppress index */
+ break;
+ case DBL_INDEX:
+ serror("bad indexing");
+ case PRE_INDEX:
+ ffew_2 |= 063; break;
+ case POST_INDEX:
+ ffew_2 |= 067; break;
+ }
+ mrg_2 = (mrg_2 & PC_MODE) ? 073 : (060 | $3);
+ }
+ ;
+imm : '#' expr
+ { mrg_2 = 074; bd_2 = $2;
+ RELOMOVE(bd_rel2, relonami);
+ }
+ ;
+bd_areg_index
+ : /* empty */
+ { $$ = 0; ffew_2 |= 0200;
+ /* base-reg suppressed */
+ bd_2.typ = S_ABS; bd_2.val = (valu_t)0;
+ /* zero displacement */
+ }
+ | expr { $$ = 0; ffew_2 |= 0300;
+ bd_2 = $1;
+ RELOMOVE(bd_rel2, relonami);
+ }
+ | areg_index
+ { bd_2.typ = S_ABS; bd_2.val = (valu_t)0;
+ }
+ | expr ',' areg_index
+ { $$ = $3; bd_2 = $1;
+ RELOMOVE(bd_rel2, relonami);
+ }
+ ;
+areg_index
+ : areg
+ | index { $$ = 0;
+ ffew_2 |= 0200; /* base-reg suppressed */
+ mrg_2 |= PRE_INDEX;
+ }
+ | areg ',' index
+ { mrg_2 |= PRE_INDEX;
+ }
+ ;
+areg : AREG
+ | PC { mrg_2 |= PC_MODE;}
+ | ZPC { mrg_2 |= PC_MODE;
+ ffew_2 |= 0200; /* base-reg suppressed */
+ }
+ ;
+index : reg sizedef scale
+ { checksize($2, 2|4);
+ ffew_2 |= $1<<12 | ($2&0200)<<4 | $3;
+ }
+ ;
+scale : /* empty */
+ { $$ = 0;}
+ | '*' absexp
+ { $$ = checkscale($2);}
+ ;
+index_od: /* empty */
+ { od_2.typ = S_ABS; od_2.val = (valu_t)0;}
+ | ',' index
+ { od_2.typ = S_ABS; od_2.val = (valu_t)0;
+ mrg_2 |= POST_INDEX;
+ }
+ | ',' expr
+ { od_2 = $2;
+ RELOMOVE(od_rel2, relonami);
+ }
+ | ',' index ',' expr
+ { od_2 = $4;
+ mrg_2 |= POST_INDEX;
+ RELOMOVE(od_rel2, relonami);
+ }
+ ;
+reg : DREG
+ | AREG
+ { $$ = $1 | 010;}
+ ;
+sizedef : /* empty */
+ { $$ = SIZE_DEF;}
+ | SIZE
+ ;
+sizenon : /* empty */
+ { $$ = SIZE_NON;}
+ | SIZE
+ ;
+ea_ea : ea ','
+ { mrg_1 = mrg_2;
+ bd_1 = bd_2;
+ od_1 = od_2;
+ ffew_1 = ffew_2;
+ RELOMOVE(bd_rel1, bd_rel2);
+ RELOMOVE(od_rel1, od_rel2);
+ }
+ ea
+ ;
--- /dev/null
+/* @(#)mach5.c 1.16 */
+/*
+ * Motorola 68020 auxiliary functions
+ */
+
+/* With pc-relative modes the offset is calulated from the address of the
+ * extension word. This address is not known until the instruction opcode(s)
+ * have been emitted. Since this address is unknown, the offset from pc
+ * cannot be calculated correctly, so it cannot immediately be decided whether
+ * to use mode 072 (pc-relative with 16 bit offset) or mode 073 (pc_relative
+ * with possibly 32 bit offset) Because of this, instruction opcodes
+ * are not really emitted right away, but temporarily stored. This way
+ * the address of the extension word is known so the offset can be calculated
+ * correctly and it then can be decided to use mode 072 or 073; this can be
+ * altered in the instruction opcode, if necessary. For the sake of consistency
+ * the effective address(es) are also stored temporarily. The instruction is
+ * then emitted in one go, by emit_instr().
+ */
+
+emit_instr()
+{
+ register instr_t *ip;
+
+ for (ip=instr; ip<instrp; emit2(ip++->i_word)) {
+#ifdef RELOCATION
+ RELOMOVE(relonami, ip->i_relonami);
+ if (ip->i_reloinfo)
+ newrelo(ip->i_relotype, ip->i_reloinfo | RELBR | RELWR);
+#endif
+ }
+}
+
+
+#ifdef RELOCATION
+t_emit2(word, relotype, reloinfo, relnm)
+short word;
+short relotype;
+valu_t relnm;
+#else
+t_emit2(word)
+short word;
+#endif
+{
+#ifdef RELOCATION
+ if (instrp->i_reloinfo = reloinfo) {
+ RELOMOVE(instrp->i_relonami, relnm);
+ instrp->i_relotype = relotype;
+ }
+#endif
+ instrp++->i_word = word;
+ dot_offset += 2;
+}
+
+#ifdef RELOCATION
+t_emit4(words, relotype, reloinfo, relnm)
+long words;
+short relotype;
+valu_t relnm;
+#else
+t_emit4(words)
+long words;
+#endif
+{
+ T_EMIT2((short)(words>>16), relotype, reloinfo, relnm);
+ T_EMIT2((short)(words), 0, 0, 0);
+}
+
+ea_1(sz, bits)
+{
+ /* Because displacements come in three sizes (null displacement,
+ * word and long displacement), each displacement requires
+ * two bits in the bittable, so two calls to small. Sometimes
+ * one of these calls is a dummy call.
+ */
+
+ register flag;
+ register sm, sm1, sm2;
+
+ if (mrg_1 > 074)
+ serror("no specials");
+ if ((flag = eamode[mrg_1>>3]) == 0)
+ if ((flag = eamode[010 + (mrg_1&07)]) == 0)
+ flag = eamode[015 + (sz>>6)];
+ if ((mrg_1 & 070) == 010)
+ checksize(sz, 2|4);
+ bits &= ~flag;
+ if (bits)
+ serror("bad addressing category");
+ if (mrg_1==073 && (ffew_1 & 0200) == 0 && (bd_1.typ & ~S_DOT) == DOTTYP)
+ bd_1.val -= (DOTVAL + dot_offset);
+
+ if ( (mrg_1==073) || (mrg_1&070)==060 ) {
+ sm = (
+ (mrg_1==073 && (bd_1.typ & ~S_DOT)==DOTTYP)
+ ||
+ (bd_1.typ == S_ABS)
+ );
+ if (small(sm && fitw(bd_1.val), 2)) {
+ sm = (
+ (sm1 = ((ffew_1 & 0307)==0 && fitb(bd_1.val)))
+ ||
+ (sm2 = ((ffew_1 & 0307)==0100 && mrg_1==073))
+ ||
+ (bd_1.val==0)
+ );
+ if (small(sm,2)) {
+ if (sm1) { /* brief format extension */
+ T_EMIT2((ffew_1&0177000) | lowb(bd_1.val),
+ 0, 0, 0);
+ return;
+ }
+ if (sm2) {
+ /* change mode to 072 in opcode word */
+ instr->i_word &= ~1;
+ T_EMIT2(loww(bd_1.val), 0, 0, 0);
+ return;
+ }
+ ffew_1 &= ~040; /* null displacement */
+ }
+ else
+ ffew_1 &= ~020; /* word displacement */
+ } else
+ sm = small(0,2); /* dummy call */
+
+ if (ffew_1 & 3) {
+ sm = (od_1.typ == S_ABS);
+ if (small(sm && fitw(od_1.val), 2))
+ ffew_1 &= small(od_1.val==0, 2) ? ~2 : ~1;
+ else
+ sm = small(0,2); /* dummy call */
+ }
+
+ assert((ffew_1 & 0410) == 0400);
+ T_EMIT2(ffew_1, 0, 0, 0);
+
+ assert(ffew_1 & 060);
+ switch(ffew_1 & 060) {
+ case 020:
+ break;
+ case 040:
+ T_EMIT2(loww(bd_1.val), 0, 0, 0);
+ break;
+ case 060:
+ T_EMIT4( bd_1.val,
+ bd_1.typ,
+ (mrg_1 == 073 && (ffew_1 & 0200) == 0)
+ ? RELPC|RELO4
+ : RELO4,
+ bd_rel1
+ );
+ }
+
+ if (ffew_1 & 3) {
+ switch(ffew_1 & 3) {
+ case 1:
+ break;
+ case 2:
+ T_EMIT2(loww(od_1.val), 0, 0, 0);
+ break;
+ case 3:
+ T_EMIT4(od_1.val, od_1.typ, RELO4, od_rel1);
+ }
+ }
+ return; /* mode 060 and 073 have been dealt with */
+ }
+
+ if (flag & FITW)
+ if (
+ ! fitw(bd_1.val)
+ &&
+ (mrg_1 != 074 || ! fit16(bd_1.val))
+ )
+ nofit();
+ if (flag & FITB) {
+ if (
+ ! fitb(bd_1.val)
+ &&
+ (mrg_1 != 074 || ! fit8(bd_1.val))
+ )
+ nofit();
+ if (mrg_1 == 074)
+ bd_1.val &= 0xFF;
+ }
+ if (flag & PUTL)
+ T_EMIT4(bd_1.val, bd_1.typ, (flag>>8), bd_rel1);
+ if (flag & PUTW)
+ T_EMIT2(loww(bd_1.val), bd_1.typ, (flag>>8), bd_rel1);
+}
+
+ea_2(sz, bits)
+{
+ mrg_1 = mrg_2;
+ bd_1 = bd_2;
+ od_1 = od_2;
+ ffew_1 = ffew_2;
+ RELOMOVE(bd_rel1, bd_rel2);
+ RELOMOVE(od_rel1, od_rel2);
+ ea_1(sz, bits);
+}
+
+checksize(sz, bits)
+{
+ if ((bits & (1 << (sz>>6))) == 0)
+ serror("bad size");
+}
+
+checkscale(val)
+valu_t val;
+{
+ switch(val) {
+ case 1: return 0;
+ case 2: return 1<<9;
+ case 4: return 2<<9;
+ case 8: return 3<<9;
+ default: serror("bad scale"); return 0;
+ }
+}
+
+badoperand()
+{
+ serror("bad operands");
+}
+
+shift_op(opc, sz)
+{
+ if (mrg_1 < 010 && mrg_2 < 010) {
+ T_EMIT2((opc & 0170470) | sz | mrg_1<<9 | mrg_2, 0, 0, 0);
+ return;
+ }
+ if (bd_1.typ != S_ABS || mrg_1 != 074) {
+ badoperand();
+ return;
+ }
+ if (mrg_2 < 010) {
+ fit(fit3(bd_1.val));
+ T_EMIT2((opc & 0170430) | sz | low3(bd_1.val)<<9 | mrg_2,0,0,0);
+ return;
+ }
+ checksize(sz, 2);
+ fit(bd_1.val == 1);
+ T_EMIT2((opc & 0177700) | mrg_2, 0, 0, 0);
+ ea_2(SIZE_W, MEM|ALT);
+}
+
+bitop(opc)
+{
+ register bits;
+
+ bits = DTA|ALT;
+ if (opc == 0 && (mrg_1 < 010 || mrg_2 != 074))
+ bits = DTA;
+ if (mrg_1 < 010) {
+ T_EMIT2(opc | 0400 | mrg_1<<9 | mrg_2, 0, 0, 0);
+ ea_2(0, bits);
+ return;
+ }
+ if (mrg_1 == 074) {
+ T_EMIT2(opc | 04000 | mrg_2, 0, 0, 0);
+ ea_1(SIZE_W, 0);
+ ea_2(0, bits);
+ return;
+ }
+ badoperand();
+}
+
+bitfield(opc, extension)
+{
+ T_EMIT2(opc | mrg_2, 0, 0, 0);
+ T_EMIT2(extension, 0, 0, 0);
+ ea_2(SIZE_L, (mrg_2 < 010) ? 0 : (CTR | ALT));
+}
+
+add(opc, sz)
+{
+ if ((mrg_2 & 070) == 010)
+ checksize(sz, 2|4);
+ if (
+ mrg_1 == 074
+ &&
+ small(
+ bd_1.typ==S_ABS && fit3(bd_1.val),
+ sz==SIZE_L ? 4 : 2
+ )
+ ) {
+ T_EMIT2((opc&0400) | 050000 | low3(bd_1.val)<<9 | sz | mrg_2,
+ 0, 0, 0);
+ ea_2(sz, ALT);
+ return;
+ }
+ if (mrg_1 == 074 && (mrg_2 & 070) != 010) {
+ T_EMIT2((opc&03000) | sz | mrg_2, 0, 0, 0);
+ ea_1(sz, 0);
+ ea_2(sz, DTA|ALT);
+ return;
+ }
+ if ((mrg_2 & 070) == 010) {
+ T_EMIT2((opc&0170300) | (mrg_2&7)<<9 | sz<<1 | mrg_1, 0, 0, 0);
+ ea_1(sz, 0);
+ return;
+ }
+ if (to_dreg(opc, sz, 0))
+ return;
+ if (from_dreg(opc, sz, ALT|MEM))
+ return;
+ badoperand();
+}
+
+and(opc, sz)
+{
+ if (mrg_1 == 074 && mrg_2 >= 076) { /* ccr or sr */
+ if (sz != SIZE_NON)
+ checksize(sz, mrg_2==076 ? 1 : 2);
+ else
+ sz = (mrg_2==076 ? SIZE_B : SIZE_W);
+ T_EMIT2((opc&07400) | sz | 074, 0, 0, 0);
+ ea_1(sz, 0);
+ return;
+ }
+ if (sz == SIZE_NON)
+ sz = SIZE_DEF;
+ if (mrg_1 == 074) {
+ T_EMIT2((opc&07400) | sz | mrg_2, 0, 0, 0);
+ ea_1(sz, 0);
+ ea_2(sz, DTA|ALT);
+ return;
+ }
+ if ((opc & 010000) == 0 && to_dreg(opc, sz, DTA))
+ return;
+ if (from_dreg(opc, sz, (opc & 010000) ? DTA|ALT : ALT|MEM))
+ return;
+ badoperand();
+}
+
+to_dreg(opc, sz, bits)
+{
+ if ((mrg_2 & 070) != 000)
+ return(0);
+ T_EMIT2((opc & 0170000) | sz | (mrg_2&7)<<9 | mrg_1, 0, 0, 0);
+ ea_1(sz, bits);
+ return(1);
+}
+
+from_dreg(opc, sz, bits)
+{
+ if ((mrg_1 & 070) != 000)
+ return(0);
+ T_EMIT2((opc & 0170000) | sz | (mrg_1&7)<<9 | 0400 | mrg_2, 0, 0, 0);
+ ea_2(sz, bits);
+ return(1);
+}
+
+cmp(sz)
+{
+ register opc;
+
+ if ((mrg_1&070) == 030 && (mrg_2&070) == 030) {
+ T_EMIT2(0130410 | sz | (mrg_1&7) | (mrg_2&7)<<9, 0, 0, 0);
+ return;
+ }
+ if (mrg_1 == 074 && (mrg_2 & 070) != 010) {
+ if (mrg_2==074)
+ badoperand();
+ T_EMIT2(06000 | sz | mrg_2, 0, 0, 0);
+ ea_1(sz, 0);
+ ea_2(sz, DTA);
+ return;
+ }
+ if (mrg_2 < 020) {
+ if (mrg_2 >= 010) {
+ checksize(sz, 2|4);
+ opc = 0130300 | sz<<1;
+ mrg_2 &= 7;
+ } else
+ opc = 0130000 | sz;
+ T_EMIT2(opc | mrg_2<<9 | mrg_1, 0, 0, 0);
+ ea_1(sz, 0);
+ return;
+ }
+ badoperand();
+}
+
+link(sz, areg)
+{
+ if (sz == SIZE_NON) {
+ if (bd_2.typ == S_ABS && fitw(bd_2.val))
+ sz = SIZE_W;
+ else
+ sz = SIZE_L;
+ }
+ checksize(sz, 2|4);
+ if (sz == SIZE_W)
+ T_EMIT2(047120 | areg, 0, 0, 0);
+ else /* sz == SIZE_L */
+ T_EMIT2(044010 | areg, 0, 0, 0);
+ ea_2(sz, 0);
+}
+
+move(sz)
+{
+ register opc;
+
+ if (mrg_1 > 074 || mrg_2 > 074) {
+ move_special(sz);
+ return;
+ }
+ if (sz == SIZE_NON)
+ sz = SIZE_DEF;
+ if (
+ mrg_2<010
+ &&
+ mrg_1==074
+ &&
+ sz==SIZE_L
+ &&
+ small(bd_1.typ==S_ABS && fitb(bd_1.val), 4)
+ ) {
+ T_EMIT2(070000 | mrg_2<<9 | lowb(bd_1.val), 0, 0, 0);
+ return;
+ }
+ switch (sz) {
+ case SIZE_B: opc = 010000; break;
+ case SIZE_W: opc = 030000; break;
+ case SIZE_L: opc = 020000; break;
+ }
+ T_EMIT2(opc | mrg_1 | (mrg_2&7)<<9 | (mrg_2&070)<<3, 0, 0, 0);
+ ea_1(sz, 0);
+ ea_2(sz, ALT);
+}
+
+move_special(sz)
+{
+ if (mrg_2 >= 076) {
+ if (sz != SIZE_NON)
+ checksize(sz, 2);
+ T_EMIT2(042300 | (mrg_2==076?0:01000) | mrg_1, 0, 0, 0);
+ ea_1(SIZE_W, DTA);
+ return;
+ }
+ if (mrg_1 >= 076) {
+ if (sz != SIZE_NON)
+ checksize(sz, 2);
+ T_EMIT2(040300 | (mrg_1==076?01000:0) | mrg_2, 0, 0, 0);
+ ea_2(SIZE_W, DTA|ALT);
+ return;
+ }
+ if (sz != SIZE_NON)
+ checksize(sz, 4);
+ if (mrg_1==075 && (mrg_2&070)==010) {
+ T_EMIT2(047150 | (mrg_2&7), 0, 0, 0);
+ return;
+ }
+ if (mrg_2==075 && (mrg_1&070)==010) {
+ T_EMIT2(047140 | (mrg_1&7), 0, 0, 0);
+ return;
+ }
+ badoperand();
+}
+
+movem(dr, sz, regs)
+{
+ register i;
+ register r;
+
+ if ((mrg_2>>3) == 04) {
+ r = regs; regs = 0;
+ for (i = 0; i < 16; i++) {
+ regs <<= 1;
+ if (r & 1)
+ regs++;
+ r >>= 1;
+ }
+ }
+ checksize(sz, 2|4);
+ if ((mrg_2>>3)-3 == dr)
+ badoperand();
+ T_EMIT2(044200 | dr<<10 | (sz & 0200) >> 1 | mrg_2, 0, 0, 0);
+ T_EMIT2(regs, 0, 0, 0);
+ i = CTR;
+ if (dr == 0 && (mrg_2&070) == 040)
+ i = MEM;
+ if (dr != 0 && (mrg_2&070) == 030)
+ i = MEM;
+ if (dr == 0)
+ i |= ALT;
+ ea_2(sz, i);
+}
+
+movep(sz)
+{
+ checksize(sz, 2|4);
+ if (mrg_1<010 && (mrg_2&070)==050) {
+ T_EMIT2(0610 | (sz & 0200)>>1 | mrg_1<<9 | (mrg_2&7), 0, 0, 0);
+ ea_2(sz, 0);
+ return;
+ }
+ if (mrg_2<010 && (mrg_1&070)==050) {
+ T_EMIT2(0410 | (sz & 0200)>>1 | mrg_2<<9 | (mrg_1&7), 0, 0, 0);
+ ea_1(sz, 0);
+ return;
+ }
+ badoperand();
+}
+
+branch(opc, exp)
+expr_t exp;
+{
+ register sm;
+
+ exp.val -= (DOTVAL + 2);
+ if ((pass == PASS_2)
+ &&
+ (exp.val > 0)
+ &&
+ ((exp.typ & S_DOT) == 0)
+ )
+ exp.val -= DOTGAIN;
+ sm = fitw(exp.val);
+ if ((exp.typ & ~S_DOT) != DOTTYP)
+ sm = 0;
+ if (small(sm,2)) {
+ if (small(fitb(exp.val),2)) {
+ if (exp.val == 0)
+ T_EMIT2(047161, 0, 0, 0); /* NOP */
+ else if (exp.val == -1) {
+ T_EMIT2(047161, 0, 0, 0);
+ serror("bad branch offset");
+ } else
+ T_EMIT2(opc | lowb(exp.val), 0, 0, 0);
+ } else {
+ T_EMIT2(opc, 0, 0, 0);
+ T_EMIT2(loww(exp.val), 0, 0, 0);
+ }
+ return;
+ }
+ sm = small(0,2); /* dummy call; two calls to small per branch */
+ T_EMIT2(opc | 0377, 0, 0, 0); /* 4 byte offset */
+ T_EMIT4(exp.val, exp.typ, RELPC|RELO4, relonami);
+}
+
+cpbcc(opc, exp)
+expr_t exp;
+{
+ register sm;
+
+ exp.val -= (DOTVAL + 2);
+ if ((pass == PASS_2)
+ &&
+ (exp.val > 0)
+ &&
+ ((exp.typ & S_DOT) == 0)
+ )
+ exp.val -= DOTGAIN;
+ sm = fitw(exp.val);
+ if ((exp.typ & ~S_DOT) != DOTTYP)
+ sm = 0;
+ if (small(sm,2)) {
+ T_EMIT2(opc, 0, 0, 0);
+ T_EMIT2(loww(exp.val), 0, 0, 0);
+ return;
+ }
+
+ T_EMIT2(opc | 0100, 0, 0, 0); /* 4 byte offset */
+ /* NB: no coprocessor defined extension words are emitted */
+ T_EMIT4(exp.val, exp.typ, RELPC|RELO4, relonami);
+}
+
+ea7071(sz)
+{
+ mrg_2 = 071;
+ switch (sz) {
+ case SIZE_B:
+ badoperand();
+ case SIZE_W:
+ mrg_2 = 070;
+ case SIZE_L:
+ return;
+ case SIZE_NON:
+ break;
+ }
+ /* If this absolute address is in program space, and if we
+ * can assume that the only references to program space are made
+ * by instructins like 'jsr', 'jmp', 'lea' and 'pea', it might
+ * be possible to use a (PC,d16) effective address mode instead
+ * of absolute long. This is done here. If this scheme is in
+ * some way undesirable (e.g. when references to program space
+ * are made by instructions with more than one opcode word or by
+ * second effective addresses in instructions), the rest
+ * of this routine can simply be removed and replaced by the
+ * next two lines (which of course are in comment brackets now).
+ if (small(bd_2.typ == S_ABS && fitw(bd_2.val), 2))
+ mrg_2 = 070;
+ */
+ if (pass == PASS_1) {
+ /* Reserve a bit in the bittable; in the following
+ * passes one call to small() will be done, but know yet
+ * which one, because bd_2.typ cannot be trusted yet.
+ */
+ small(0, 2);
+ return;
+ }
+ if ((bd_2.typ & ~S_DOT) == DOTTYP) {
+ if (small(fitw(bd_2.val-(DOTVAL+2)), 2)) {
+ bd_2.val -= (DOTVAL+2);
+ mrg_2 = 072;
+ }
+ } else
+ if (small(bd_2.typ == S_ABS && fitw(bd_2.val), 2))
+ mrg_2 = 070;
+}