Initial revision
authorceriel <none@none>
Thu, 29 Jan 1987 20:15:14 +0000 (20:15 +0000)
committerceriel <none@none>
Thu, 29 Jan 1987 20:15:14 +0000 (20:15 +0000)
mach/m68020/as/mach0.c [new file with mode: 0644]
mach/m68020/as/mach1.c [new file with mode: 0644]
mach/m68020/as/mach2.c [new file with mode: 0644]
mach/m68020/as/mach3.c [new file with mode: 0644]
mach/m68020/as/mach4.c [new file with mode: 0644]
mach/m68020/as/mach5.c [new file with mode: 0644]

diff --git a/mach/m68020/as/mach0.c b/mach/m68020/as/mach0.c
new file mode 100644 (file)
index 0000000..f9a80ab
--- /dev/null
@@ -0,0 +1,33 @@
+/* @(#)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
diff --git a/mach/m68020/as/mach1.c b/mach/m68020/as/mach1.c
new file mode 100644 (file)
index 0000000..50e4712
--- /dev/null
@@ -0,0 +1,99 @@
+/* @(#)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
diff --git a/mach/m68020/as/mach2.c b/mach/m68020/as/mach2.c
new file mode 100644 (file)
index 0000000..48090cc
--- /dev/null
@@ -0,0 +1,65 @@
+/* @(#)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
diff --git a/mach/m68020/as/mach3.c b/mach/m68020/as/mach3.c
new file mode 100644 (file)
index 0000000..4396142
--- /dev/null
@@ -0,0 +1,238 @@
+/* @(#)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",
diff --git a/mach/m68020/as/mach4.c b/mach/m68020/as/mach4.c
new file mode 100644 (file)
index 0000000..ca1634b
--- /dev/null
@@ -0,0 +1,428 @@
+/* @(#)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
+       ;
diff --git a/mach/m68020/as/mach5.c b/mach/m68020/as/mach5.c
new file mode 100644 (file)
index 0000000..1e232f2
--- /dev/null
@@ -0,0 +1,609 @@
+/* @(#)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;
+}