|
|
1.1 root 1: /*
2: * See the comments at the beginning of bb.c and bbc.h
3: * for an outline of how this bitblt works
4:
5: * The VGA screen on the 386 has an awful bit/byte order:
6: * the high order bit of a byte is leftmost, but the low
7: * order byte of a word is leftmost.
8: * This is a totally littleendian bitblt, so the bytes will
9: * have to be bit-reversed before putting them on the screen.
10: */
11: typedef uchar Type;
12:
13: /*
14: * Registers:
15: */
16: #define As 6 /* ESI */
17: #define Ad 7 /* EDI */
18: #define Rs 0 /* EAX: FIELD works better with this here */
19: #define Rd 3 /* EBX */
20: #define Rt 2 /* EDX */
21: #define Ru 1 /* ECX */
22: #define RX 5 /* EBP */
23: #define SP 4 /* ESP */
24: /* Ri is top-of-stack, if needed */
25: /* Ro is second-top-of-stack, if needed */
26:
27: /*
28: * Macros for assembling 386 instructions
29: */
30: #define MODRM(mod,rm,reg) (((mod)<<6)|((reg)<<3)|(rm))
31: #define SIB(ss,ind,base) (((ss)<<6)|((ind)<<3)|(base))
32: #define RMR(rm,reg) MODRM(3,rm,reg)
33: #define IRMR(rm,reg) MODRM(0,rm,reg)
34: #define DB(b1,b2,b3,b4) ((b1)|((b2)<<8)|((b3)<<16)|((b4)<<24))
35: #define SB(b1,b2) ((b1)|((b2)<<8))
36:
37: #define OR(src,dst) SB(0x0B, RMR(src,dst))
38: #define XOR(src,dst) SB(0x31, RMR(dst,src))
39: #define AND(src,dst) SB(0x21, RMR(dst,src))
40: #define NOT(r) SB(0xF7, RMR(r,2))
41: #define MOV(src,dst) SB(0x89, RMR(dst,src))
42:
43: #define Immd(v) *(long*)p = (long)(v); p += 4
44: #define Immdb(b1,b2,b3,b4) Immd(DB(b1,b2,b3,b4))
45: #define Imms(v) *(short*)p = (v); p += 2
46: #define Immsb(b1,b2) Imms(SB(b1,b2))
47:
48: #define Load(areg,dst) Immsb(0x8B, IRMR(areg,dst))
49: #define Store(src,areg) Immsb(0x89, IRMR(areg,src))
50: #define Mov(src,dst) Imms(MOV(src,dst))
51: #define Movd(v,dst) *p++ = (0xB8 + (dst)); Immd(v)
52: #define Imov(a,i,r) *p++ = 0x8B; Immsb(IRMR(4,r),SIB(2,i,5)); Immd(a)
53: #define Or(src,dst) Imms(OR(src,dst))
54: #define Xor(src,dst) Imms(XOR(src,dst))
55: #define And(src,dst) Imms(AND(src,dst))
56: #define Andd(v,dst) if(dst==Rs) {\
57: *p++ = 0x25;\
58: } else {\
59: Immsb(0x81, RMR(dst,4));\
60: }\
61: Immd(v)
62: #define Not(r) Imms(NOT(r))
63: #define Inc(r) *p++ = (0x40 + (r))
64: #define Dec(r) *p++ = (0x48 + (r))
65: #define Decsp Immsb(0xFF, IRMR(4,1)); *p++ = SIB(0,4,4)
66: #define Shl(r,sh) Immsb(0xC1, RMR(r,4)); *p++ = (sh)
67: #define Shr(r,sh) Immsb(0xC1, RMR(r,5)); *p++ = (sh)
68: #define Addd(v,r) Immsb(0x81, RMR(r,0)); Immd(v)
69: #define Addbsx(v,r) Immsb(0x83, RMR(r,0)); *p++ = v
70: #define Addsp(v) Immsb(0x83, RMR(4,0)); *p++ = v
71: #define Pushd(v) *p++ = 0x68; Immd(v)
72: #define Loop(d) *p = 0xE2; *(p+1) = d; p += 2
73: #define Jmp8(d) *p = 0xEB; *(p+1) = d; p += 2
74: #define Jmp(d) *p++ = 0xE9; Immd(d)
75: #define Jg8(d) *p = 0x7F; *(p+1) = d; p += 2
76: #define Jle8(d) *p = 0x7E; *(p+1) = d; p += 2
77:
78: #define Ofield(c) Xor(Rd,Rs); Andd(c,Rs); Xor(Rd,Rs)
79: #define Olsha_RsRt Mov(Rt,Rs); Shr(Rs,sha)
80: #define Olshb_RsRt Mov(Rt,Rs); Shr(Rs,shb)
81: #define Olsh_RsRd(sh) Mov(Rd,Rs); Shr(Rs,sh)
82: #define Olsh_RtRt(sh) Shr(Rt,sh)
83: #define Olsha_RtRt Shr(Rt,sha)
84: #define Olsha_RtRu Mov(Ru,Rt); Shr(Rt,sha)
85: #define Olshb_RtRu Mov(Ru,Rt); Shr(Rt,shb)
86: #define Orsha_RsRt Mov(Rt,Rs); Shl(Rs,sha)
87: #define Orshb_RsRt Mov(Rt,Rs); Shl(Rs,shb)
88: #define Orsha_RtRu Mov(Ru,Rt); Shl(Rt,sha)
89: #define Orshb_RtRu Mov(Ru,Rt); Shl(Rt,shb)
90: #define Oorlsha_RsRt Mov(Rt,RX); Shr(RX,sha); Or(RX,Rs)
91: #define Oorlshb_RsRt Mov(Rt,RX); Shr(RX,shb); Or(RX,Rs)
92: #define Oorlsh_RsRd(sh) Mov(Rd,RX); Shr(RX,sh); Or(RX,Rs)
93: #define Oorrsha_RsRt Mov(Rt,RX); Shl(RX,sha); Or(RX,Rs)
94: #define Oorrshb_RsRt Mov(Rt,RX); Shl(RX,shb); Or(RX,Rs)
95: #define Oorrsha_RtRu Mov(Ru,RX); Shl(RX,sha); Or(RX,Rt)
96: #define Oorrshb_RtRu Mov(Ru,RX); Shl(RX,shb); Or(RX,Rt)
97: #define Oor_RsRd Or(Rd,Rs)
98: #define Add_As(v) Addd(v,As)
99: #define Add_Ad(v) Addd(v,Ad)
100: #define Initsd(s,d) Movd(s,As); Movd(d,Ad)
101: #define Ilabel(c) Pushd(c)
102: #define Olabel(c) Pushd(c)
103: #define Iloop(lp) Decsp; \
104: tmp = (lp)-(p+2); \
105: if(tmp > -128) { \
106: Jg8(tmp); \
107: } else { \
108: Jle8(5); \
109: tmp = (lp) - (p+5); \
110: Jmp(tmp); \
111: } \
112: Addsp(4)
113: #define Oloop(lp) Decsp; \
114: tmp = (lp)-(p+2); \
115: if(tmp > -128) { \
116: Jg8(tmp); \
117: } else { \
118: Jle8(5); \
119: tmp = (lp) - (p+5); \
120: Jmp(tmp); \
121: } \
122: Addsp(4)
123: #define Orts *p++ = 0xC3
124: /* load */
125: #define Load_Rs_P Load(As,Rs); Addbsx(4,As)
126: #define Load_Rt_P Load(As,Rt); Addbsx(4,As)
127: #define Loadzx_Rt_P Load(As,Rt); Addbsx(4,As)
128: #define Loador_Rt_P Load(As,Rt); Addbsx(4,As)
129: #define Load_Ru_P Load(As,Ru); Addbsx(4,As)
130: #define Load_Rd_D(f) Addbsx(-4,As); Load(As,Rd)
131: #define Load_Rs_D(f) Addbsx(-4,As); Load(As,Rs)
132: #define Load_Rt_D(f) Addbsx(-4,As); Load(As,Rt)
133: #define Loadzx_Rt_D(f) Addbsx(-4,As); Load(As,Rt)
134: #define Load_Rd(f) Load(As,Rd)
135: #define Load_Rs(f) Load(As,Rs)
136: #define Load_Rt(f) Load(As,Rt)
137: #define Loadzx_Rt(f) Load(As,Rt)
138: /* fetch */
139: #define Fetch_Rd_P(f) Load(Ad,Rd); Addbsx(4,Ad)
140: #define Fetch_Rd_D(f) Addbsx(-4,Ad); Load(Ad,Rd)
141: #define Fetch_Rd(f) Load(Ad,Rd)
142: /* store */
143: #define Store_Rs_P Store(Rs,Ad); Addbsx(4,Ad)
144: #define Store_Rs_D Addbsx(-4,Ad); Store(Rs,Ad)
145: #define Store_Rs Store(Rs,Ad)
146:
147: #define Inittab(t,s)
148: #define Initsh(a,b)
149:
150: /* emit code to look up n bits of Rt at offset o, answer ulong in Rd */
151: #define Table_RdRt(o,n,l) \
152: Mov(Rt,Rd); \
153: if(o) { Shr(Rd,(o)); } \
154: Andd(((1<<(n))-1),Rd); \
155: Imov(tab,Rd,Rd)
156:
157: #define Table_RsRt(o,n,l) \
158: Mov(Rt,Rs); \
159: if(o) { Shr(Rs,o); } \
160: Andd(((1<<(n))-1),Rs); \
161: Imov(tab,Rs,Rs)
162:
163: /* emit code to assemble high n bits of Rd into offset o in Rs */
164: #define Assemble(o,n) \
165: if((o) == 0) { \
166: Olsh_RsRd(32-(n)); \
167: } else if((o) == 32-(n)) { \
168: Or(Rd,Rs); \
169: } else { \
170: Oorlsh_RsRd(32-((o)+(n))); \
171: }
172:
173: /* concept of shifting-as-you-go doesn't work when filling from low end */
174: #define Assemblex(o,n) Assemble(o,n)
175:
176: #define Nop
177:
178: #ifdef TEST
179: #define Extrainit \
180: Movd(lrand(),Rs); \
181: Movd(lrand(),Rd); \
182: Movd(lrand(),Rt); \
183: Movd(lrand(),Ru); \
184: Movd(lrand(),RX)
185: #else
186: #define Extrainit
187: #endif
188:
189: #define Execandfree(memstart,onstack) \
190: (*(void (*)(void))memstart)(); \
191: if(!onstack) \
192: bbfree(memstart, (p-memstart) * sizeof(Type));
193:
194: /* emit code seq at fi (at most 3 shorts) */
195: #define Emitop \
196: *(long *)p = *(long *)fi; \
197: *(short *)(p+4) = *(short *)(((char *)fi)+4); \
198: p = (Type*)(((char *)p)+fin)
199:
200: typedef struct Fstr
201: {
202: short fetchs;
203: short fetchd;
204: int n;
205: short instr[4];
206: } Fstr;
207:
208: Fstr fstr[16] =
209: {
210: [0] 0,0,2, /* Zero */
211: { XOR(Rs,Rs), 0, 0, 0 },
212:
213: [1] 1,1,4, /* DnorS */
214: { OR(Rd,Rs), NOT(Rs), 0, 0},
215:
216: [2] 1,1,4, /* DandnotS */
217: { NOT(Rs), AND(Rd,Rs), 0, 0},
218:
219: [3] 1,0,2, /* notS */
220: { NOT(Rs), 0, 0, 0},
221:
222: [4] 1,1,6, /* notDandS */
223: { NOT(Rs), OR(Rd,Rs), NOT(Rs), 0},
224:
225: [5] 0,1,4, /* notD */
226: { MOV(Rd,Rs), NOT(Rs), 0, 0},
227:
228: [6] 1,1,2, /* DxorS */
229: { XOR(Rd,Rs), 0, 0, 0},
230:
231: [7] 1,1,4, /* DnandS */
232: { AND(Rd,Rs), NOT(Rs), 0, 0},
233:
234: [8] 1,1,2, /* DandS */
235: { AND(Rd,Rs), 0, 0, 0},
236:
237: [9] 1,1,4, /* DxnorS */
238: { XOR(Rd,Rs), NOT(Rs), 0, 0},
239:
240: [10] 0,1,2, /* D */
241: { MOV(Rd,Rs), 0, 0, 0},
242:
243: [11] 1,1,4, /* DornotS */
244: { NOT(Rs), OR(Rd,Rs), 0, 0},
245:
246: [12] 1,0,0, /* S */
247: { 0, 0, 0, 0},
248:
249: [13] 1,1,6, /* notDorS */
250: { NOT(Rs), AND(Rd,Rs), NOT(Rs), 0},
251:
252: [14] 1,1,2, /* DorS */
253: { OR(Rd,Rs), 0, 0, 0},
254:
255: [15] 0,0,4, /* F */
256: { XOR(Rs,Rs), NOT(Rs), 0, 0},
257: };
258:
259: #include "tabs.h"
260:
261: static uchar *tabs[4][4] =
262: {
263: { 0, (uchar*)tab01l, (uchar*)tab02l, (uchar*)tab03l},
264: {(uchar*)tab10l, 0, (uchar*)tab12l, (uchar*)tab13l},
265: {(uchar*)tab20l, (uchar*)tab21l, 0, (uchar*)tab23l},
266: {(uchar*)tab30l, (uchar*)tab31l, (uchar*)tab32l, 0},
267: };
268:
269: static uchar tabosiz[4][4] = /* size in bytes of entries */
270: {
271: { 0, 2, 4, 4},
272: { 1, 0, 2, 4},
273: { 1, 1, 0, 2},
274: { 1, 1, 1, 0},
275: };
276:
277: enum {
278: Progmax = 3000, /* max number of bytes in a bitblt prog */
279: Progmaxnoconv = 200, /* max number when not converting */
280: };
281:
282: #ifdef TEST
283: void
284: prprog(void)
285: {
286: abort(); /* use db */
287: }
288:
289: void
290: bbexec(void (*memstart)(void), int len, int onstack)
291: {
292: memstart();
293: if(!onstack)
294: bbfree(memstart, len);
295: }
296:
297: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.