Initial revision

This commit is contained in:
ceriel 1987-01-29 20:15:14 +00:00
parent 62746ef4ff
commit 31b5e111bf
6 changed files with 1472 additions and 0 deletions

33
mach/m68020/as/mach0.c Normal file
View file

@ -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

99
mach/m68020/as/mach1.c Normal file
View file

@ -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

65
mach/m68020/as/mach2.c Normal file
View file

@ -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

238
mach/m68020/as/mach3.c Normal file
View file

@ -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",

428
mach/m68020/as/mach4.c Normal file
View file

@ -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
;

609
mach/m68020/as/mach5.c Normal file
View file

@ -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;
}