summaryrefslogtreecommitdiff
path: root/sys/src/boot/pc/x16.h
blob: 9727a11e81f6c1f8fe0553099ef018119119f103 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Can't write 16-bit code for 8a without getting into
 * lots of bother, so define some simple commands and
 * output the code directly.
 * 
 * N.B. CALL16(x) kills DI, so don't expect it to be
 * saved across calls.
 */
#define rAX		0		/* rX  */
#define rCX		1
#define rDX		2
#define rBX		3
#define rSP		4		/* SP */
#define rBP		5		/* BP */
#define rSI		6		/* SI */
#define rDI		7		/* DI */

#define rAL		0		/* rL  */
#define rCL		1
#define rDL		2
#define rBL		3
#define rAH		4		/* rH */
#define rCH		5
#define rDH		6
#define rBH		7

#define rES		0		/* rS */
#define rCS		1
#define rSS		2
#define rDS		3
#define rFS		4
#define rGS		5

#define xSI		4		/* rI (index) */
#define xDI		5
#define xBP		6
#define xBX		7

#define rCR0		0		/* rC */
#define rCR2		2
#define rCR3		3
#define rCR4		4

#define OP(o, m, ro, rm)	BYTE $o;	/* op + modr/m byte */	\
			BYTE $(((m)<<6)|((ro)<<3)|(rm))
#define OPrm(o, r, m)	OP(o, 0x00, r, 0x06);	/* general r <-> m */	\
			WORD $m;
#define OPrr(o, r0, r1)	OP(o, 0x03, r0, r1);	/* general r -> r */

#define LW(m, rX)	OPrm(0x8B, rX, m)	/* m -> rX */
#define LXW(x, rI, r)	OP(0x8B, 0x02, r, rI);	/* x(rI) -> r */	\
			WORD $x
#define LBPW(x, r)	OP(0x8B, 0x02, r, xBP);	/* x(rBP) -> r */	\
			WORD $x
#define LB(m, rB)	OPrm(0x8A, rB, m)	/* m -> r[HL] */
#define LXB(x, rI, r)	OP(0x8A, 0x01, r, rI);	/* x(rI) -> r */	\
			BYTE $x
#define LBPB(x, r)	OP(0x8A, 0x01, r, xBP);	/* x(rBP) -> r */	\
			BYTE $x
#define SW(rX, m)	OPrm(0x89, rX, m)	/* rX -> m */
#define SXW(r, x, rI)	OP(0x89, 0x02, r, rI);	/* r -> x(rI) */	\
			WORD $x
#define SBPW(r, x)	OP(0x89, 0x02, r, xBP);	/* r -> x(rBP) */	\
			WORD $(x)
#define SBPWI(i, x)	OP(0xC7, 0x01, 0, xBP);	/* i -> x(rBP) */	\
			BYTE $(x); WORD $(i)
#define STB(rB, m)	OPrm(0x88, rB, m)	/* rB -> m */
#define SXB(r, x, rI)	OP(0x88, 0x01, r, rI);	/* rB -> x(rI) */	\
			BYTE $x
#define SBPB(r, x)	OP(0x88, 0x01, r, xBP);	/* r -> x(rBP) */	\
			BYTE $x
#define SBPBI(i, x)	OP(0xC6, 0x01, 0, xBP);	/* i -> x(rBP) */	\
			BYTE $(x); BYTE $(i)
#define LWI(i, rX)	BYTE $(0xB8+rX);	/* i -> rX */		\
			WORD $i;
#define LBI(i, rB)	BYTE $(0xB0+rB);	/* i -> r[HL] */	\
			BYTE $i

#define MW(r0, r1)	OPrr(0x89, r0, r1)	/* r0 -> r1 */
#define MFSR(rS, rX)	OPrr(0x8C, rS, rX)	/* rS -> rX */
#define MTSR(rX, rS)	OPrr(0x8E, rS, rX)	/* rX -> rS */
#define MFCR(rC, rX)	BYTE $0x0F;		/* rC -> rX */		\
			OP(0x20, 0x03, rC, rX)
#define MTCR(rX, rC)	BYTE $0x0F;		/* rX -> rC */		\
			OP(0x22, 0x03, rC, rX)

#define ADC(r0, r1)	OPrr(0x11, r0, r1)	/* r0 + r1 -> r1 */
#define ADD(r0, r1)	OPrr(0x01, r0, r1)	/* r0 + r1 -> r1 */
#define ADDI(i, r)	OP(0x81, 0x03, 0x00, r);/* i+r -> r */		\
			WORD $i;
#define AND(r0, r1)	OPrr(0x21, r0, r1)	/* r0&r1 -> r1 */
#define ANDI(i, r)	OP(0x81, 0x03, 0x04, r);/* i&r -> r */		\
			WORD $i;
#define CLR(r)		OPrr(0x31, r, r)	/* r^r -> r */
#define CLRB(r)		OPrr(0x30, r, r)	/* r^r -> r */
#define CMP(r0, r1)	OPrr(0x39, r0, r1)	/* r1-r0 -> flags */
#define CMPI(i, r)	OP(0x81, 0x03, 0x07, r);/* r-i -> flags */	\
			WORD $i;
#define CMPBR(r0, r1)	OPrr(0x38, r0, r1)	/* r1-r0 -> flags */
#define DEC(r)		BYTE $(0x48|r)		/* r-1 -> r */
#define DIV(r)		OPrr(0xF7, 0x06, r)	/* rDX:rAX/r -> rAX, rDX:rAX%r -> rDX */
#define INC(r)		BYTE $(0x40|r)		/* r+1 -> r */
#define MUL(r)		OPrr(0xF7, 0x04, r)	/* r*rAX -> rDX:rAX */
#define IMUL(r0, r1)	BYTE $0x0F;		/* r0*r1 -> r1 */	\
			OPrr(0xAF, r1, r0)	/* (signed) */
#define OR(r0, r1)	OPrr(0x09, r0, r1)	/* r0|r1 -> r1 */
#define ORB(r0, r1)	OPrr(0x08, r0, r1)	/* r0|r1 -> r1 */
#define ORI(i, r)	OP(0x81, 0x03, 0x01, r);/* i|r -> r */		\
			WORD $i;
#define ROLI(i, r)	OPrr(0xC1, 0x00, r);	/* r<<>>i -> r */	\
			BYTE $i;
#define SHLI(i, r)	OPrr(0xC1, 0x04, r);	/* r<<i -> r */		\
			BYTE $i;
#define SHLBI(i, r)	OPrr(0xC0, 0x04, r);	/* r<<i -> r */		\
			BYTE $i;
#define SHRI(i, r)	OPrr(0xC1, 0x05, r);	/* r>>i -> r */		\
			BYTE $i;
#define SHRBI(i, r)	OPrr(0xC0, 0x05, r);	/* r>>i -> r */		\
			BYTE $i;
#define SUB(r0, r1)	OPrr(0x29, r0, r1)	/* r1-r0 -> r1 */
#define SUBI(i, r)	OP(0x81, 0x03, 0x05, r);/* r-i -> r */		\
			WORD $i;

#define STOSW		STOSL

#define CALL16(f)	LWI(f, rDI);		/* &f -> rDI */		\
			BYTE $0xFF;		/* (*rDI) */		\
			BYTE $0xD7;
#define FARJUMP16(s, o)	BYTE $0xEA;		/* jump to ptr16:16 */	\
			WORD $o; WORD $s
#define FARJUMP32(s, o)	BYTE $0x66;		/* jump to ptr32:16 */	\
			BYTE $0xEA; LONG $o; WORD $s
#define	DELAY		BYTE $0xEB;		/* jmp .+2 */		\
			BYTE $0x00
#define BIOSCALL(b)	INT $b			/* INT $b */

#define PEEKW		BYTE $0x26;		/* MOVW	rES:[rBX], rAX  */	\
			BYTE $0x8B; BYTE $0x07
#define POKEW		BYTE $0x26;		/* MOVW	rAX, rES:[rBX] */	\
			BYTE $0x89; BYTE $0x07
#define OUTPORTB(p, d)	LBI(d, rAL);		/* d -> I/O port p */	\
			BYTE $0xE6;					\
			BYTE $p; DELAY
#define PUSHA		BYTE $0x60
#define PUSHR(r)	BYTE $(0x50|r)		/* r  -> (--rSP) */
#define PUSHS(rS)	BYTE $(0x06|((rS)<<3))	/* rS  -> (--rSP) */
#define PUSHI(i)	BYTE $0x68; WORD $i;	/* i -> --(rSP) */
#define POPA		BYTE $0x61
#define POPR(r)		BYTE $(0x58|r)		/* (rSP++) -> r */
#define POPS(rS)	BYTE $(0x07|((rS)<<3))	/* (rSP++) -> r */
#define NOP		BYTE $0x90		/* nop */

#define LGDT(gdtptr)	BYTE $0x0F;		/* LGDT */			\
			BYTE $0x01; BYTE $0x16;					\
			WORD $gdtptr

/* operand size switch. */
#define OPSIZE		BYTE $0x66