|
|
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.