initial version
This commit is contained in:
parent
9aac83a83e
commit
555c29971f
6 changed files with 1236 additions and 0 deletions
16
mach/z8000/as/mach0.c
Normal file
16
mach/z8000/as/mach0.c
Normal 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
78
mach/z8000/as/mach1.c
Normal 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
34
mach/z8000/as/mach2.c
Normal 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
365
mach/z8000/as/mach3.c
Normal 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
569
mach/z8000/as/mach4.c
Normal 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
174
mach/z8000/as/mach5.c
Normal 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" ); }
|
Loading…
Reference in a new issue