From: ceriel Date: Thu, 29 Jan 1987 20:15:14 +0000 (+0000) Subject: Initial revision X-Git-Tag: release-5-5~4869 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=31b5e111bf9ec52cc3eb1d15b5b023134a639058;p=ack.git Initial revision --- diff --git a/mach/m68020/as/mach0.c b/mach/m68020/as/mach0.c new file mode 100644 index 000000000..f9a80ab4a --- /dev/null +++ b/mach/m68020/as/mach0.c @@ -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 index 000000000..50e471282 --- /dev/null +++ b/mach/m68020/as/mach1.c @@ -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 index 000000000..48090ccac --- /dev/null +++ b/mach/m68020/as/mach2.c @@ -0,0 +1,65 @@ +/* @(#)mach2.c 1.5 */ +/* + * Motorola 68020 tokens + */ + +%token SIZE +%token DREG +%token AREG +%token PC +%token ZPC +%token CREG +%token SPEC +%token ABCD +%token ADDX +%token ADD +%token AND +%token BITOP +%token BITFIELD +%token BF_TO_D +%token BFINS +%token SHIFT +%token SZ_EA +%token OP_EA +%token OP_NOOP +%token LEA +%token DBR +%token BR +%token OP_EXT +%token OP_RANGE +%token TRAPCC +%token PACK +%token RTM +%token CHK +%token DIVMUL +%token DIVL +%token CMP +%token MOVE +%token MOVEP +%token MOVEM +%token MOVEC +%token MOVES +%token SWAP +%token LINK +%token UNLK +%token TRAP +%token STOP +%token EXG +%token RTD +%token BKPT +%token CALLM +%token CAS +%token CAS2 +%token CP +%token CPBCC +%token CPDBCC +%token CPGEN +%token CPRESTORE +%token CPSAVE +%token CPSCC +%token CPTRAPCC + +%type bcdx op_ea regs rrange +%type reg sizedef sizenon creg +%type off_width abs31 bd_areg_index +%type areg_index areg scale cp_cond diff --git a/mach/m68020/as/mach3.c b/mach/m68020/as/mach3.c new file mode 100644 index 000000000..4396142df --- /dev/null +++ b/mach/m68020/as/mach3.c @@ -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 index 000000000..ca1634b37 --- /dev/null +++ b/mach/m68020/as/mach4.c @@ -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 index 000000000..1e232f2e5 --- /dev/null +++ b/mach/m68020/as/mach5.c @@ -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; ipi_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; +}