From 555c29971f7bdef366b2eceaa76540113d8ef590 Mon Sep 17 00:00:00 2001 From: ceriel Date: Fri, 5 Dec 1986 17:09:41 +0000 Subject: [PATCH] initial version --- mach/z8000/as/mach0.c | 16 ++ mach/z8000/as/mach1.c | 78 ++++++ mach/z8000/as/mach2.c | 34 +++ mach/z8000/as/mach3.c | 365 +++++++++++++++++++++++++++ mach/z8000/as/mach4.c | 569 ++++++++++++++++++++++++++++++++++++++++++ mach/z8000/as/mach5.c | 174 +++++++++++++ 6 files changed, 1236 insertions(+) create mode 100644 mach/z8000/as/mach0.c create mode 100644 mach/z8000/as/mach1.c create mode 100644 mach/z8000/as/mach2.c create mode 100644 mach/z8000/as/mach3.c create mode 100644 mach/z8000/as/mach4.c create mode 100644 mach/z8000/as/mach5.c diff --git a/mach/z8000/as/mach0.c b/mach/z8000/as/mach0.c new file mode 100644 index 000000000..398247f00 --- /dev/null +++ b/mach/z8000/as/mach0.c @@ -0,0 +1,16 @@ +#define RCSID0 "$Header$" + +/* +** Zilog z8000 machine dependent options +*/ +#define THREE_PASS +#define BYTES_REVERSED +#define WORDS_REVERSED +#define LISTING +#define ASLD +#undef ALIGNSECT +#define ALIGNSECT 2 +#undef valu_t +#define valu_t long +#undef addr_t +#define addr_t long diff --git a/mach/z8000/as/mach1.c b/mach/z8000/as/mach1.c new file mode 100644 index 000000000..686594bbf --- /dev/null +++ b/mach/z8000/as/mach1.c @@ -0,0 +1,78 @@ +#define RCSID1 "$Header$" + +/* +** Zilog z8000 machine dependent C declarations +*/ +#define REG 1 +#define IM 2 +#define IR 4 +#define DA 8 +#define X 16 +#define RA 32 +#define BA 64 +#define BX 128 + +#define TYPE_11a23 IR | DA | X +#define TYPE_11b23 REG | IR | DA | X +#define TYPE_12 REG | IR | DA | X +#define TYPE_1263 REG | IR | DA | X +#define TYPE_jp IR | DA | X +#define TYPE_21a REG | IR | DA | X +#define TYPE_21b REG +#define TYPE_2151 REG | IM | IR | DA | X +#define TYPE_pop REG | IR | DA | X +#define TYPE_push REG | IM | IR | DA | X +#define TYPE_ldm IR | DA | X +#define TYPE_ld IR | DA | X + +#define DST 0 +#define SRC 1 + +#define DJNZ_ 0xF000 +#define JR_ 0xE000 +#define CALR_ 0xD000 + +#define low3(z) ( ((short) z) & 07 ) +#define low4(z) ( ((short) z) & 017 ) +#define low5(z) ( ((short) z) & 037 ) +#define low7(z) ( ((short) z) & 0177 ) +#define low8(z) ( ((short) z) & 0377 ) +#define low11(z) ( ((short) z) & 03777 ) +#define low12(z) ( ((short) z) & 07777 ) +#define low15(z) ( ((short) z) & 077777 ) +#define fit3(z) ( low3(z) == (z) ) +#define fit4(z) ( low4(z) == (z) ) +#define fit5(z) ( low5(z) == (z) ) +#define fit7(z) ( low7(z) == (z) ) +#define fit8(z) ( low8(z) == (z) ) +#define fits8(z) ( low7(z) == (z) || low7(-z-1) == (-z-1) ) +#define fits12(z) ( low11(z) == (z) || low11(-z-1) == (-z-1) ) +#define fits16(z) ( low15(z) == (z) || low15(-z-1) == (-z-1) ) + +#define bitset(x,b) ( ((int) x) & ((int) 1< CALR CC CTLR CTLRFLAGS DJNZ FLAG F1_1a F1_1b +%token F1_1F2_3 F1_2 F1_2F6_3 F2_1 F2_1F5_1 F5_1L F5_1R +%token F6_4 F6_5 F6_6 F9_1 F9_2 F9_3 IN INTCB JP JR +%token LD LDA LDAR LDCTL LDCTLB LDK LDL LDM LDR MREQ +%token OUT POP PUSH R8 R16 R32 R64 RET SC TCC + + + /* From all addressing modes only 'im' and 'ra' might need more than + ** 16 bits; This is achieved by using the global var 'immed' in + ** case of 'im' and by returning a long in case of 'ra'. + */ +%type ba bx coco1 coco2 ctlargs ctlbargs da dst flags +%type im imexpr ints ir opr option option2 reg src x + +%type ra diff --git a/mach/z8000/as/mach3.c b/mach/z8000/as/mach3.c new file mode 100644 index 000000000..ffea86038 --- /dev/null +++ b/mach/z8000/as/mach3.c @@ -0,0 +1,365 @@ +#define RCSID3 "$Header$" + +/* +** Zilog z8000 keywords +*/ +0, R8, 8, "RL0", +0, R8, 0, "RH0", +0, R8, 9, "RL1", +0, R8, 1, "RH1", +0, R8, 10, "RL2", +0, R8, 2, "RH2", +0, R8, 11, "RL3", +0, R8, 3, "RH3", +0, R8, 12, "RL4", +0, R8, 4, "RH4", +0, R8, 13, "RL5", +0, R8, 5, "RH5", +0, R8, 14, "RL6", +0, R8, 6, "RH6", +0, R8, 15, "RL7", +0, R8, 7, "RH7", +/* Special format for some byte-registers. Not really available on +** the z8000 but designed to ease writing a z8000-backend-table. +** LR[0..7] are equivalent with RL[0..7]. +*/ +0, R8, 8, "LR0", +0, R8, 9, "LR1", +0, R8, 10, "LR2", +0, R8, 11, "LR3", +0, R8, 12, "LR4", +0, R8, 13, "LR5", +0, R8, 14, "LR6", +0, R8, 15, "LR7", +0, R16, 0, "R0", +0, R16, 1, "R1", +0, R16, 2, "R2", +0, R16, 3, "R3", +0, R16, 4, "R4", +0, R16, 5, "R5", +0, R16, 6, "R6", +0, R16, 7, "R7", +0, R16, 8, "R8", +0, R16, 9, "R9", +0, R16, 10, "R10", +0, R16, 11, "R11", +0, R16, 12, "R12", +0, R16, 13, "R13", +0, R16, 14, "R14", +0, R16, 15, "R15", +0, R32, 0, "RR0", +0, R32, 2, "RR2", +0, R32, 4, "RR4", +0, R32, 6, "RR6", +0, R32, 8, "RR8", +0, R32, 10, "RR10", +0, R32, 12, "RR12", +0, R32, 14, "RR14", +0, R64, 0, "RQ0", +0, R64, 4, "RQ4", +0, R64, 8, "RQ8", +0, R64, 12, "RQ12", +0, CC, 14, "NZ", +0, CC, 15, "NC", +0, CC, 13, "PL", +0, CC, 5, "MI", +0, CC, 14, "NE", +0, CC, 6, "EQ", +0, CC, 4, "OV", +0, CC, 12, "NOV", +0, CC, 4, "PE", +0, CC, 12, "PO", +0, CC, 9, "GE", +0, CC, 1, "LT", +0, CC, 10, "GT", +0, CC, 2, "LE", +0, CC, 15, "UGE", +0, CC, 7, "ULT", +0, CC, 11, "UGT", +0, CC, 3, "ULE", +0, FLAG, 0x80, "C", +0, FLAG, 0x40, "Z", +0, FLAG, 0x20, "S", +0, FLAG, 0x10, "P", +0, FLAG, 0x10, "V", +0, INTCB, 2, "VI", +0, INTCB, 1, "NVI", +0, CTLRFLAGS, 1, "FLAGS", +0, CTLR, 2, "FCW", +0, CTLR, 3, "REFRESH", +0, CTLR, 4, "PSAPSEG", +0, CTLR, 5, "PSAPOFF", +0, CTLR, 6, "NSPSEG", +0, CTLR, 7, "NSPOFF", +0, CTLR, 5, "PSAP", +0, CTLR, 7, "NSP", + + /* TYPE_11a23 */ +0, F1_1F2_3, 0x1F00, "call", +0, F1_1F2_3, 0x3900, "ldps", + /* TYPE_11b23 */ +0, F1_1F2_3, 0x0D08, "clr", +0, F1_1F2_3, 0x0C08, "clrb", +0, F1_1F2_3, 0x0D00, "com", +0, F1_1F2_3, 0x0C00, "comb", +0, F1_1F2_3, 0x0D02, "neg", +0, F1_1F2_3, 0x0C02, "negb", +0, F1_1F2_3, 0x0D04, "test", +0, F1_1F2_3, 0x0C04, "testb", +0, F1_1F2_3, 0x1C08, "testl", +0, F1_1F2_3, 0x0D06, "tset", +0, F1_1F2_3, 0x0C06, "tsetb", + +0, F1_1a, 0xB000, "dab", +0, F1_1a, 0xB10A, "exts", +0, F1_1a, 0xB100, "extsb", +0, F1_1a, 0xB107, "extsl", + +0, F1_1b, 0xB300, "rl", +0, F1_1b, 0xB200, "rlb", +0, F1_1b, 0xB308, "rlc", +0, F1_1b, 0xB208, "rlcb", +0, F1_1b, 0xB304, "rr", +0, F1_1b, 0xB204, "rrb", +0, F1_1b, 0xB30C, "rrc", +0, F1_1b, 0xB20C, "rrcb", + + /* TYPE_12 */ +0, F1_2, 0x2B00, "dec", +0, F1_2, 0x2A00, "decb", +0, F1_2, 0x2900, "inc", +0, F1_2, 0x2800, "incb", +0, LDK, 0xBD00, "ldk", + /* TYPE_1263 */ +0, F1_2F6_3, 0x2700, "bit", +0, F1_2F6_3, 0x2600, "bitb", +0, F1_2F6_3, 0x2300, "res", +0, F1_2F6_3, 0x2200, "resb", +0, F1_2F6_3, 0x2500, "set", +0, F1_2F6_3, 0x2400, "setb", + + /* TYPE_jp */ +0, JP, 0x1E00, "jp", + +0, TCC, 0xAF00, "tcc", +0, TCC, 0xAE00, "tccb", + + /* TYPE_21a */ +0, F2_1, 0x2D00, "ex", +0, F2_1, 0x2C00, "exb", + /* TYPE_21b */ +0, F2_1, 0x3500, "adc", +0, F2_1, 0x3400, "adcb", +0, F2_1, 0x3E00, "rldb", +0, F2_1, 0x3C00, "rrdb", +0, F2_1, 0x3700, "sbc", +0, F2_1, 0x3600, "sbcb", + /* TYPE_2151. + ** Depending on their operands the cp-instructions might + ** have an opcode of 0x201 more then listed below. This is + ** added at the appropriate place. + ** The difference in opcode between byte-,word- and long- + ** instructions of the F2_1F5_1 group is as follows: + ** If bit 8 is on it is a word instruction; If it is not a + ** word instruction and bit 12 is on it is a long instruction, + ** else it is a byte instruction. This information is used + ** when one of the operands is of type IM. + */ +0, F2_1F5_1, 0x0100, "add", +0, F2_1F5_1, 0x0000, "addb", +0, F2_1F5_1, 0x1600, "addl", +0, F2_1F5_1, 0x0700, "and", +0, F2_1F5_1, 0x0600, "andb", +0, F2_1F5_1, 0x1B00, "div", +0, F2_1F5_1, 0x1A00, "divl", +0, F2_1F5_1, 0x1900, "mult", +0, F2_1F5_1, 0x1800, "multl", +0, F2_1F5_1, 0x0500, "or", +0, F2_1F5_1, 0x0400, "orb", +0, F2_1F5_1, 0x0300, "sub", +0, F2_1F5_1, 0x0200, "subb", +0, F2_1F5_1, 0x1200, "subl", +0, F2_1F5_1, 0x0900, "xor", +0, F2_1F5_1, 0x0800, "xorb", +0, F2_1F5_1, 0x0B00, "cp", +0, F2_1F5_1, 0x0A00, "cpb", +0, F2_1F5_1, 0x1000, "cpl", + +0, LDA, 0, "lda", + /* TYPE_pop */ +0, POP, 0x1700, "pop", +0, POP, 0x1500, "popl", + /* TYPE_push */ +0, PUSH, 0x1300, "push", +0, PUSH, 0x1100, "pushl", + + /* TYPE_ld */ +0, LD, 0x0100, "ld", +0, LD, 0, "ldb", +0, LDL, 0, "ldl", + +0, DJNZ, 0xF080, "djnz", +0, DJNZ, 0xF000, "dbjnz", +0, JR, 0xE000, "jr", +0, CALR, 0xD000, "calr", + + /* Depending on their operands the LDR-instructions might + ** have an opcode of 0x200 more then listed below. This is + ** or-ed in at the appropriate place. + */ +0, LDR, 0x3100, "ldr", +0, LDR, 0x3000, "ldrb", +0, LDR, 0x3500, "ldrl", + +0, LDAR, 0x3400, "ldar", + +0, F5_1L, 0xB309, "sla", +0, F5_1L, 0xB209, "slab", +0, F5_1L, 0xB30D, "slal", +0, F5_1L, 0xB301, "sll", +0, F5_1L, 0xB201, "sllb", +0, F5_1L, 0xB305, "slll", +0, F5_1R, 0xB309, "sra", +0, F5_1R, 0xB209, "srab", +0, F5_1R, 0xB30D, "sral", +0, F5_1R, 0xB301, "srl", +0, F5_1R, 0xB201, "srlb", +0, F5_1R, 0xB305, "srll", + + /* Depending on its operands the LDM-instruction might have + ** an opcode of 8 more then listed below. This is added at the + ** appropriate place. + ** TYPE_ldm + */ +0, LDM, 0x1C01, "ldm", + + /* For the F6.4 instructions below the yylval-column contains + ** the opcode for the instruction. However the third hexa-digit + ** should be 0; But this is the opcode which must be put into + ** the second word of the instruction! + */ +0, F6_4, 0x3B88, "ind", +0, F6_4, 0x3A88, "indb", +0, F6_4, 0x3B08, "indr", +0, F6_4, 0x3A08, "indrb", +0, F6_4, 0x3B80, "ini", +0, F6_4, 0x3A80, "inib", +0, F6_4, 0x3B00, "inir", +0, F6_4, 0x3A00, "inirb", +0, F6_4, 0xBB89, "ldd", +0, F6_4, 0xBA89, "lddb", +0, F6_4, 0xBB09, "lddr", +0, F6_4, 0xBA09, "lddrb", +0, F6_4, 0xBB81, "ldi", +0, F6_4, 0xBA81, "ldib", +0, F6_4, 0xBB01, "ldir", +0, F6_4, 0xBA01, "ldirb", +0, F6_4, 0x3B0A, "otdr", +0, F6_4, 0x3A0A, "otdrb", +0, F6_4, 0x3B02, "otir", +0, F6_4, 0x3A02, "otirb", +0, F6_4, 0x3B8A, "outd", +0, F6_4, 0x3A8A, "outdb", +0, F6_4, 0x3B82, "outi", +0, F6_4, 0x3A82, "outib", +0, F6_4, 0x3B89, "sind", +0, F6_4, 0x3A89, "sindb", +0, F6_4, 0x3B09, "sindr", +0, F6_4, 0x3A09, "sindrb", +0, F6_4, 0x3B81, "sini", +0, F6_4, 0x3A81, "sinib", +0, F6_4, 0x3B01, "sinir", +0, F6_4, 0x3A01, "sinirb", +0, F6_4, 0x3B0B, "sotdr", +0, F6_4, 0x3A0B, "sotdrb", +0, F6_4, 0x3B03, "sotir", +0, F6_4, 0x3A03, "sotirb", +0, F6_4, 0x3B8B, "soutd", +0, F6_4, 0x3A8B, "soutdb", +0, F6_4, 0x3B83, "souti", +0, F6_4, 0x3A83, "soutib", +0, F6_4, 0xB808, "trdb", +0, F6_4, 0xB80C, "trdrb", +0, F6_4, 0xB800, "trib", +0, F6_4, 0xB804, "trirb", +0, F6_4, 0xB80A, "trtdb", +0, F6_4, 0xB8EE, "trtdrb", +0, F6_4, 0xB802, "trtib", +0, F6_4, 0xB8E6, "trtirb", + + /* From the F6.5 instructions below the last eight ('string'- + ** instructions) want an 'ir' as operand; The others want a 'r'. + ** In the opcode for the string-instructions bit 1 is on, which + ** indicates the difference. + */ +0, F6_5, 0xBB08, "cpd", +0, F6_5, 0xBA08, "cpdb", +0, F6_5, 0xBB0C, "cpdr", +0, F6_5, 0xBA0C, "cpdrb", +0, F6_5, 0xBB00, "cpi", +0, F6_5, 0xBA00, "cpib", +0, F6_5, 0xBB04, "cpir", +0, F6_5, 0xBA04, "cpirb", +0, F6_5, 0xBB0A, "cpsd", +0, F6_5, 0xBA0A, "cpsdb", +0, F6_5, 0xBB0E, "cpsdr", +0, F6_5, 0xBA0E, "cpsdrb", +0, F6_5, 0xBB02, "cpsi", +0, F6_5, 0xBA02, "cpsib", +0, F6_5, 0xBB06, "cpsir", +0, F6_5, 0xBA06, "cpsirb", + +0, F6_6, 0xB30B, "sda", +0, F6_6, 0xB20B, "sdab", +0, F6_6, 0xB30F, "sdal", +0, F6_6, 0xB303, "sdl", +0, F6_6, 0xB203, "sdlb", +0, F6_6, 0xB307, "sdll", + + /* The instructions in\b and out\b have two different opcodes + ** depending on their operands (...). Therefore the opcodes + ** below are not complete. The rest is or-ed in at the ap- + ** propriate place! + ** rest | r and da r and ir + ** --------------------------------- + ** in\b | 0xA04 0xC00 + ** out\b | 0xA06 OxE00 + ** Furthermore the 'special'-instructions don't allow an 'ir' + ** as operand. In their opcode bit 0 is on, which indicates + ** the difference with the other instructions of this group. + */ +0, IN, 0x3100, "in", +0, IN, 0x3000, "inb", +0, IN, 0x3B05, "sin", +0, IN, 0x3A05, "sinb", +0, OUT, 0x3100, "out", +0, OUT, 0x3000, "outb", +0, OUT, 0x3B07, "sout", +0, OUT, 0x3A07, "soutb", + + /* Depending on their operands the LDCTL-instructions might + ** have an opcode of 8 more then listed below. This is or-ed + ** in at the appropriate place. + */ +0, LDCTL, 0x7D00, "ldctl", +0, LDCTLB, 0x8C00, "ldctlb", +0, MREQ, 0x7B0D, "mreq", + +0, F9_1, 0x8D05, "comflg", +0, F9_1, 0x8D03, "resflg", +0, F9_1, 0x8D01, "setflg", + +0, F9_2, 0x7C00, "di", +0, F9_2, 0x7C04, "ei", + +0, F9_3, 0x7A00, "halt", +0, F9_3, 0x7B00, "iret", +0, F9_3, 0x7B0A, "mbit", +0, F9_3, 0x7B09, "mres", +0, F9_3, 0x7B08, "mset", +0, F9_3, 0x8D07, "nop", + + /* Rest of the opcode-0x200 is or-ed in at the appropriate place + */ +0, RET, 0x9E00, "ret", +0, SC, 0x7F00, "sc", diff --git a/mach/z8000/as/mach4.c b/mach/z8000/as/mach4.c new file mode 100644 index 000000000..886536158 --- /dev/null +++ b/mach/z8000/as/mach4.c @@ -0,0 +1,569 @@ +#define RCSID4 "$Header$" + +/* +** Zilog z8000 yacc parsing rules +*/ +operation + : f1 + | f2 + | f3 + | f4 + | f5 + | f6 + | f7 + | f8 + | f9 + ; + + +f1 : F1_1F2_3 dst + { switch( ($1 & 0x0F00)>>8 ) { + case 9: case 0xF: chtype( DST, TYPE_11a23 ); break; + case 0xC: case 0xD: chtype( DST, TYPE_11b23 ); break; + } + emit2( mode | $1 | $2<<4 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + } + | F1_1a reg + { chreg( $1, $2 ); + emit2( $1 | $2<<4 ); + } + | F1_1b reg option + { if ( $3 != 1 && $3 != 2 ) argerr(); + emit2( $1 | $2<<4 | ($3-1)<<1 ); + } + | F1_2 dst option + { chtype( DST, TYPE_12 ); + fit(fit4($3-1)); + emit2( mode | $1 | $2<<4 | $3-1 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + } + | LDK reg ',' imexpr + { fit(fit4($4)); + emit2( $1 | $2<<4 | $4 ); + } + | F1_2F6_3 dst ',' src + { if ( oprtype[ DST ] == REG && oprtype[ SRC ] == REG ) + { emit2( $1 | $4 ); + emit2( $2<<8 ); + } + else if ( oprtype[ SRC ] == IM ) + { chtype( DST, TYPE_1263 ); + if ((immed.typ & ~S_EXT) != S_ABS) { + serror("must be absolute"); + } + if ( bitset($1,8) ) /* word */ fit(fit4(immed.val)); + else /* byte */ fit(fit3(immed.val)); + emit2( mode | $1 | $2<<4 | (int)immed.val ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + } + else argerr(); + } + | JP coco1 dst + { chtype( DST, TYPE_jp ); + emit2( mode | $1 | $3<<4 | $2 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + } + | TCC coco1 reg + { emit2( $1 | $3<<4 | $2 ); } + ; + + +f2 : F2_1 reg ',' src + { switch( ($1 & 0xF000)>>12 ) + { case 2: chtype( SRC, TYPE_21a ); break; + case 3: chtype( SRC, TYPE_21b ); break; + } + emit2( mode | $1 | $4<<4 | $2 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + } + | F2_1F5_1 dst ',' src + { switch( oprtype[ DST ] ) + { case REG: chtype( SRC, TYPE_2151 ); + chreg( $1, $2 ); + emit2( mode | $1 | $4<<4 | $2 ); + break; + case IR: case DA: case X: + if ( oprtype[ SRC ] == IM + && ( $1 == 0x0B00 || $1 == 0x0A00 ) ) + /* cp or cpb */ + { setmode( DST ); + emit2( mode | $1 + 0x201 | $2<<4 ); + break; + } + default: argerr(); + } + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + if ( oprtype[ SRC ] == IM ) + { if (bitset($1,8)) /* word */ { +#ifdef RELOCATION + newrelo(immed.typ, RELO2|RELBR); +#endif + emit2( (int)immed.val ); + } + else if (bitset($1,12)) /* long */ { +#ifdef RELOCATION + newrelo(immed.typ, RELO4|RELWR|RELBR); +#endif + emit4( immed.val ); + } + else /* byte */ { +#ifdef RELOCATION + newrelo(immed.typ, RELO1); +#endif + emit1((int) immed.val); + /* emit1((int) immed.val); ??? twice ??? */ + } + } + } + | LDA R32 ',' src + { switch( oprtype[ SRC ] ) + { case DA: case X: emit2( 0x7600 | $4<<4 | $2 ); + emit_ad( addr_inf ); + break; + case BA: emit2( 0x3400 | $4<<4 | $2 ); +#ifdef RELOCATION + newrelo(displ.typ,RELO2|RELBR); +#endif + emit2( (int) displ.val ); break; + case BX: emit2( 0x7400 | $4<<4 | $2 ); + emit2( index<<8 ); break; + default: argerr(); + } + } + | POP dst ',' ir + { chtype( DST, TYPE_pop ); + emit2( mode | $1 | $4<<4 | $2 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + } + | PUSH ir ',' src + { chtype( SRC, TYPE_push ); + switch ( oprtype[ SRC ] ) + { case IM: if ( $1 == 0x1100 ) /* pushl */ argerr(); + /* { emit2( 0x9109 | $2<<4 ); + ** emit4( immed ); + ** } + */ + else + { emit2( 0x0D09 | $2<<4 ); +#ifdef RELOCATION + newrelo(immed.typ, RELO2|RELBR); +#endif + emit2( (int)immed.val ); + } + break; + default: emit2( mode | $1 | $2<<4 | $4 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + } + } + | LD dst ',' src + { if ( oprtype[ DST ] == REG ) + { switch( oprtype[ SRC ] ) + { case IM: + if ( $1 == 0 ) /* ldb: F3.2 */ + { /* fit(fits8(immed)); */ + emit1( 0xC000 | $2<<8); +#ifdef RELOCATION + newrelo(immed.typ, RELO1); +#endif + emit1((int) immed.val); + } + else + { /*fit(fits16(immed));*/ + emit2( 0x2100 | $2 ); +#ifdef RELOCATION + newrelo(immed.typ, RELO2|RELBR); +#endif + emit2( (int)immed.val ); + } + break; + case REG: case IR: case DA: case X: + setmode( SRC ); + emit2( mode | 0x2000 | $1 | $4<<4 | $2 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + break; + case BA: emit2( 0x3000 | $1 | $4<<4 | $2 ); +#ifdef RELOCATION + newrelo(displ.typ,RELO2|RELBR); +#endif + emit2( (int) displ.val ); + break; + case BX: emit2( 0x7000 | $1 | $4<<4 | $2 ); + emit2( index<<8 ); + break; + default: argerr(); + } + break; + } + if ( oprtype[ SRC ] == REG ) + { switch( oprtype[ DST ] ) + { case IR: case DA: case X: + setmode( DST ); + emit2( mode | 0x2E00 | $1 | $2<<4 | $4 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + break; + case BA: emit2( 0x3200 | $1 | $2<<4 | $4 ); +#ifdef RELOCATION + newrelo(displ.typ,RELO2|RELBR); +#endif + emit2( (int) displ.val ); + break; + case BX: emit2( 0x7200 | $1 | $2<<4 | $4 ); + emit2( index<<8 ); + break; + default: argerr(); + } + break; + } + if ( oprtype[ SRC ] == IM ) /* F5.1 */ + { chtype( DST, TYPE_ld ); + emit2( mode | 0xC05 | $1 | $2<<4 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + if ( $1 == 0 ) /* ldb */ + { /* fit(fits8(immed)); */ +#ifdef RELOCATION + newrelo(immed.typ, RELO1); +#endif + emit1((int) immed.val); + /* emit1((int) immed.val); ??? twice ??? */ + } + else /* ld */ + { /*fit(fits16(immed));*/ +#ifdef RELOCATION + newrelo(immed.typ, RELO2 | RELBR); +#endif + emit2( (int)immed.val ); + } + break; + } + argerr(); + } + | LDL dst ',' src + { if ( oprtype[ DST ] == REG ) + { switch( oprtype[ SRC ] ) + { case IM: emit2( 0x1400 | $2 ); +#ifdef RELOCATION + newrelo(immed.typ, RELO4|RELBR|RELWR); +#endif + emit4( immed.val ); + break; + case REG: case IR: case DA: case X: + setmode( SRC ); + emit2( mode | 0x1400 | $4<<4 | $2 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + break; + case BA: emit2( 0x3500 | $4<<4 | $2 ); +#ifdef RELOCATION + newrelo(displ.typ,RELO2|RELBR); +#endif + emit2((int) displ.val ); + break; + case BX: emit2( 0x7500 | $4<<4 | $2 ); + emit2( index<<8 ); + break; + default: argerr(); + } + break; + } + if ( oprtype[ SRC ] == REG ) + { switch( oprtype[ DST ] ) + { case IR: case DA: case X: + setmode( DST ); + emit2( mode | 0x1D00 | $2<<4 | $4 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); + break; + case BA: emit2( 0x3700 | $2<<4 | $4 ); +#ifdef RELOCATION + newrelo(displ.typ,RELO2|RELBR); +#endif + emit2( (int) displ.val ); + break; + case BX: emit2( 0x7700 | $2<<4 | $4 ); + emit2( index<<8 ); + break; + default: argerr(); + } + break; + } + /* if ( oprtype[ SRC ] == IM ) + ** { chtype( DST, TYPE_ld ); + ** emit2( mode | 0xD07 | $2<<4 ); + ** if ( mode>>12 == 4 ) emit_ad( addr_inf ); + ** emit4( immed ); + ** break; + ** } + */ + argerr(); + } + ; + + +f3 : DJNZ reg ',' ra + { branch( $1 | $2<<8, $4 ); } + | JR coco1 ra + { branch( $1 | $2<<8, $3 ); } + | CALR ra + { branch( $1, $2 ); } + ; + + +f4 : LDR reg ',' ra + { ldrel( $1 | $2, $4 ); } + | LDR ra ',' reg + { ldrel( $1 | 0x200 | $4, $2 ); } + | LDAR R32 ',' ra + { ldrel( $1 | $2, $4 ); } + ; + + +f5 : F5_1L reg option + { if ( $3 < 0 ) + { warning( "neg src results in a right shift!" ); + warning( "warning only"); + } + shiftcode( $1 | $2<<4, $3 ); + } + | F5_1R reg option2 + { if ( $3 > 0 ) + { warning( "pos src results in a left shift!" ); + warning( "warning only"); + } + shiftcode( $1 | $2<<4, $3 ); + } + ; + +option2 : ',' imexpr + { $$ = $2; } + | /* empty */ + { $$ = -1; } + ; + +f6 : LDM dst ',' src ',' imexpr + { switch( oprtype[ DST ] ) + { case REG: chtype( SRC, TYPE_ldm ); + ldmcode( $1 | $4<<4, $2, $6 ); + break; + default: switch( oprtype[ SRC ] ) + { case REG: chtype( DST, TYPE_ldm ); + ldmcode($1+8 | $2<<4, $4, $6); + break; + default: argerr(); + } + } + } + | F6_4 ir ',' ir ',' R16 + { /* For translate instructions the roles of $2 and $4 + ** are interchanged with respect to the other + ** instructions of this group. + */ + if ( ($1 & 0xB8FF) == $1 ) + { /* translate instruction */ + emit2( ($1 & ~0xF0) | $2<<4 ); + emit2( ($1 & 0xF0)>>4 | $6<<8 | $4<<4 ); + } + else + { emit2( ($1 & ~0xF0) | $4<<4 ); + emit2( ($1 & 0xF0)>>4 | $6<<8 | $2<<4 ); + } + } + | F6_5 dst ',' ir ',' R16 coco2 + { switch( oprtype[ DST ] ) + { case REG: if ( bitset($1,1) ) argerr(); break; + case IR : if ( !bitset($1,1) ) argerr(); break; + default : argerr(); + } + emit2( $1 | $4<<4 ); + emit2( $6<<8 | $2<<4 | $7 ); + } + | F6_6 reg ',' R16 + { emit2( $1 | $2<<4 ); + emit2( $4<<8 ); + } + ; + + +f7 : IN reg ',' da + { emit2( $1 | 0xA04 | $2<<4 ); +#ifdef RELOCATION + newrelo(adr_inf.typ, RELO2|RELBR); +#endif + emit2( (short)addr_inf.val ); /* i/o address */ + } + | OUT da ',' reg + { emit2( $1 | 0xA06 | $4<<4 ); +#ifdef RELOCATION + newrelo(adr_inf.typ, RELO2|RELBR); +#endif + emit2( (short)addr_inf.val ); /* i/o address */ + } + | IN reg ',' ir + { if ( bitset($1,0) ) argerr(); + emit2( $1 | 0xC00 | $4<<4 | $2 ); + } + | OUT ir ',' reg + { if ( bitset($1,0) ) argerr(); + emit2( $1 | 0xE00 | $2<<4 | $4 ); + } + ; + + +f8 : LDCTL ctlargs + { emit2( $1 | $2 ); } + | LDCTLB ctlbargs + { emit2( $1 | $2 ); } + | MREQ reg + { emit2( $1 | $2<<4 ); } + ; +ctlargs : CTLR ',' R16 + { $$ = $3<<4 | $1 | 8; } + | R16 ',' CTLR + { $$ = $1<<4 | $3; } + ; +ctlbargs: CTLRFLAGS ',' R8 + { $$ = $3<<4 | $1 | 8;} + | R8 ',' CTLRFLAGS + { $$ = $1<<4 | $3; } + ; + + + + +f9 : F9_1 flags + { emit2( $1 | $2 ); } + | F9_2 ints + { emit2( $1 | $2 ); } + | F9_3 + { emit2( $1 ); } + | RET + { emit2( $1 | 8 ); } + | RET CC + { emit2( $1 | $2 ); } + | SC imexpr + { fit(fit8($2)); + emit2( $1 | $2 ); + } + ; +flags : flags ',' FLAG + { $$ = $1 | $3; } + | FLAG + { $$ = $1; } + ; +ints : ints ',' INTCB + { $$ = $1 | $3; } + | INTCB + { $$ = $1; } + ; + + + + +coco1 : CC ',' + { $$ = $1; } + | /* empty */ + { $$ = 8; } + ; +coco2 : ',' CC + { $$ = $2; } + | /* empty */ + { $$ = 8; } + ; +option : ',' imexpr + { $$ = $2; } + | /* empty */ + { $$ = 1; } + ; +/* `imexpr', just as `im', is used to implement immediate data. +** But `imexpr' is used in those cases where the immediate value +** always will fit into 16 bits, so (long) `immed' is not needed. +** Those cases are in `option', `option2', f9-`SC', f6-`LDM' and +** f1-`LDK'. +*/ +imexpr : '$' absexp + { $$ = $2; } + ; +/* Destination (dst) as well as source (src) operands never +** have RA as addressing mode, except for some instructions of the +** F3 and F4 instruction format group. In those cases RA is even +** the only addressing mode which is allowed. This is why `ra' +** has a yacc-rule not being part of `opr'. +*/ +ra : expr + { $$ = $1; } + ; +dst : { operand = DST;} + opr + { $$ = $2; } + ; +src : { operand = SRC;} + opr + { $$ = $2; } + ; +opr : reg + { settype( REG ); } + | im + { settype( IM ); } + | ir + { settype( IR ); } + | da + { settype( DA ); } + | x + { settype( X ); } + | ba + { settype( BA ); } + | bx + { settype( BX ); } + ; +reg : R8 + | R16 + | R32 + | R64 + ; +im : '$' expr + { $$ = 0; + immed = $2; + } + | '$' '<' '<' expr '>' '>' expr + { $$ = 0; + immed.typ = combine($4.typ, $7.typ, '+'); + immed.val = $4.val<<16 | $7.val; + } + ; +ir : '*' R32 + { if ( $2 == 0 ) regerr(); + $$ = $2; + } + ; +da : expr + { $$ = 0; + addr_inf = $1; + } + | '<' '<' expr '>' '>' expr + { $$ = 0; + addr_inf.typ = combine( $3.typ, $6.typ, '+' ); + addr_inf.val = $3.val<<16 | $6.val; + } + ; +x : expr '(' R16 ')' + { if ( $3 == 0 ) regerr(); + $$ = $3; + addr_inf = $1; + } + | '<' '<' expr '>' '>' expr '(' R16 ')' + { if ( $8 == 0 ) regerr(); + $$ = $8; + addr_inf.typ = combine( $3.typ, $6.typ, '+' ); + addr_inf.val = $3.val<<16 | $6.val; + } + ; +ba : R32 '(' '$' expr ')' + { if ( $1 == 0 ) regerr(); + $$ = $1; + displ = $4; + } + ; +bx : R32 '(' R16 ')' + { if ( $1 == 0 || $3 == 0 ) regerr(); + $$ = $1; + index = $3; + } + ; diff --git a/mach/z8000/as/mach5.c b/mach/z8000/as/mach5.c new file mode 100644 index 000000000..93724b675 --- /dev/null +++ b/mach/z8000/as/mach5.c @@ -0,0 +1,174 @@ +#define RCSID5 "$Header$" + +settype( type ) +int type; +{ oprtype[ operand ] = type; } + + +short twolog( s ) +short s; +{ short twopower = 0; + while ( (s>>=1) != 0 ) twopower++; + return( twopower ); +} + + +setmode( opr ) +short opr; +{ mode = modetbl[ twolog( oprtype[opr] ) ] << 12; } + + +chtype( opr, typerange ) +short opr, + typerange; +/* Check type of 'opr' with given 'typerange' and +** set the global var 'mode'. +*/ +{ if ( (oprtype[opr] & typerange) != oprtype[opr] ) argerr(); + else /* We have a permitted type for 'opr'. */ setmode( opr ); +} + + +chreg( opc, reg ) +short opc, reg; +{ switch( opc ) { + case 0xB10A: case 0x1B00: case 0x1900: + /* R32 expected */ if (reg & 1) regerr(); break; + case 0xB107: case 0x1A00: case 0x1800: + /* R64 expected */ if (reg & 3) regerr(); break; + } +} + +ATYPE checkaddr( addr ) +valu_t addr; +/* Called by functions emit_ad() and branch(). */ +{ ATYPE addr_struct; + + addr_struct.seg = addr >> 16; + addr_struct.off = addr & 0xFFFF; + if ( addr_struct.seg < 0 ) addr_struct.seg = 0; +#ifdef ASLD + else fit(fit7(addr_struct.seg)); +#endif + return( addr_struct ); +} + +emit_ad( ad_inf ) +expr_t ad_inf; +/* When the type of an operand is 'da' or 'x' this function +** emits the address. +*/ +{ short sm; + ATYPE addr; + + addr = checkaddr( ad_inf.val ); + /* Always the long format is emitted, because the binary + ** will be downloaded into one z8000-segment with offset + ** 0x0000 upto 0xFFFF,so the chance we can use the short + ** format is very small. + */ + emit2( 1<<15 | addr.seg<<8 ); + emit2( addr.off ); /* ??? relocation information ??? */ +} + + +ldmcode( wrd1, wrd2, num ) +int wrd1, wrd2, num; +{ fit(fit4(num-1)); + emit2( mode | wrd1 ); + emit2( wrd2<<8 | num-1 ); + if ( mode>>12 == 4 ) emit_ad( addr_inf ); +} + + +valu_t adjust( absval ) +valu_t absval; +{ valu_t val = absval - DOTVAL - 2; + + if ( pass == PASS_2 && val > 0 ) val -= DOTGAIN; + return( val ); +} + + +branch( opc, exp ) +short opc; +expr_t exp; +/* This routine determines for the F3 format instructions whether the +** relative address is small enough to fit in normal code; If this is +** so normal code is emitted otherwise 'long' code is emitted contai- +** ning the direct address. +*/ +{ short longopc = 0, reladdr = 0, sm2, sm4; + valu_t val; + ATYPE addr; + + val = adjust(exp.val) >> 1; + if ( (exp.typ & ~S_DOT) != DOTTYP ) sm2 = sm4 = 0; + else + { switch ( opc & 0xF000 ) + { case DJNZ_: sm2 = fit7( -val ); + reladdr = -val; + break; + case JR_: sm2 = fits8( val ); + reladdr = low8( val ); + longopc = 0x5E00 | (opc>>8 & 0xF); + break; + case CALR_: sm2 = fits12( -val ); + reladdr = low12( -val ); + longopc = 0x5F00; + break; + } + sm4 = sm2 || fit8( (short)exp.val ); + } + switch ( opc & 0xF000 ) + { case DJNZ_: fit( sm2 ); /* djnz must be short */ + emit2( opc | reladdr ); + break; + case JR_: case CALR_: + sm4 = small(sm4, 2); + sm2 = small(sm2, 2); + if ( sm2 ) emit2( opc | reladdr ); + else /* replace by jp/call da */ + { emit2( longopc ); + addr = checkaddr( exp.val ); + if ( sm4 ) /* short-offset */ + emit2( addr.seg<<8 | addr.off ); + else + { emit2( 1<<15 | addr.seg<<8 ); + emit2( addr.off ); + } + } + } +} + + +ldrel( opc, exp ) +short opc; +expr_t exp; +/* This routine determines for the F4 format instructions whether the +** address is within the same segment (meaning a relative address of +** less than 16 bits); If this is so normal code is emitted otherwise +** an error message is given. +*/ +{ if ( pass >= PASS_2 && (exp.typ & ~S_DOT) != DOTTYP ) + serror( "relative too far" ); + emit2( opc ); + emit2( (short)adjust(exp.val) ); +} + + +shiftcode( w1, w2 ) +int w1, w2; +{ switch( w1 & 0x0F04 ) + { /* Remember: w2 negative means right shift ! */ + case 0x200: /*byte*/ fit( w2>=-8 && w2<=8 ); break; + case 0x300: /*word*/ fit( w2>=-16 && w2<=16 ); break; + case 0x304: /*long*/ fit( w2>=-32 && w2<=32 ); break; + } + emit2( w1 ); + emit2( w2 ); +} + + +argerr() +{ serror( "illegal operand" ); } -- 2.34.1