initial version

This commit is contained in:
ceriel 1986-12-05 17:09:41 +00:00
parent 9aac83a83e
commit 555c29971f
6 changed files with 1236 additions and 0 deletions

16
mach/z8000/as/mach0.c Normal file
View file

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

78
mach/z8000/as/mach1.c Normal file
View file

@ -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<<b) ) /*bit b set in x?*/
typedef struct address ATYPE;
struct address
{ short seg;
short off;
};
extern expr_t displ; /* never more than 16 bits */
extern short index; /* never more than 16 bits */
extern short mode;
#ifndef extern
extern short modetbl[ 5 ];
#else
short modetbl[5] = { 8, 0, 0, 4, 4 };
/* Modes for REG, IM, IR, DA, X. e.g. modetbl[ 2log REG ]
** is the mode if operand is of type REG.
** No entries for RA, BA and BX are needed.
*/
#endif
extern short operand;
extern short oprtype[ 2 ];
extern expr_t addr_inf; /* .val (address) up to 23 bits! */
extern expr_t immed;
#define regerr() serror("register error")

34
mach/z8000/as/mach2.c Normal file
View file

@ -0,0 +1,34 @@
#define RCSID2 "$Header$"
/*
** Zilog z8000 machine dependent yacc declarations
*/
/* Some of the following mnemonics might seem a little cryptic,
** especially those like F1_1a. The decision to choose these mnemo-
** nics is based on the fact that the manual `Z8000 PLZ/ASM Assembly
** Language Programming Manual' distinguishes some instruction for-
** mats and gave them names like F1.1, etc. In fact section 3.3 of
** this manual describes the instruction set and mentions with each
** instruction also the corresponding instruction format(s). So I
** sorted all instructions on their instruction format(s) resulting
** in groups named F1_1, F1_2, F2_1, etc. (Groups consisting of one
** member where named to that member). Almost all groups were so
** consistent that writing one yacc-rule per group sufficed. Only
** some groups had to be split up resulting in mnemonics like F1_1a
** and F1_1b.
*/
%token <y_word> CALR CC CTLR CTLRFLAGS DJNZ FLAG F1_1a F1_1b
%token <y_word> F1_1F2_3 F1_2 F1_2F6_3 F2_1 F2_1F5_1 F5_1L F5_1R
%token <y_word> F6_4 F6_5 F6_6 F9_1 F9_2 F9_3 IN INTCB JP JR
%token <y_word> LD LDA LDAR LDCTL LDCTLB LDK LDL LDM LDR MREQ
%token <y_word> 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 <y_word> ba bx coco1 coco2 ctlargs ctlbargs da dst flags
%type <y_word> im imexpr ints ir opr option option2 reg src x
%type <y_expr> ra

365
mach/z8000/as/mach3.c Normal file
View file

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

569
mach/z8000/as/mach4.c Normal file
View file

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

174
mach/z8000/as/mach5.c Normal file
View file

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