|
|
1.1 root 1: typedef ushort Type;
2:
3: /*
4: * See the comments at the beginning of bb.c and bbc.h
5: * for an outline of how this bitblt works
6:
7: * Registers
8: * in addition to the registers of the abstract machine,
9: * we use RY as a scratch register, and AT to hold the
10: * address of the table given in Inittab.
11: */
12: /* A registers */
13: #define As 0
14: #define Ad 1
15: #define AT 2 /* conversion table */
16: #define Ao 3 /* Ro in abstract machine */
17: #define Au 4 /* Ru in abstract machine */
18: /* D registers */
19: #define Rs 0
20: #define Rd 1
21: #define Rt 2
22: #define Ri 3
23: #define Ra 4 /* shift a */
24: #define Rb 5 /* shift b */
25: #define RX 6 /* scratch */
26: #define RY 7 /* scratch */
27:
28: /*
29: * Addressing modes
30: */
31: /* use Rx by itself to get Dn mode */
32: #define AR(n) ((1<<3)|n) /* An */
33: #define AI(n) ((2<<3)|n) /* (An) */
34: #define AIPOST(n) ((3<<3)|n) /* (An)+ */
35: #define AIPRE(n) ((4<<3)|n) /* -(An) */
36: #define AID(n) ((5<<3)|n) /* d16(An) */
37: #define AIX(n) ((6<<3)|n) /* (An+Xm) with following word */
38: #define AIXEXT(m) ((m<<12)|(1<<11)) /* scale factor 1 */
39: #define AIX2EXT(m) ((m<<12)|(1<<11)|(1<<9)) /* scale factor 2 */
40: #define AIX4EXT(m) ((m<<12)|(1<<11)|(2<<9)) /* scale factor 4 */
41: #define IMML ((7<<3)|4) /* immediate long (following) */
42: #define ABSW ((7<<3)|0) /* absolute short address */
43:
44: /* generate `a', `size' bits wide, into bit position `shift' */
45: /* the SMM version is used when there might be extra bits in `a' */
46: #define SM(a,size,shift) ((a)<<(shift))
47: #define SMM(a,size,shift) (((a)&(1<<(size))-1)<<(shift))
48: /*
49: * Instructions
50: * They operate on long words, unless suffixed by 'w' or 'b'
51: * The 'I' instructions must be followed by immediate data (bigendian)
52: */
53:
54: #define MOVE(dmode,smode) (SM(2,4,12)|SMM(dmode,3,9)|SMM((dmode>>3),3,6)|SM(smode,6,0))
55: #define MOVEw(dmode,smode) (SM(3,4,12)|SMM(dmode,3,9)|SMM((dmode>>3),3,6)|SM(smode,6,0))
56: #define MOVEb(dmode,smode) (SM(1,4,12)|SMM(dmode,3,9)|SMM((dmode>>3),3,6)|SM(smode,6,0))
57: #define MOVEQ(dreg,v) (SM(0x7,4,12)|SM(dreg,3,9)|SM(v,8,0))
58: /* MOVEQ sign-extends the 8-bit value; make sure it is masked to 8 bits */
59:
60: #define AND(dreg,smode) (SM(0xC,4,12)|SM(dreg,3,9)|SM(2,3,6)|SM(smode,6,0))
61: #define ANDI(dmode) (SM(0x02,8,8)|SM(2,2,6)|SM(dmode,6,0))
62: #define ANDIw(dmode) (SM(0x02,8,8)|SM(1,2,6)|SM(dmode,6,0))
63:
64: /* the 68020 gnot.h defines an OR */
65: #undef OR
66: #define OR(dreg,smode) (SM(0x8,4,12)|SM(dreg,3,9)|SM(2,3,6)|SM(smode,6,0))
67: #define XOR(dmode,sreg) (SM(0xB,4,12)|SM(sreg,3,9)|SM(6,3,6)|SM(dmode,6,0))
68: #define NOT(dmode) (SM(0x46,8,8)|SM(2,2,6)|SM(dmode,6,0))
69: #define CLR(dmode) (SM(0x42,8,8)|SM(2,2,6)|SM(dmode,6,0))
70:
71: /* LS[LR] can shift 1-8 (n==8 gets smashed to 0, which is the right encoding) */
72: /* else have to put shift amount in reg and use LS[LR]R */
73: #define LSL(dreg,n) (SM(0xE,4,12)|SMM(n,3,9)|SM(1,1,8)|SM(0x11,5,3)|SM(dreg,3,0))
74: #define LSLR(dreg,rn) (SM(0xE,4,12)|SM(rn,3,9)|SM(1,1,8)|SM(0x15,5,3)|SM(dreg,3,0))
75:
76: #define LSR(dreg,n) (SM(0xE,4,12)|SMM(n,3,9)|SM(0,1,8)|SM(0x11,5,3)|SM(dreg,3,0))
77: #define LSRR(dreg,rn) (SM(0xE,4,12)|SM(rn,3,9)|SM(0,1,8)|SM(0x15,5,3)|SM(dreg,3,0))
78:
79: #define ADDA(dareg,smode) (SM(0xD,4,12)|SM(dareg,3,9)|SM(7,3,6)|SM(smode,6,0))
80: #define ADDQ(dmode,v) (SM(0x5,4,12)|SMM(v,3,9)|SM(0,1,8)|SM(2,2,6)|SM(dmode,6,0))
81: #define SUBQ(dmode,v) (SM(0x5,4,12)|SMM(v,3,9)|SM(1,1,8)|SM(2,2,6)|SM(dmode,6,0))
82: #define LEA(dareg,smode) (SM(0x4,4,12)|SM(dareg,3,9)|SM(7,3,6)|SM(smode,6,0))
83:
84: /* BFEXTU and BFINS each must be followed by BFIELD */
85: #define BFEXTU(smode) (SM(0xE9,8,8)|SM(3,2,6)|SM(smode,6,0))
86: #define BFINS(dmode) (SM(0xEF,8,8)|SM(3,2,6)|SM(dmode,6,0))
87:
88: /* low part of r is dst for BFEXTU, src for BFINS */
89: /* offset is from high order bit; w==0 means width of 32 */
90: #define BFIELD(r,o,w) (SM(r,3,12)|SM(o,5,6)|SMM(w,5,0))
91:
92: #define DBF(countreg) (SM(0x5,4,12)|SM(0x39,6,3)|SM(countreg,3,0))
93:
94: #define BCC(cond,d8) (SM(0x6,4,12)|SM(cond,4,8)|SMM(d8,8,0))
95:
96: #define RTS 0x4E75
97:
98: /*
99: * Macros for assembling the operations of the abstract machine.
100: * Each assumes that ushort *p points to the next location where
101: * an instruction should be assembled.
102: * These macros can use RY as a scratch register, but no others.
103: */
104:
105: #define Two(h,l) *(long *)p = (long)(((h)<<16)|(l)); p += 2
106: #define Lsh(r,n) if(n != 0) { \
107: if(n <= 8) \
108: *p++ = LSL(r,n); \
109: else { \
110: *p++ = MOVEQ(RX,n); *p++ = LSLR(r,RX); \
111: } \
112: }
113: #define Rsh(r,n) if(n != 0) { \
114: if(n <= 8) \
115: *p++ = LSR(r,n); \
116: else { \
117: *p++ = MOVEQ(RX,n); *p++ = LSRR(r,RX); \
118: } \
119: }
120: #define Lsha(r) *p++ = LSLR(r,Ra)
121: #define Lshb(r) *p++ = LSLR(r,Rb)
122: #define Rsha(r) *p++ = LSRR(r,Ra)
123: #define Rshb(r) *p++ = LSRR(r,Rb)
124: #define Andcon(r,c) *p++ = ANDI(r); *(long *)p = (long)(c); p += 2
125: #define Movecon(r,c) *p++ = MOVE(r,IMML); *(long *)p = (long)(c); p += 2
126: #define Moveacon(dareg,c) *p++ = MOVE(AR(dareg),IMML); *(long *)p = (long)(c); p += 2
127: /* Addacon assumes value added will fit in a short */
128: #define Addacon(dareg,c) *p++ = LEA(dareg,AID(dareg)); *p++ = c
129: /* Bcc assumes distance to branch is less than short offset */
130: #define Bcc(cond,lp) *p++ = BCC(cond,0); *p++ = ((char*)(lp))-(((char*)p))
131: #define Ofield(c) *p++ = XOR(Rs,Rd); Andcon(Rs,c); *p++ = XOR(Rs,Rd)
132: #define Olsha_RsRt *p++ = MOVE(Rs,Rt); Lsha(Rs)
133: #define Olshb_RsRt *p++ = MOVE(Rs,Rt); Lshb(Rs)
134: #define Olsh_RsRd(c) *p++ = MOVE(Rs,Rd); Lsh(Rs,c)
135: #define Olsh_RtRt(c) Lsh(Rt,c)
136: #define Olsha_RtRt Lsha(Rt)
137: #define Olsha_RtRu Two(MOVE(Rt,AR(Au)),LSLR(Rt,Ra))
138: #define Olshb_RtRu Two(MOVE(Rt,AR(Au)),LSLR(Rt,Rb))
139: #define Orsha_RsRt Two(MOVE(Rs,Rt),LSRR(Rs,Ra))
140: #define Orshb_RsRt Two(MOVE(Rs,Rt),LSRR(Rs,Rb))
141: #define Orsha_RtRu Two(MOVE(Rt,AR(Au)),LSRR(Rt,Ra))
142: #define Orshb_RtRu Two(MOVE(Rt,AR(Au)),LSRR(Rt,Rb))
143: #define Oorlsha_RsRt Two(MOVE(RY,Rt),LSLR(RY,Ra)); *p++ = OR(Rs,RY)
144: #define Oorlshb_RsRt Two(MOVE(RY,Rt),LSLR(RY,Rb)); *p++ = OR(Rs,RY)
145: #define Oorlsh_RsRd(c) *p++ = MOVE(RY,Rd); Lsh(RY,c); *p++ = OR(Rs,RY)
146: #define Oorrsha_RsRt Two(MOVE(RY,Rt),LSRR(RY,Ra)); *p++ = OR(Rs,RY)
147: #define Oorrshb_RsRt Two(MOVE(RY,Rt),LSRR(RY,Rb)); *p++ = OR(Rs,RY)
148: #define Oorrsha_RtRu Two(MOVE(RY,AR(Au)),LSRR(RY,Ra)); *p++ = OR(Rt,RY)
149: #define Oorrshb_RtRu Two(MOVE(RY,AR(Au)),LSRR(RY,Rb)); *p++ = OR(Rt,RY)
150: #define Oor_RsRd *p++ = OR(Rs,Rd)
151: #define Add_As(c) Addacon(As,c)
152: #define Add_Ad(c) Addacon(Ad,c)
153: #define Initsd(s,d) *p++ = MOVE(AR(As),IMML); *(long *)p = (long) (s); p += 2; \
154: *p++ = MOVE(AR(Ad),IMML); *(long *)p = (long) (d); p += 2
155: #define Initsh(a,b) *p++ = MOVEQ(Ra,a); *p++ = MOVEQ(Rb,b)
156:
157: /*
158: * use DBF instruction. assume counts < 16k
159: */
160: #define Ilabel(c) tmp = (c)-1; Movecon(Ri,tmp)
161: #define Olabel(c) Moveacon(Ao,(c))
162: #define Iloop(lp) *p++ = DBF(Ri); *p++ = ((char*)(lp))-((char*)p)
163: #define Oloop(lp) *p++ = SUBQ(AR(Ao),1); *p++ = MOVE(Rs,AR(Ao)); \
164: Bcc(0x6,lp) /* Bne */
165:
166: #define Orts *p++ = RTS
167: #define Nop /* nothing */
168:
169: /*
170: * Load and Fetch macros: arg is ignored for this architecture
171: */
172:
173: #define Load_Rs_P *p++ = MOVE(Rs,AIPOST(As))
174: #define Load_Rt_P *p++ = MOVE(Rt,AIPOST(As))
175: #define Loadzx_Rt_P *p++ = MOVE(Rt,AIPOST(As))
176: #define Loador_Rt_P *p++ = MOVE(Rt,AIPOST(As))
177: #define Load_Ru_P *p++ = MOVE(AR(Au),AIPOST(As))
178: #define Load_Rd_D(f) *p++ = MOVE(Rd,AIPRE(As))
179: #define Load_Rs_D(f) *p++ = MOVE(Rs,AIPRE(As))
180: #define Load_Rt_D(f) *p++ = MOVE(Rt,AIPRE(As))
181: #define Loadzx_Rt_D(f) *p++ = MOVE(Rt,AIPRE(As))
182: #define Load_Rd(f) *p++ = MOVE(Rd,AI(As))
183: #define Load_Rs(f) *p++ = MOVE(Rs,AI(As))
184: #define Load_Rt(f) *p++ = MOVE(Rt,AI(As))
185: #define Loadzx_Rt(f) *p++ = MOVE(Rt,AI(As))
186: #define Fetch_Rd_P(f) *p++ = MOVE(Rd,AIPOST(Ad))
187: #define Fetch_Rd_D(f) *p++ = MOVE(Rd,AIPRE(Ad))
188: #define Fetch_Rd(f) *p++ = MOVE(Rd,AI(Ad))
189: #define Store_Rs_P *p++ = MOVE(AIPOST(Ad),Rs)
190: #define Store_Rs_D *p++ = MOVE(AIPRE(Ad),Rs)
191: #define Store_Rs *p++ = MOVE(AI(Ad),Rs)
192:
193: #define HAVEBF
194: #define Bfextu_RdAd(o,w) *p++ = BFEXTU(AI(Ad)); *p++ = BFIELD(Rd,o,w)
195: #define Bfextu_RsAs(o,w) *p++ = BFEXTU(AI(As)); *p++ = BFIELD(Rs,o,w)
196: #define Bfins_AdRs(o,w) *p++ = BFINS(AI(Ad)); *p++ = BFIELD(Rs,o,w)
197:
198: #define Inittab(t,s) *p++ = MOVE(AR(AT),IMML); *(long *)p = (long) t; p += 2
199:
200: /* look up n bits at offset o in Rt; move table entry (1<<l bytes long) to Rd */
201: #define Table_RdRt(o,n,l) Two(BFEXTU(Rt),BFIELD(Rd,o,n)); \
202: if(osiz==1) { \
203: Two(MOVEb(Rd,AIX(AT)),AIXEXT(Rd)); \
204: } else if(osiz==2) { \
205: Two(MOVEw(Rd,AIX(AT)),AIX2EXT(Rd)); \
206: } else { \
207: Two(MOVE(Rd,AIX(AT)),AIX4EXT(Rd)); \
208: }
209:
210: #define Table_RsRt(o,n,l) Two(BFEXTU(Rt),BFIELD(Rs,o,n)); \
211: if(osiz==1) { \
212: Two(MOVEb(Rs,AIX(AT)),AIXEXT(Rs)); \
213: } else if(osiz==2) { \
214: Two(MOVEw(Rs,AIX(AT)),AIX2EXT(Rs)); \
215: } else { \
216: Two(MOVE(Rs,AIX(AT)),AIX4EXT(Rs)); \
217: }
218:
219: /* emit code to assemble low n bits of Rd into offset o in Rs */
220: #define Assemble(o,n) \
221: if((o) == 0) { \
222: Olsh_RsRd(32-(n)); \
223: } else if((o) == 32-(n)) { \
224: *p++ = OR(Rs,Rd); \
225: } else { \
226: Oorlsh_RsRd(32-((o)+(n))); \
227: }
228: /* emit code to assemble low n bits of Rd into offset o in Rs.
229: this works by shifting Rd as we go, it only works if
230: the whole word will eventually be filled */
231: #define Assemblex(o,n) \
232: if((o) == 0) { \
233: *p++ = MOVE(Rs,Rd); \
234: } else { \
235: Lsh(Rs,n); \
236: *p++ = OR(Rs,Rd); \
237: }
238:
239: #define Extrainit
240:
241: extern void flushvirtpage(void *);
242: extern void bbdflush(void *, int);
243:
244: #define Execandfree(memstart,onstack) \
245: if(onstack) { \
246: flushvirtpage(memstart); \
247: (*(void (*)(void))memstart)(); \
248: } else { \
249: tmp = (p-memstart) * sizeof(Type); \
250: bbdflush(memstart, tmp); \
251: (*(void (*)(void))memstart)(); \
252: bbfree(memstart, tmp); \
253: }
254:
255: /* emit code seq at fi (at most 3 shorts) */
256: #define Emitop \
257: *(long *)p = *(long *)fi; \
258: p[2] = fi[2]; \
259: p = (Type*)(((char *)p)+fin)
260:
261: typedef struct Fstr
262: {
263: short fetchs;
264: short fetchd;
265: int n;
266: Type instr[4];
267: } Fstr;
268:
269: Fstr fstr[16] =
270: {
271: [0] 0,0,2, /* Zero */
272: { CLR(Rs), 0, 0, 0 },
273:
274: [1] 1,1,4, /* DnorS */
275: { OR(Rs,Rd), NOT(Rs), 0, 0},
276:
277: [2] 1,1,4, /* DandnotS */
278: { NOT(Rs), AND(Rs,Rd), 0, 0},
279:
280: [3] 1,0,2, /* notS */
281: { NOT(Rs), 0, 0, 0},
282:
283: [4] 1,1,6, /* notDandS */
284: { NOT(Rs), OR(Rs,Rd), NOT(Rs), 0},
285:
286: [5] 0,1,4, /* notD */
287: { MOVE(Rs,Rd), NOT(Rs), 0, 0},
288:
289: [6] 1,1,2, /* DxorS */
290: { XOR(Rs,Rd), 0, 0, 0},
291:
292: [7] 1,1,4, /* DnandS */
293: { AND(Rs,Rd), NOT(Rs), 0, 0},
294:
295: [8] 1,1,2, /* DandS */
296: { AND(Rs,Rd), 0, 0, 0},
297:
298: [9] 1,1,4, /* DxnorS */
299: { XOR(Rs,Rd), NOT(Rs), 0, 0},
300:
301: [10] 0,1,2, /* D */
302: { MOVE(Rs,Rd), 0, 0, 0},
303:
304: [11] 1,1,4, /* DornotS */
305: { NOT(Rs), OR(Rs,Rd), 0, 0},
306:
307: [12] 1,0,0, /* S */
308: { 0, 0, 0, 0},
309:
310: [13] 1,1,6, /* notDorS */
311: { NOT(Rs), AND(Rs,Rd), NOT(Rs), 0},
312:
313: [14] 1,1,2, /* DorS */
314: { OR(Rs,Rd), 0, 0, 0},
315:
316: [15] 0,0,4, /* F */
317: { CLR(Rs), NOT(Rs), 0, 0},
318: };
319:
320: #include "tabs.h"
321: static uchar *tabs[4][4] =
322: {
323: { 0, (uchar*)tab01, (uchar*)tab02, (uchar*)tab03},
324: {(uchar*)tab10, 0, (uchar*)tab12, (uchar*)tab13},
325: {(uchar*)tab20, (uchar*)tab21, 0, (uchar*)tab23},
326: {(uchar*)tab30, (uchar*)tab31, (uchar*)tab32, 0},
327: };
328:
329: static uchar tabosiz[4][4] = /* size in bytes of entries */
330: {
331: { 0, 2, 4, 4},
332: { 1, 0, 2, 4},
333: { 1, 1, 0, 2},
334: { 1, 1, 1, 0},
335: };
336:
337: enum {
338: Progmax = 1600, /* max number of Type units in a bitblt prog */
339: /* should be bigger if want 0->5 conversion */
340: Progmaxnoconv = 80, /* max number of Type units when no conversion */
341: };
342:
343: #ifdef TEST
344:
345: void
346: prprog(void)
347: {
348: abort(); /* use db */
349: }
350:
351: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.