|
|
1.1 root 1: #if USE_LOW_OPTIMIZER
2: /* Welcome to the magical world of cpp ;-) */
3:
4: /* This was broken by the advent of FPU emulation. It also didn't
5: provide any useful speedup while it worked. *Sigh* Someone fix my
6: software, please ;-) */
7:
8: #define MAXLOPTINST 100
9:
10: #define LDECISION currprefs.comp_lowopt
11:
12: #define lopt_op0(dummy) lopt_store_op0(
13: #define lopt_op1(a1) lopt_store_op1(LOPT_##a1,
14: #define lopt_op2(a1,a2) lopt_store_op2(LOPT_##a1,LOPT_##a2,
15: #define lopt_op3(a1,a2,a3) lopt_store_op3(LOPT_##a1,LOPT_##a2,LOPT_##a3,
16: #define lopt_op4(a1,a2,a3,a4) lopt_store_op4(LOPT_##a1,LOPT_##a2,LOPT_##a3,LOPT_##a4,
17: #define lopt_op5(a1,a2,a3,a4,a5) lopt_store_op5(LOPT_##a1,LOPT_##a2,LOPT_##a3,LOPT_##a4,LOPT_##a5,
18:
19: #define ldirect0(dummy) ()
20: #define ldirect1(a1) (LDIR_##a1)
21: #define ldirect2(a1,a2) (LDIR_##a1,LDIR_##a2)
22: #define ldirect3(a1,a2,a3) (LDIR_##a1,LDIR_##a2,LDIR_##a3)
23: #define ldirect4(a1,a2,a3,a4) (LDIR_##a1,LDIR_##a2,LDIR_##a3,LDIR_##a4)
24: #define ldirect5(a1,a2,a3,a4,a5) (LDIR_##a1,LDIR_##a2,LDIR_##a3,LDIR_##a4,LDIR_##a5)
25:
26: #define NONE 0
27: #define READ 1
28: #define WRITE 2
29: #define RMW (READ|WRITE)
30:
31: #define SIZE1 4
32: #define SIZE2 8
33: #define SIZE4 12
34: #define FLOAT 16
35: #define SIZEMASK 12
36:
37: #define LIMM NONE
38: #define LR1 (READ | SIZE1)
39: #define LR2 (READ | SIZE2)
40: #define LR4 (READ | SIZE4)
41: #define LW1 (WRITE | SIZE1)
42: #define LW2 (WRITE | SIZE2)
43: #define LW4 (WRITE | SIZE4)
44: #define LRW1 (RMW | SIZE1)
45: #define LRW2 (RMW | SIZE2)
46: #define LRW4 (RMW | SIZE4)
47: #define LFW (READ | FLOAT)
48: #define LFR (WRITE | FLOAT)
49: #define LFRW (RMW | FLOAT)
50: #define LMEMR NONE
51: #define LMEMW NONE
52: #define LMEMRW NONE
53:
54: #define LOPT_IMM LIMM,
55: #define LOPT_R1 LR1 ,
56: #define LOPT_R2 LR2 ,
57: #define LOPT_R4 LR4 ,
58: #define LOPT_W1 LW1 ,
59: #define LOPT_W2 LW2 ,
60: #define LOPT_W4 LW4 ,
61: #define LOPT_RW1 LRW1,
62: #define LOPT_RW2 LRW2,
63: #define LOPT_RW4 LRW4,
64: #define LOPT_FR LFR,
65: #define LOPT_FW LFW,
66: #define LOPT_FRW LFRW,
67: #define LOPT_MEMR LMEMR,
68: #define LOPT_MEMW LMEMW,
69: #define LOPT_MEMRW LMEMRW,
70:
71: #define LDIR_IMM
72: #define LDIR_R1
73: #define LDIR_R2
74: #define LDIR_R4
75: #define LDIR_W1
76: #define LDIR_W2
77: #define LDIR_W4
78: #define LDIR_RW1
79: #define LDIR_RW2
80: #define LDIR_RW4
81: #define LDIR_FW
82: #define LDIR_FR
83: #define LDIR_FRW
84: #define LDIR_MEMR
85: #define LDIR_MEMW
86: #define LDIR_MEMRW
87:
88:
89: #undef LOWFUNC
90: #undef LENDFUNC
91:
92: #define LOWFUNC(flags,mem,nargs,func,args) \
93: STATIC_INLINE void do_##func args
94:
95: #define LENDFUNC(flags,mem,nargs,func,args) \
96: STATIC_INLINE void func args \
97: { \
98: if (LDECISION) { \
99: lopt_op##nargs##args do_##func, mem, flags); \
100: } else { \
101: do_##func ldirect##nargs##args; \
102: } \
103: }
104:
105: typedef struct lopt_inst_rec {
106: void* func;
107: uae_u32 args[5];
108: uae_u8 argtype[5];
109: uae_s8 nargs;
110: uae_u8 mem;
111: uae_u8 flags;
112: } lopt_inst;
113:
114:
115:
116: static lopt_inst linst[MAXLOPTINST];
117: static int lopt_index=0;
118:
119: STATIC_INLINE int argsize(int type)
120: {
121: return type&SIZEMASK;
122: }
123:
124: STATIC_INLINE int reads_mem(int i) {
125: return linst[i].mem & READ;
126: }
127:
128:
129: STATIC_INLINE int access_reg(int i, int r, int mode)
130: {
131: int k;
132: for (k=0;k<linst[i].nargs;k++)
133: if (linst[i].args[k]==r &&
134: (linst[i].argtype[k]&mode) &&
135: !(linst[i].argtype[k]&FLOAT))
136: return 1;
137: return 0;
138: }
139:
140: STATIC_INLINE_ int writes_reg(int i, int r)
141: {
142: return access_reg(i,r,WRITE);
143: }
144:
145: STATIC_INLINE int reads_reg(int i, int r)
146: {
147: return access_reg(i,r,READ);
148: }
149:
150: STATIC_INLINE int uses_reg(int i, int r)
151: {
152: return access_reg(i,r,RMW);
153: }
154:
155:
156: STATIC_INLINE int writes_mem(int i) {
157: return linst[i].mem & WRITE;
158: }
159:
160: STATIC_INLINE int uses_mem(int i)
161: {
162: return linst[i].mem & RMW;
163: }
164:
165: STATIC_INLINE int reads_flags(int i) {
166: return linst[i].flags & READ;
167: }
168:
169: STATIC_INLINE int writes_flags(int i) {
170: return linst[i].flags & WRITE;
171: }
172:
173: STATIC_INLINE int uses_flags(int i)
174: {
175: return linst[i].flags & RMW;
176: }
177:
178: static void do_raw_mov_l_rm(W4,MEMR);
179: static void do_raw_fflags_save(void);
180:
181:
182: /* Whether i depends on j */
183: STATIC_INLINE int depends_on(int i, int j)
184: {
185: int n;
186:
187: /* First, check memory */
188: if (writes_mem(i) && uses_mem(j))
189: return 1;
190: if (reads_mem(i) && writes_mem(j))
191: return 1;
192:
193: /* Next, check flags */
194: if (writes_flags(i) && uses_flags(j))
195: return 1;
196: if (reads_flags(i) && writes_flags(j))
197: return 1;
198:
199: for (n=0;n<linst[i].nargs;n++) {
200: if (linst[i].argtype[n] & FLOAT)
201: return 1;
202: }
203: for (n=0;n<linst[j].nargs;n++) {
204: if (linst[j].argtype[n] & FLOAT)
205: return 1;
206: }
207:
208: for (n=0;n<linst[i].nargs;n++) {
209: if ((linst[i].argtype[n] & WRITE) &&
210: !(linst[i].argtype[n] & FLOAT)) {
211: if (uses_reg(j,linst[i].args[n]))
212: return 1;
213: }
214: else if ((linst[i].argtype[n] & READ) &&
215: !(linst[i].argtype[n] & FLOAT)) {
216: if (writes_reg(j,linst[i].args[n]))
217: return 1;
218: }
219: }
220:
221: /* The need for this indicates a problem somewhere in the
222: LOWFUNC definitions --- I think. FIXME! */
223:
224: if (uses_flags(j) && uses_flags(i))
225: return 1;
226: if (linst[i].func==do_raw_fflags_save)
227: return 1;
228: if (linst[j].func==do_raw_fflags_save)
229: return 1;
230:
231: return 0;
232: }
233:
234: static void do_raw_mov_l_rm(W4 d, MEMR s);
235:
236: STATIC_INLINE void low_peephole(void)
237: {
238: int i;
239:
240: for (i=0;i<lopt_index;i++) {
241: if (uses_mem(i)) {
242: int j=i-1;
243:
244: while (j>=i-4 && j>=0 && !depends_on(i,j)) {
245: j--;
246: }
247: if (j!=i-1) {
248: lopt_inst x=linst[i];
249: int k=i;
250:
251: j++;
252: while (k>j) {
253: linst[k]=linst[k-1];
254: k--;
255: }
256: linst[j]=x;
257: }
258: }
259: }
260: }
261:
262:
263: typedef void lopt_handler0(void);
264: typedef void lopt_handler1(uae_u32);
265: typedef void lopt_handler2(uae_u32,uae_u32);
266: typedef void lopt_handler3(uae_u32,uae_u32,uae_u32);
267: typedef void lopt_handler4(uae_u32,uae_u32,uae_u32,uae_u32);
268: typedef void lopt_handler5(uae_u32,uae_u32,uae_u32,uae_u32,uae_u32);
269:
270: static void lopt_emit_all(void)
271: {
272: int i;
273: lopt_inst* x;
274: static int inemit=0;
275:
276: if (inemit) {
277: printf("WARNING: lopt_emit is not reentrant!\n");
278: }
279: inemit=1;
280:
281: low_peephole();
282:
283: for (i=0;i<lopt_index;i++) {
284: x=linst+i;
285: switch(x->nargs) {
286: case 0: ((lopt_handler0*)x->func)(); break;
287: case 1: ((lopt_handler1*)x->func)(x->args[0]); break;
288: case 2: ((lopt_handler2*)x->func)(x->args[0],x->args[1]); break;
289: case 3: ((lopt_handler3*)x->func)(x->args[0],x->args[1],x->args[2]); break;
290: case 4: ((lopt_handler4*)x->func)(x->args[0],x->args[1],x->args[2],
291: x->args[3]); break;
292: case 5: ((lopt_handler5*)x->func)(x->args[0],x->args[1],x->args[2],
293: x->args[3],x->args[4]); break;
294: default: abort();
295: }
296: }
297: lopt_index=0;
298: inemit=0;
299: }
300:
301: STATIC_INLINE void low_advance(void)
302: {
303: lopt_index++;
304: if (lopt_index==MAXLOPTINST)
305: lopt_emit_all();
306: }
307:
308: STATIC_INLINE void lopt_store_op0(void* lfuncptr, uae_u32 lmem,
309: uae_u32 lflags)
310: {
311: linst[lopt_index].func=lfuncptr;
312: linst[lopt_index].mem=lmem;
313: linst[lopt_index].flags=lflags;
314: linst[lopt_index].nargs=0;
315: low_advance();
316: }
317:
318: STATIC_INLINE void lopt_store_op1(uae_u8 t1, uae_u32 a1,
319: void* lfuncptr, uae_u32 lmem,
320: uae_u32 lflags)
321: {
322: linst[lopt_index].func=lfuncptr;
323: linst[lopt_index].mem=lmem;
324: linst[lopt_index].flags=lflags;
325: linst[lopt_index].nargs=1;
326: linst[lopt_index].argtype[0]=t1;
327: linst[lopt_index].args[0]=a1;
328: low_advance();
329: }
330:
331: STATIC_INLINE void lopt_store_op2(uae_u8 t1, uae_u32 a1,
332: uae_u8 t2, uae_u32 a2,
333: void* lfuncptr, uae_u32 lmem,
334: uae_u32 lflags)
335: {
336: linst[lopt_index].func=lfuncptr;
337: linst[lopt_index].mem=lmem;
338: linst[lopt_index].flags=lflags;
339: linst[lopt_index].nargs=2;
340: linst[lopt_index].argtype[0]=t1;
341: linst[lopt_index].args[0]=a1;
342: linst[lopt_index].argtype[1]=t2;
343: linst[lopt_index].args[1]=a2;
344: low_advance();
345: }
346:
347: STATIC_INLINE void lopt_store_op3(uae_u8 t1, uae_u32 a1,
348: uae_u8 t2, uae_u32 a2,
349: uae_u8 t3, uae_u32 a3,
350: void* lfuncptr, uae_u32 lmem,
351: uae_u32 lflags)
352: {
353: linst[lopt_index].func=lfuncptr;
354: linst[lopt_index].mem=lmem;
355: linst[lopt_index].flags=lflags;
356: linst[lopt_index].nargs=3;
357: linst[lopt_index].argtype[0]=t1;
358: linst[lopt_index].args[0]=a1;
359: linst[lopt_index].argtype[1]=t2;
360: linst[lopt_index].args[1]=a2;
361: linst[lopt_index].argtype[2]=t3;
362: linst[lopt_index].args[2]=a3;
363: low_advance();
364: }
365:
366: STATIC_INLINE void lopt_store_op4(uae_u8 t1, uae_u32 a1,
367: uae_u8 t2, uae_u32 a2,
368: uae_u8 t3, uae_u32 a3,
369: uae_u8 t4, uae_u32 a4,
370: void* lfuncptr, uae_u32 lmem,
371: uae_u32 lflags)
372: {
373: linst[lopt_index].func=lfuncptr;
374: linst[lopt_index].mem=lmem;
375: linst[lopt_index].flags=lflags;
376: linst[lopt_index].nargs=4;
377: linst[lopt_index].argtype[0]=t1;
378: linst[lopt_index].args[0]=a1;
379: linst[lopt_index].argtype[1]=t2;
380: linst[lopt_index].args[1]=a2;
381: linst[lopt_index].argtype[2]=t3;
382: linst[lopt_index].args[2]=a3;
383: linst[lopt_index].argtype[3]=t4;
384: linst[lopt_index].args[3]=a4;
385: low_advance();
386: }
387:
388: STATIC_INLINE void lopt_store_op5(uae_u8 t1, uae_u32 a1,
389: uae_u8 t2, uae_u32 a2,
390: uae_u8 t3, uae_u32 a3,
391: uae_u8 t4, uae_u32 a4,
392: uae_u8 t5, uae_u32 a5,
393: void* lfuncptr, uae_u32 lmem,
394: uae_u32 lflags)
395: {
396: linst[lopt_index].func=lfuncptr;
397: linst[lopt_index].mem=lmem;
398: linst[lopt_index].flags=lflags;
399: linst[lopt_index].nargs=5;
400: linst[lopt_index].argtype[0]=t1;
401: linst[lopt_index].args[0]=a1;
402: linst[lopt_index].argtype[1]=t2;
403: linst[lopt_index].args[1]=a2;
404: linst[lopt_index].argtype[2]=t3;
405: linst[lopt_index].args[2]=a3;
406: linst[lopt_index].argtype[3]=t4;
407: linst[lopt_index].args[3]=a4;
408: linst[lopt_index].argtype[4]=t5;
409: linst[lopt_index].args[4]=a5;
410: low_advance();
411: }
412:
413: STATIC_INLINE void empty_low_optimizer(void)
414: {
415: lopt_emit_all();
416: }
417:
418: #else
419: #define lopt_emit_all()
420: #define empty_low_optimizer()
421: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.