|
|
1.1 root 1: typedef long 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 RF to hold ~0 always, RX as a scratch register,
10: * Rc as a scratch register for forming constants, and
11: * AT to hold the address of the table given in Inittab.
12: */
13: #define R0 0
14: #define As 19
15: #define Ad 20
16: #define Rs 21
17: #define Rd 22
18: #define Rt 23
19: #define Ru 24
20: #define Ri 25
21: #define Ro 26
22: #define Rc 27 /* const temporary */
23: #define RF 16 /* ~0 */
24: #define RX 17 /* scratch */
25: #define AT 18 /* conversion table */
26:
27: /*
28: * Instructions
29: */
30: /* Inst2a */
31: #define SETHI 0x04
32: /* Inst2b */
33: #define BG 0x0A
34: /* Inst3 2 */
35: #define ADD 0x00
36: #define SUB 0x04
37: #define AND 0x01
38: #define OR 0x02
39: #define XOR 0x03
40: #define ANDN 0x05
41: #define ORN 0x06
42: #define SUBcc 0x14
43: #define SLL 0x25
44: #define SRL 0x26
45: #define JMPL 0x38
46: /* Inst3 3 */
47: #define LD 0x00
48: #define LDUB 0x01
49: #define LDUH 0x02
50: #define ST 0x04
51:
52: /*
53: * Generate `a', `size' bits wide, into bit position `shift'.
54: * (to save execution time, the onus is on the caller to make sure that
55: * `a' fits in `size')
56: */
57: #define SM(a,size,shift) ((a)<<(shift))
58:
59: #define Inst2a(rd,op2,i) (SM(rd,5,25)|SM(op2,4,22)|SM(i,22,0))
60: #define Inst2b(a,cond,op2,d) Inst2a(SM(a,1,4)|SM(cond,4,0), op2, d)
61:
62: #define Inst3X(op,rd,op3,rs1) (SM(op,2,30)|SM(rd,5,25)|SM(op3,6,19)|SM(rs1,5,14))
63: #define Inst3a(op,rd,op3,rs1,i,asi,rs2) (Inst3X(op,rd,op3,rs1)|SM(i,1,13)|SM(asi,8,5)|SM(rs2,5,0))
64: #define Inst3b(op,rd,op3,rs1,i,si) (Inst3X(op,rd,op3,rs1)|SM(i,1,13)|SM(si,13,0))
65: #define Inst3c(op,rd,op3,rs1,opf,rs2) (Inst3X(op,rd,op3,rs1)|SM(opf,9,5)|SM(rs2,5,0))
66:
67: #define OpConst(Rdst,Rsrc,op,c) /* Rdst = Rsrc op c */ \
68: if(((ulong)(c)) <= 0xFFF) \
69: *p++ = Inst3b(2,Rdst,op,Rsrc,1,(c)); \
70: else { \
71: RConst(Rc,(c)); \
72: *p++ = Inst3a(2,Rdst,op,Rsrc,0,0,Rc); \
73: }
74:
75: #define RConst(Rdst,c) /* Rdst = c; c is large */ \
76: *p++ = Inst2a(Rdst,SETHI,((ulong)(c))>>10); \
77: *p++ = Inst3b(2,Rdst,OR,Rdst,1,(c)&0x3FF)
78:
79:
80: /*
81: * Macros for assembling the operations of the abstract machine.
82: * Each assumes that ulong *p points to the next location where
83: * an instruction should be assembled.
84: * These macros can use RX as a scratch register, but no others.
85: * They can assume RF holds ~0 and R0 holds 0.
86: */
87:
88: #define Ofield(c) *p++ = Inst3a(2,Rs,XOR,Rs,0,0,Rd); \
89: RConst(Rc,(c)); \
90: *p++ = Inst3a(2,Rs,AND,Rs,0,0,Rc); \
91: *p++ = Inst3a(2,Rs,XOR,Rs,0,0,Rd)
92:
93: #define Olsha_RsRt *p++ = Inst3a(2,Rs,SLL,Rt,1,0,sha)
94: #define Olshb_RsRt *p++ = Inst3a(2,Rs,SLL,Rt,1,0,shb)
95: #define Olsh_RsRd(c) *p++ = Inst3a(2,Rs,SLL,Rd,1,0,(c))
96: #define Olsh_RtRt(c) *p++ = Inst3a(2,Rt,SLL,Rt,1,0,(c))
97: #define Olsha_RtRt *p++ = Inst3a(2,Rt,SLL,Rt,1,0,sha)
98: #define Olsha_RtRu *p++ = Inst3a(2,Rt,SLL,Ru,1,0,sha)
99: #define Olshb_RtRu *p++ = Inst3a(2,Rt,SLL,Ru,1,0,shb)
100: #define Orsha_RsRt *p++ = Inst3a(2,Rs,SRL,Rt,1,0,sha)
101: #define Orshb_RsRt *p++ = Inst3a(2,Rs,SRL,Rt,1,0,shb)
102: #define Orsha_RtRu *p++ = Inst3a(2,Rt,SRL,Ru,1,0,sha)
103: #define Orshb_RtRu *p++ = Inst3a(2,Rt,SRL,Ru,1,0,shb)
104: #define Oorlsha_RsRt *p++ = Inst3a(2,RX,SLL,Rt,1,0,sha); \
105: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX)
106: #define Oorlshb_RsRt *p++ = Inst3a(2,RX,SLL,Rt,1,0,shb); \
107: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX)
108: #define Oorlsh_RsRd(c) *p++ = Inst3a(2,RX,SLL,Rd,1,0,(c)); \
109: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX)
110: #define Oorrsha_RsRt *p++ = Inst3a(2,RX,SRL,Rt,1,0,sha); \
111: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX)
112: #define Oorrshb_RsRt *p++ = Inst3a(2,RX,SRL,Rt,1,0,shb); \
113: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX)
114: #define Oorrsha_RtRu *p++ = Inst3a(2,RX,SRL,Ru,1,0,sha); \
115: *p++ = Inst3a(2,Rt,OR,Rt,0,0,RX)
116: #define Oorrshb_RtRu *p++ = Inst3a(2,RX,SRL,Ru,1,0,shb); \
117: *p++ = Inst3a(2,Rt,OR,Rt,0,0,RX)
118: #define Oor_RsRd *p++ = Inst3a(2,Rs,OR,Rd,0,0,Rs)
119:
120: #define Add_As(c) OpConst(As,As,ADD,(c))
121:
122: #define Add_Ad(c) OpConst(Ad,Ad,ADD,(c))
123:
124: #define Initsd(s,d) RConst(As,((ulong)(s))); \
125: RConst(Ad,((ulong)(d)))
126:
127: #define Initsh(a,b)
128:
129: /* Put all ones in RF */
130: #define Extrainit *p++ = Inst3b(2,RF,ORN,R0,1,0)
131:
132: #define Ilabel(c) RConst(Ri,(c))
133:
134: #define Olabel(c) RConst(Ro,(c))
135:
136: #define Iloop(lp) *p++ = Inst3b(2,Ri,SUBcc,Ri,1,1); \
137: *p = Inst2b(0,BG,0x2,((lp)-p)&0x3FFFFF); p++; \
138: Nop
139:
140: #define Oloop(lp) *p++ = Inst3b(2,Ro,SUBcc,Ro,1,1); \
141: *p = Inst2b(0,BG,0x2,((lp)-p)&0x3FFFFF); p++; \
142: Nop
143:
144: #define Orts *p++ = Inst3b(2,R0,JMPL,15,1,8); \
145: Nop
146:
147: /*
148: * In the predecrement versions, it's as easy to do the decrement afterwards
149: * in the (virtual) delay slot, which will go faster on some versions
150: */
151:
152: #define Load_Rs_P *p++ = Inst3b(3,Rs,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4)
153: #define Load_Rt_P *p++ = Inst3b(3,Rt,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4)
154: #define Loadzx_Rt_P *p++ = Inst3b(3,Rt,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4)
155: #define Loador_Rt_P *p++ = Inst3b(3,Rt,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4)
156: #define Load_Ru_P *p++ = Inst3b(3,Ru,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4)
157: #define Load_Rd_D(f) *p++ = Inst3b(3,Rd,LD,As,1,(-4)&0x1FFF); *p++ = Inst3b(2,As,SUB,As,1,4)
158: #define Load_Rs_D(f) *p++ = Inst3b(3,Rs,LD,As,1,(-4)&0x1FFF); *p++ = Inst3b(2,As,SUB,As,1,4)
159: #define Load_Rt_D(f) *p++ = Inst3b(3,Rt,LD,As,1,(-4)&0x1FFF); *p++ = Inst3b(2,As,SUB,As,1,4)
160: #define Loadzx_Rt_D(f) *p++ = Inst3b(3,Rt,LD,As,1,(-4)&0x1FFF); *p++ = Inst3b(2,As,SUB,As,1,4)
161: #define Load_Rd(f) *p++ = Inst3b(3,Rd,LD,As,1,0)
162: #define Load_Rs(f) *p++ = Inst3b(3,Rs,LD,As,1,0)
163: #define Load_Rt(f) *p++ = Inst3b(3,Rt,LD,As,1,0)
164: #define Loadzx_Rt(f) *p++ = Inst3b(3,Rt,LD,As,1,0)
165: #define Fetch_Rd_P(f) *p++ = Inst3b(3,Rd,LD,Ad,1,0); *p++ = Inst3b(2,Ad,ADD,Ad,1,4)
166: #define Fetch_Rd_D(f) *p++ = Inst3b(3,Rd,LD,Ad,1,(-4)&0x1FFF); *p++ = Inst3b(2,Ad,SUB,Ad,1,4)
167: #define Fetch_Rd(f) *p++ = Inst3b(3,Rd,LD,Ad,1,0);
168: #define Store_Rs_P *p++ = Inst3b(3,Rs,ST,Ad,1,0); *p++ = Inst3b(2,Ad,ADD,Ad,1,4)
169: #define Store_Rs_D *p++ = Inst3b(3,Rs,ST,Ad,1,(-4)&0x1FFF); *p++ = Inst3b(2,Ad,SUB,Ad,1,4)
170: #define Store_Rs *p++ = Inst3b(3,Rs,ST,Ad,1,0)
171: #define Nop *p++ = Inst3a(2,R0,OR,R0,0,0,R0)
172:
173: #define Inittab(t,s) RConst(AT,((ulong)(t)))
174:
175: /* emit code to look up n bits at offset o; table entries are 1<<l bytes long */
176: #define Table_RdRt(o,n,l) \
177: tmp = 32-((o)+(n))-(l); \
178: if(tmp >= 0) \
179: *p++ = Inst3a(2,Rd,SRL,Rt,1,0,tmp); \
180: else if((l) > 0) \
181: *p++ = Inst3a(2,Rd,SLL,Rt,1,0,l); \
182: else \
183: *p++ = Inst3a(2,Rd,ADD,Rt,0,0,R0); \
184: *p++ = Inst3b(2,Rd,AND,Rd,1,((1<<(n))-1)<<(l)); \
185: if(osiz==1) *p++ = Inst3b(3,Rd,LDUB,Rd,0,AT); \
186: else if(osiz==2) *p++ = Inst3b(3,Rd,LDUH,Rd,0,AT); \
187: else *p++ = Inst3b(3,Rd,LD,Rd,0,AT); \
188:
189: #define Table_RsRt(o,n,l) \
190: tmp = 32-((o)+(n))-(l); \
191: *p++ = Inst3a(2,Rs,SRL,Rt,1,0,tmp); \
192: if(tmp >= 0) \
193: *p++ = Inst3a(2,Rs,SRL,Rt,1,0,tmp); \
194: else if((l) > 0) \
195: *p++ = Inst3a(2,Rs,SLL,Rt,1,0,l); \
196: else \
197: *p++ = Inst3a(2,Rs,ADD,Rt,0,0,R0); \
198: if(osiz==1) *p++ = Inst3b(3,Rs,LDUB,Rs,0,AT); \
199: else if(osiz==2) *p++ = Inst3b(3,Rs,LDUH,Rs,0,AT); \
200: else *p++ = Inst3b(3,Rs,LD,Rs,0,AT); \
201:
202: /* emit code to assemble low n bits of Rd into offset o in Rs */
203: #define Assemble(o,n) \
204: if((o) == 0) { \
205: Olsh_RsRd(32-(n)); \
206: } else if((o) == 32-(n)) { \
207: *p++ = Inst3a(2,Rs,OR,Rs,0,0,Rd); \
208: } else { \
209: Oorlsh_RsRd(32-((o)+(n))); \
210: }
211:
212: /* emit code to assemble low n bits of Rd into offset o in Rs.
213: this works by shifting Rd as we go, it only works if
214: the whole word will eventually be filled */
215: #define Assemblex(o,n) \
216: if((o) == 0) { \
217: *p++ = Inst3a(2,Rs,OR,Rd,0,0,R0); \
218: } else { \
219: *p++ = Inst3a(2,Rs,SLL,Rs,1,0,n); \
220: *p++ = Inst3a(2,Rs,OR,Rd,0,0,Rs); \
221: }
222:
223: #define Execandfree(memstart,onstack) \
224: (*(void (*)(void))memstart)(); \
225: if(!onstack) \
226: bbfree(memstart, (p-memstart) * sizeof(Type));
227:
228: #define Emitop \
229: p[0] = fi[0]; \
230: p[1] = fi[1]; \
231: p = (Type*)(((char *)p)+fin)
232:
233: typedef struct Fstr
234: {
235: char fetchs;
236: char fetchd;
237: short n;
238: Type instr[2];
239: } Fstr;
240:
241: Fstr fstr[16] =
242: {
243: [0] 0,0,4, /* Zero */
244: { Inst3a(2,Rs,ADD,R0,0,0,R0), 0 },
245:
246: [1] 1,1,8, /* DnorS */
247: { Inst3a(2,Rs,OR,Rs,0,0,Rd), Inst3a(2,Rs,XOR,Rs,0,0,RF) },
248:
249: [2] 1,1,4, /* DandnotS */
250: { Inst3a(2,Rs,ANDN,Rd,0,0,Rs), 0 },
251:
252: [3] 1,0,4, /* notS */
253: { Inst3a(2,Rs,XOR,Rs,0,0,RF), 0 },
254:
255: [4] 1,1,4, /* notDandS */
256: { Inst3a(2,Rs,ANDN,Rs,0,0,Rd), 0 },
257:
258: [5] 0,1,4, /* notD */
259: { Inst3a(2,Rs,XOR,Rd,0,0,RF), 0 },
260:
261: [6] 1,1,4, /* DxorS */
262: { Inst3a(2,Rs,XOR,Rd,0,0,Rs), 0 },
263:
264: [7] 1,1,8, /* DnandS */
265: { Inst3a(2,Rs,AND,Rd,0,0,Rs), Inst3a(2,Rs,XOR,Rs,0,0,RF) },
266:
267: [8] 1,1,4, /* DandS */
268: { Inst3a(2,Rs,AND,Rd,0,0,Rs), 0 },
269:
270: [9] 1,1,8, /* DxnorS */
271: { Inst3a(2,Rs,XOR,Rd,0,0,Rs), Inst3a(2,Rs,XOR,Rs,0,0,RF) },
272:
273: [10] 0,1,4, /* D */
274: { Inst3a(2,Rs,ADD,Rd,0,0,R0), 0 },
275:
276: [11] 1,1,4, /* DornotS */
277: { Inst3a(2,Rs,ORN,Rd,0,0,Rs), 0 },
278:
279: [12] 1,0,0, /* S */
280: {0, 0},
281:
282: [13] 1,1,4, /* notDorS */
283: { Inst3a(2,Rs,ORN,Rs,0,0,Rd), 0 },
284:
285: [14] 1,1,4, /* DorS */
286: { Inst3a(2,Rs,OR,Rd,0,0,Rs), 0 },
287:
288: [15] 0,0,4, /* F */
289: { Inst3a(2,Rs,OR,R0,0,0,RF), 0 },
290: };
291:
292: #include "tabs.h"
293: static uchar *tabs[4][4] =
294: {
295: { 0, (uchar*)tab01, (uchar*)tab02, (uchar*)tab03},
296: {(uchar*)tab10, 0, (uchar*)tab12, (uchar*)tab13},
297: {(uchar*)tab20, (uchar*)tab21, 0, (uchar*)tab23},
298: {(uchar*)tab30, (uchar*)tab31, (uchar*)tab32, 0},
299: };
300:
301: static uchar tabosiz[4][4] = /* size in bytes of entries */
302: {
303: { 0, 2, 4, 4},
304: { 1, 0, 2, 4},
305: { 1, 1, 0, 2},
306: { 1, 1, 1, 0},
307: };
308:
309: enum {
310: Progmax = 1000, /* max number of bytes in a bitblt prog */
311: Progmaxnoconv = 70, /* max number of Type units when no conversion */
312: };
313:
314:
315: #ifdef TEST
316: void
317: prprog(void)
318: {
319: abort(); /* use db */
320: }
321:
322: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.