|
|
1.1 ! root 1: /* This should eventually end up in machdep/, but for now, x86 is the ! 2: only target, and it's easier this way... */ ! 3: ! 4: /************************************************************************* ! 5: * Some basic information about the the target CPU * ! 6: *************************************************************************/ ! 7: ! 8: #define EAX_INDEX 0 ! 9: #define ECX_INDEX 1 ! 10: #define EDX_INDEX 2 ! 11: #define EBX_INDEX 3 ! 12: #define ESP_INDEX 4 ! 13: #define EBP_INDEX 5 ! 14: #define ESI_INDEX 6 ! 15: #define EDI_INDEX 7 ! 16: #if defined(__x86_64__) ! 17: #define R8_INDEX 8 ! 18: #define R9_INDEX 9 ! 19: #define R10_INDEX 10 ! 20: #define R11_INDEX 11 ! 21: #define R12_INDEX 12 ! 22: #define R13_INDEX 13 ! 23: #define R14_INDEX 14 ! 24: #define R15_INDEX 15 ! 25: #endif ! 26: /* XXX this has to match X86_Reg8H_Base + 4 */ ! 27: #define AH_INDEX (0x10+4+EAX_INDEX) ! 28: #define CH_INDEX (0x10+4+ECX_INDEX) ! 29: #define DH_INDEX (0x10+4+EDX_INDEX) ! 30: #define BH_INDEX (0x10+4+EBX_INDEX) ! 31: ! 32: /* The register in which subroutines return an integer return value */ ! 33: #define REG_RESULT EAX_INDEX ! 34: ! 35: /* The registers subroutines take their first and second argument in */ ! 36: #if defined(_WIN32) ! 37: /* Handle the _fastcall parameters of ECX and EDX */ ! 38: #define REG_PAR1 ECX_INDEX ! 39: #define REG_PAR2 EDX_INDEX ! 40: #elif defined(__x86_64__) ! 41: #define REG_PAR1 EDI_INDEX ! 42: #define REG_PAR2 ESI_INDEX ! 43: #else ! 44: #define REG_PAR1 EAX_INDEX ! 45: #define REG_PAR2 EDX_INDEX ! 46: #endif ! 47: ! 48: #if defined(_WIN32) ! 49: #define REG_PC_PRE EAX_INDEX /* The register we use for preloading regs.pc_p */ ! 50: #define REG_PC_TMP ECX_INDEX ! 51: #define SHIFTCOUNT_NREG ECX_INDEX /* Register that can be used for shiftcount. -1 if any reg will do */ ! 52: #else ! 53: #define REG_PC_PRE EAX_INDEX /* The register we use for preloading regs.pc_p */ ! 54: #define REG_PC_TMP ECX_INDEX /* Another register that is not the above */ ! 55: #define SHIFTCOUNT_NREG ECX_INDEX /* Register that can be used for shiftcount. -1 if any reg will do */ ! 56: #endif ! 57: ! 58: #define MUL_NREG1 EAX_INDEX /* %eax will hold the low 32 bits after a 32x32 mul */ ! 59: #define MUL_NREG2 EDX_INDEX /* %edx will hold the high 32 bits */ ! 60: ! 61: #define STACK_ALIGN 16 ! 62: #define STACK_OFFSET sizeof(void *) ! 63: ! 64: uae_u8 always_used[]={4,0xff}; ! 65: #if defined(__x86_64__) ! 66: uae_s8 can_byte[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1}; ! 67: uae_s8 can_word[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1}; ! 68: #else ! 69: uae_u8 can_byte[]={0,1,2,3,0xff}; ! 70: uae_u8 can_word[]={0,1,2,3,5,6,7,0xff}; ! 71: #endif ! 72: ! 73: uae_u8 call_saved[]={0,0,0,0,1,0,0,0}; ! 74: ! 75: /* This *should* be the same as call_saved. But: ! 76: - We might not really know which registers are saved, and which aren't, ! 77: so we need to preserve some, but don't want to rely on everyone else ! 78: also saving those registers ! 79: - Special registers (such like the stack pointer) should not be "preserved" ! 80: by pushing, even though they are "saved" across function calls ! 81: */ ! 82: uae_u8 need_to_preserve[]={1,1,1,1,0,1,1,1}; ! 83: ! 84: /* Whether classes of instructions do or don't clobber the native flags */ ! 85: #define CLOBBER_MOV ! 86: #define CLOBBER_LEA ! 87: #define CLOBBER_CMOV ! 88: #define CLOBBER_POP ! 89: #define CLOBBER_PUSH ! 90: #define CLOBBER_SUB clobber_flags() ! 91: #define CLOBBER_SBB clobber_flags() ! 92: #define CLOBBER_CMP clobber_flags() ! 93: #define CLOBBER_ADD clobber_flags() ! 94: #define CLOBBER_ADC clobber_flags() ! 95: #define CLOBBER_AND clobber_flags() ! 96: #define CLOBBER_OR clobber_flags() ! 97: #define CLOBBER_XOR clobber_flags() ! 98: ! 99: #define CLOBBER_ROL clobber_flags() ! 100: #define CLOBBER_ROR clobber_flags() ! 101: #define CLOBBER_SHLL clobber_flags() ! 102: #define CLOBBER_SHRL clobber_flags() ! 103: #define CLOBBER_SHRA clobber_flags() ! 104: #define CLOBBER_TEST clobber_flags() ! 105: #define CLOBBER_CL16 ! 106: #define CLOBBER_CL8 ! 107: #define CLOBBER_SE16 ! 108: #define CLOBBER_SE8 ! 109: #define CLOBBER_ZE16 ! 110: #define CLOBBER_ZE8 ! 111: #define CLOBBER_SW16 clobber_flags() ! 112: #define CLOBBER_SW32 ! 113: #define CLOBBER_SETCC ! 114: #define CLOBBER_MUL clobber_flags() ! 115: #define CLOBBER_BT clobber_flags() ! 116: #define CLOBBER_BSF clobber_flags() ! 117: ! 118: /************************************************************************* ! 119: * Actual encoding of the instructions on the target CPU * ! 120: *************************************************************************/ ! 121: ! 122: //#include "compemu_optimizer_x86.c" ! 123: ! 124: STATIC_INLINE uae_u16 swap16(uae_u16 x) ! 125: { ! 126: return ((x&0xff00)>>8)|((x&0x00ff)<<8); ! 127: } ! 128: ! 129: STATIC_INLINE uae_u32 swap32(uae_u32 x) ! 130: { ! 131: return ((x&0xff00)<<8)|((x&0x00ff)<<24)|((x&0xff0000)>>8)|((x&0xff000000)>>24); ! 132: } ! 133: ! 134: STATIC_INLINE int isbyte(uae_s32 x) ! 135: { ! 136: return (x>=-128 && x<=127); ! 137: } ! 138: ! 139: LOWFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) ! 140: { ! 141: emit_byte(0x50+r); ! 142: } ! 143: LENDFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) ! 144: ! 145: LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) ! 146: { ! 147: emit_byte(0x58+r); ! 148: } ! 149: LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) ! 150: ! 151: LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) ! 152: { ! 153: emit_byte(0x0f); ! 154: emit_byte(0xba); ! 155: emit_byte(0xe0+r); ! 156: emit_byte(i); ! 157: } ! 158: LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) ! 159: ! 160: LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) ! 161: { ! 162: emit_byte(0x0f); ! 163: emit_byte(0xa3); ! 164: emit_byte(0xc0+8*b+r); ! 165: } ! 166: LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) ! 167: ! 168: LOWFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) ! 169: { ! 170: emit_byte(0x0f); ! 171: emit_byte(0xba); ! 172: emit_byte(0xf8+r); ! 173: emit_byte(i); ! 174: } ! 175: LENDFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) ! 176: ! 177: LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) ! 178: { ! 179: emit_byte(0x0f); ! 180: emit_byte(0xbb); ! 181: emit_byte(0xc0+8*b+r); ! 182: } ! 183: LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) ! 184: ! 185: ! 186: LOWFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) ! 187: { ! 188: emit_byte(0x0f); ! 189: emit_byte(0xba); ! 190: emit_byte(0xf0+r); ! 191: emit_byte(i); ! 192: } ! 193: LENDFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) ! 194: ! 195: LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) ! 196: { ! 197: emit_byte(0x0f); ! 198: emit_byte(0xb3); ! 199: emit_byte(0xc0+8*b+r); ! 200: } ! 201: LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) ! 202: ! 203: LOWFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) ! 204: { ! 205: emit_byte(0x0f); ! 206: emit_byte(0xba); ! 207: emit_byte(0xe8+r); ! 208: emit_byte(i); ! 209: } ! 210: LENDFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) ! 211: ! 212: LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) ! 213: { ! 214: emit_byte(0x0f); ! 215: emit_byte(0xab); ! 216: emit_byte(0xc0+8*b+r); ! 217: } ! 218: LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) ! 219: ! 220: LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) ! 221: { ! 222: emit_byte(0x66); ! 223: if (isbyte(i)) { ! 224: emit_byte(0x83); ! 225: emit_byte(0xe8+d); ! 226: emit_byte(i); ! 227: } ! 228: else { ! 229: emit_byte(0x81); ! 230: emit_byte(0xe8+d); ! 231: emit_word(i); ! 232: } ! 233: } ! 234: LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) ! 235: ! 236: ! 237: LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) ! 238: { ! 239: emit_byte(0xc7); ! 240: emit_byte(0x05); ! 241: emit_long(d); ! 242: emit_long(s); ! 243: } ! 244: LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) ! 245: ! 246: LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) ! 247: { ! 248: emit_byte(0x66); ! 249: emit_byte(0xc7); ! 250: emit_byte(0x05); ! 251: emit_long(d); ! 252: emit_word(s); ! 253: } ! 254: LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) ! 255: ! 256: LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) ! 257: { ! 258: emit_byte(0xc6); ! 259: emit_byte(0x05); ! 260: emit_long(d); ! 261: emit_byte(s); ! 262: } ! 263: LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) ! 264: ! 265: LOWFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) ! 266: { ! 267: emit_byte(0xc0); ! 268: emit_byte(0x05); ! 269: emit_long(d); ! 270: emit_byte(i); ! 271: } ! 272: LENDFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) ! 273: ! 274: LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) ! 275: { ! 276: emit_byte(0xc0); ! 277: emit_byte(0xc0+r); ! 278: emit_byte(i); ! 279: } ! 280: LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) ! 281: ! 282: LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) ! 283: { ! 284: emit_byte(0x66); ! 285: emit_byte(0xc1); ! 286: emit_byte(0xc0+r); ! 287: emit_byte(i); ! 288: } ! 289: LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) ! 290: ! 291: LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) ! 292: { ! 293: emit_byte(0xc1); ! 294: emit_byte(0xc0+r); ! 295: emit_byte(i); ! 296: } ! 297: LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) ! 298: ! 299: LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) ! 300: { ! 301: emit_byte(0xd3); ! 302: emit_byte(0xc0+d); ! 303: } ! 304: LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) ! 305: ! 306: LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) ! 307: { ! 308: emit_byte(0x66); ! 309: emit_byte(0xd3); ! 310: emit_byte(0xc0+d); ! 311: } ! 312: LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) ! 313: ! 314: LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) ! 315: { ! 316: emit_byte(0xd2); ! 317: emit_byte(0xc0+d); ! 318: } ! 319: LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) ! 320: ! 321: LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) ! 322: { ! 323: emit_byte(0xd3); ! 324: emit_byte(0xe0+d); ! 325: } ! 326: LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) ! 327: ! 328: LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) ! 329: { ! 330: emit_byte(0x66); ! 331: emit_byte(0xd3); ! 332: emit_byte(0xe0+d); ! 333: } ! 334: LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) ! 335: ! 336: LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) ! 337: { ! 338: emit_byte(0xd2); ! 339: emit_byte(0xe0+d); ! 340: } ! 341: LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) ! 342: ! 343: LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) ! 344: { ! 345: emit_byte(0xc0); ! 346: emit_byte(0xc8+r); ! 347: emit_byte(i); ! 348: } ! 349: LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) ! 350: ! 351: LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) ! 352: { ! 353: emit_byte(0x66); ! 354: emit_byte(0xc1); ! 355: emit_byte(0xc8+r); ! 356: emit_byte(i); ! 357: } ! 358: LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) ! 359: ! 360: LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) ! 361: { ! 362: emit_byte(0xc1); ! 363: emit_byte(0xc8+r); ! 364: emit_byte(i); ! 365: } ! 366: LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) ! 367: ! 368: LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) ! 369: { ! 370: emit_byte(0xd3); ! 371: emit_byte(0xc8+d); ! 372: } ! 373: LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) ! 374: ! 375: LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) ! 376: { ! 377: emit_byte(0x66); ! 378: emit_byte(0xd3); ! 379: emit_byte(0xc8+d); ! 380: } ! 381: LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) ! 382: ! 383: LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) ! 384: { ! 385: emit_byte(0xd2); ! 386: emit_byte(0xc8+d); ! 387: } ! 388: LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) ! 389: ! 390: LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) ! 391: { ! 392: emit_byte(0xd3); ! 393: emit_byte(0xe8+d); ! 394: } ! 395: LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) ! 396: ! 397: LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) ! 398: { ! 399: emit_byte(0x66); ! 400: emit_byte(0xd3); ! 401: emit_byte(0xe8+d); ! 402: } ! 403: LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) ! 404: ! 405: LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) ! 406: { ! 407: emit_byte(0xd2); ! 408: emit_byte(0xe8+d); ! 409: } ! 410: LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) ! 411: ! 412: LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) ! 413: { ! 414: emit_byte(0xd3); ! 415: emit_byte(0xf8+d); ! 416: } ! 417: LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) ! 418: ! 419: LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) ! 420: { ! 421: emit_byte(0x66); ! 422: emit_byte(0xd3); ! 423: emit_byte(0xf8+d); ! 424: } ! 425: LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) ! 426: ! 427: LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) ! 428: { ! 429: emit_byte(0xd2); ! 430: emit_byte(0xf8+d); ! 431: } ! 432: LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) ! 433: ! 434: LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) ! 435: { ! 436: emit_byte(0xc1); ! 437: emit_byte(0xe0+r); ! 438: emit_byte(i); ! 439: } ! 440: LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) ! 441: ! 442: LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) ! 443: { ! 444: emit_byte(0x66); ! 445: emit_byte(0xc1); ! 446: emit_byte(0xe0+r); ! 447: emit_byte(i); ! 448: } ! 449: LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) ! 450: ! 451: LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) ! 452: { ! 453: emit_byte(0xc0); ! 454: emit_byte(0xe0+r); ! 455: emit_byte(i); ! 456: } ! 457: LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) ! 458: ! 459: LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) ! 460: { ! 461: emit_byte(0xc1); ! 462: emit_byte(0xe8+r); ! 463: emit_byte(i); ! 464: } ! 465: LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) ! 466: ! 467: LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) ! 468: { ! 469: emit_byte(0x66); ! 470: emit_byte(0xc1); ! 471: emit_byte(0xe8+r); ! 472: emit_byte(i); ! 473: } ! 474: LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) ! 475: ! 476: LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) ! 477: { ! 478: emit_byte(0xc0); ! 479: emit_byte(0xe8+r); ! 480: emit_byte(i); ! 481: } ! 482: LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) ! 483: ! 484: LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) ! 485: { ! 486: emit_byte(0xc1); ! 487: emit_byte(0xf8+r); ! 488: emit_byte(i); ! 489: } ! 490: LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) ! 491: ! 492: LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) ! 493: { ! 494: emit_byte(0x66); ! 495: emit_byte(0xc1); ! 496: emit_byte(0xf8+r); ! 497: emit_byte(i); ! 498: } ! 499: LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) ! 500: ! 501: LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) ! 502: { ! 503: emit_byte(0xc0); ! 504: emit_byte(0xf8+r); ! 505: emit_byte(i); ! 506: } ! 507: LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) ! 508: ! 509: LOWFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) ! 510: { ! 511: emit_byte(0x9e); ! 512: } ! 513: LENDFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) ! 514: ! 515: LOWFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) ! 516: { ! 517: emit_byte(0x0f); ! 518: emit_byte(0xa2); ! 519: } ! 520: LENDFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) ! 521: ! 522: LOWFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) ! 523: { ! 524: emit_byte(0x9f); ! 525: } ! 526: LENDFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) ! 527: ! 528: LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) ! 529: { ! 530: emit_byte(0x0f); ! 531: emit_byte(0x90+cc); ! 532: emit_byte(0xc0+d); ! 533: } ! 534: LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) ! 535: ! 536: LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) ! 537: { ! 538: emit_byte(0x0f); ! 539: emit_byte(0x90+cc); ! 540: emit_byte(0x05); ! 541: emit_long(d); ! 542: } ! 543: LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) ! 544: ! 545: LOWFUNC(READ,NONE,3,raw_cmov_b_rr,(RW1 d, R1 s, IMM cc)) ! 546: { ! 547: /* replacement using branch and mov */ ! 548: int uncc=(cc^1); ! 549: emit_byte(0x70+uncc); ! 550: emit_byte(3); /* skip next 2 bytes if not cc=true */ ! 551: emit_byte(0x88); ! 552: emit_byte(0xc0+8*s+d); ! 553: } ! 554: LENDFUNC(READ,NONE,3,raw_cmov_b_rr,(RW1 d, R1 s, IMM cc)) ! 555: ! 556: LOWFUNC(READ,NONE,3,raw_cmov_w_rr,(RW2 d, R2 s, IMM cc)) ! 557: { ! 558: if (have_cmov) { ! 559: emit_byte(0x66); ! 560: emit_byte(0x0f); ! 561: emit_byte(0x40+cc); ! 562: emit_byte(0xc0+8*d+s); ! 563: } ! 564: else { /* replacement using branch and mov */ ! 565: int uncc=(cc^1); ! 566: emit_byte(0x70+uncc); ! 567: emit_byte(3); /* skip next 3 bytes if not cc=true */ ! 568: emit_byte(0x66); ! 569: emit_byte(0x89); ! 570: emit_byte(0xc0+8*s+d); ! 571: } ! 572: } ! 573: LENDFUNC(READ,NONE,3,raw_cmov_w_rr,(RW2 d, R2 s, IMM cc)) ! 574: ! 575: LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) ! 576: { ! 577: if (have_cmov) { ! 578: emit_byte(0x0f); ! 579: emit_byte(0x40+cc); ! 580: emit_byte(0xc0+8*d+s); ! 581: } ! 582: else { /* replacement using branch and mov */ ! 583: int uncc=(cc^1); ! 584: emit_byte(0x70+uncc); ! 585: emit_byte(2); /* skip next 2 bytes if not cc=true */ ! 586: emit_byte(0x89); ! 587: emit_byte(0xc0+8*s+d); ! 588: } ! 589: } ! 590: LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) ! 591: ! 592: LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) ! 593: { ! 594: emit_byte(0x0f); ! 595: emit_byte(0xbc); ! 596: emit_byte(0xc0+8*d+s); ! 597: } ! 598: LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) ! 599: ! 600: LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) ! 601: { ! 602: emit_byte(0x0f); ! 603: emit_byte(0xbf); ! 604: emit_byte(0xc0+8*d+s); ! 605: } ! 606: LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) ! 607: ! 608: LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) ! 609: { ! 610: emit_byte(0x0f); ! 611: emit_byte(0xbe); ! 612: emit_byte(0xc0+8*d+s); ! 613: } ! 614: LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) ! 615: ! 616: LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) ! 617: { ! 618: emit_byte(0x0f); ! 619: emit_byte(0xb7); ! 620: emit_byte(0xc0+8*d+s); ! 621: } ! 622: LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) ! 623: ! 624: LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) ! 625: { ! 626: emit_byte(0x0f); ! 627: emit_byte(0xb6); ! 628: emit_byte(0xc0+8*d+s); ! 629: } ! 630: LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) ! 631: ! 632: LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) ! 633: { ! 634: emit_byte(0x0f); ! 635: emit_byte(0xaf); ! 636: emit_byte(0xc0+8*d+s); ! 637: } ! 638: LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) ! 639: ! 640: LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) ! 641: { ! 642: #ifdef JIT_DEBUG ! 643: if (d!=MUL_NREG1 || s!=MUL_NREG2) { ! 644: write_log (L"JIT: Bad register in IMUL: d=%d, s=%d\n",d,s); ! 645: abort(); ! 646: } ! 647: #endif ! 648: emit_byte(0xf7); ! 649: emit_byte(0xea); ! 650: } ! 651: LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) ! 652: ! 653: LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) ! 654: { ! 655: #ifdef JIT_DEBUG ! 656: if (d!=MUL_NREG1 || s!=MUL_NREG2) { ! 657: write_log (L"JIT: Bad register in MUL: d=%d, s=%d\n",d,s); ! 658: abort(); ! 659: } ! 660: #endif ! 661: emit_byte(0xf7); ! 662: emit_byte(0xe2); ! 663: } ! 664: LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) ! 665: ! 666: LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) ! 667: { ! 668: emit_byte(0x88); ! 669: emit_byte(0xc0+8*s+d); ! 670: } ! 671: LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) ! 672: ! 673: LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) ! 674: { ! 675: emit_byte(0x66); ! 676: emit_byte(0x89); ! 677: emit_byte(0xc0+8*s+d); ! 678: } ! 679: LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) ! 680: ! 681: LOWFUNC(NONE,READ,3,raw_mov_l_rrm_indexed,(W4 d, R4 baser, R4 index)) ! 682: { ! 683: emit_byte(0x8b); ! 684: if (baser==5) { ! 685: emit_byte(0x44+8*d); ! 686: emit_byte(8*index+baser); ! 687: emit_byte(0); ! 688: return; ! 689: } ! 690: emit_byte(0x04+8*d); ! 691: emit_byte(8*index+baser); ! 692: } ! 693: LENDFUNC(NONE,READ,3,raw_mov_l_rrm_indexed,(W4 d, R4 baser, R4 index)) ! 694: ! 695: LOWFUNC(NONE,READ,3,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index)) ! 696: { ! 697: emit_byte(0x66); ! 698: emit_byte(0x8b); ! 699: if (baser==5) { ! 700: emit_byte(0x44+8*d); ! 701: emit_byte(8*index+baser); ! 702: emit_byte(0); ! 703: return; ! 704: } ! 705: emit_byte(0x04+8*d); ! 706: emit_byte(8*index+baser); ! 707: } ! 708: LENDFUNC(NONE,READ,3,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index)) ! 709: ! 710: LOWFUNC(NONE,READ,3,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index)) ! 711: { ! 712: emit_byte(0x8a); ! 713: if (baser==5) { ! 714: emit_byte(0x44+8*d); ! 715: emit_byte(8*index+baser); ! 716: emit_byte(0); ! 717: return; ! 718: } ! 719: emit_byte(0x04+8*d); ! 720: emit_byte(8*index+baser); ! 721: } ! 722: LENDFUNC(NONE,READ,3,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index)) ! 723: ! 724: LOWFUNC(NONE,WRITE,3,raw_mov_l_mrr_indexed,(R4 baser, R4 index, R4 s)) ! 725: { ! 726: emit_byte(0x89); ! 727: if (baser==5) { ! 728: emit_byte(0x44+8*s); ! 729: emit_byte(8*index+baser); ! 730: emit_byte(0); ! 731: return; ! 732: } ! 733: emit_byte(0x04+8*s); ! 734: emit_byte(8*index+baser); ! 735: } ! 736: LENDFUNC(NONE,WRITE,3,raw_mov_l_mrr_indexed,(R4 baser, R4 index, R4 s)) ! 737: ! 738: LOWFUNC(NONE,WRITE,3,raw_mov_w_mrr_indexed,(R4 baser, R4 index, R2 s)) ! 739: { ! 740: emit_byte(0x66); ! 741: emit_byte(0x89); ! 742: if (baser==5) { ! 743: emit_byte(0x44+8*s); ! 744: emit_byte(8*index+baser); ! 745: emit_byte(0); ! 746: return; ! 747: } ! 748: emit_byte(0x04+8*s); ! 749: emit_byte(8*index+baser); ! 750: } ! 751: LENDFUNC(NONE,WRITE,3,raw_mov_w_mrr_indexed,(R4 baser, R4 index, R2 s)) ! 752: ! 753: LOWFUNC(NONE,WRITE,3,raw_mov_b_mrr_indexed,(R4 baser, R4 index, R1 s)) ! 754: { ! 755: emit_byte(0x88); ! 756: if (baser==5) { ! 757: emit_byte(0x44+8*s); ! 758: emit_byte(8*index+baser); ! 759: emit_byte(0); ! 760: return; ! 761: } ! 762: emit_byte(0x04+8*s); ! 763: emit_byte(8*index+baser); ! 764: } ! 765: LENDFUNC(NONE,WRITE,3,raw_mov_b_mrr_indexed,(R4 baser, R4 index, R1 s)) ! 766: ! 767: LOWFUNC(NONE,READ,3,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index)) ! 768: { ! 769: emit_byte(0x8b); ! 770: emit_byte(0x04+8*d); ! 771: emit_byte(0x85+8*index); ! 772: emit_long(base); ! 773: } ! 774: LENDFUNC(NONE,READ,3,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index)) ! 775: ! 776: LOWFUNC(NONE,READ,4,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM cond)) ! 777: { ! 778: if (have_cmov) { ! 779: emit_byte(0x0f); ! 780: emit_byte(0x40+cond); ! 781: } ! 782: else { /* replacement using branch and mov */ ! 783: int uncc=(cond^1); ! 784: emit_byte(0x70+uncc); ! 785: emit_byte(7); /* skip next 7 bytes if not cc=true */ ! 786: emit_byte(0x8b); ! 787: } ! 788: emit_byte(0x04+8*d); ! 789: emit_byte(0x85+8*index); ! 790: emit_long(base); ! 791: } ! 792: LENDFUNC(NONE,READ,4,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM cond)) ! 793: ! 794: LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) ! 795: { ! 796: if (have_cmov) { ! 797: emit_byte(0x0f); ! 798: emit_byte(0x40+cond); ! 799: emit_byte(0x05+8*d); ! 800: emit_long(mem); ! 801: } ! 802: else { /* replacement using branch and mov */ ! 803: int uncc=(cond^1); ! 804: emit_byte(0x70+uncc); ! 805: emit_byte(6); /* skip next 6 bytes if not cc=true */ ! 806: emit_byte(0x8b); ! 807: emit_byte(0x05+8*d); ! 808: emit_long(mem); ! 809: } ! 810: } ! 811: LENDFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) ! 812: ! 813: LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) ! 814: { ! 815: emit_byte(0x8b); ! 816: emit_byte(0x40+8*d+s); ! 817: emit_byte(offset); ! 818: } ! 819: LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) ! 820: ! 821: LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) ! 822: { ! 823: emit_byte(0x66); ! 824: emit_byte(0x8b); ! 825: emit_byte(0x40+8*d+s); ! 826: emit_byte(offset); ! 827: } ! 828: LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) ! 829: ! 830: LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) ! 831: { ! 832: emit_byte(0x8a); ! 833: emit_byte(0x40+8*d+s); ! 834: emit_byte(offset); ! 835: } ! 836: LENDFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) ! 837: ! 838: LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) ! 839: { ! 840: emit_byte(0x8b); ! 841: emit_byte(0x80+8*d+s); ! 842: emit_long(offset); ! 843: } ! 844: LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) ! 845: ! 846: LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) ! 847: { ! 848: emit_byte(0x66); ! 849: emit_byte(0x8b); ! 850: emit_byte(0x80+8*d+s); ! 851: emit_long(offset); ! 852: } ! 853: LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) ! 854: ! 855: LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) ! 856: { ! 857: emit_byte(0x8a); ! 858: emit_byte(0x80+8*d+s); ! 859: emit_long(offset); ! 860: } ! 861: LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) ! 862: ! 863: LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) ! 864: { ! 865: emit_byte(0xc7); ! 866: emit_byte(0x40+d); ! 867: emit_byte(offset); ! 868: emit_long(i); ! 869: } ! 870: LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) ! 871: ! 872: LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) ! 873: { ! 874: emit_byte(0x66); ! 875: emit_byte(0xc7); ! 876: emit_byte(0x40+d); ! 877: emit_byte(offset); ! 878: emit_word(i); ! 879: } ! 880: LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) ! 881: ! 882: LOWFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) ! 883: { ! 884: emit_byte(0xc6); ! 885: emit_byte(0x40+d); ! 886: emit_byte(offset); ! 887: emit_byte(i); ! 888: } ! 889: LENDFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) ! 890: ! 891: LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) ! 892: { ! 893: emit_byte(0x89); ! 894: emit_byte(0x40+8*s+d); ! 895: emit_byte(offset); ! 896: } ! 897: LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) ! 898: ! 899: LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) ! 900: { ! 901: emit_byte(0x66); ! 902: emit_byte(0x89); ! 903: emit_byte(0x40+8*s+d); ! 904: emit_byte(offset); ! 905: } ! 906: LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) ! 907: ! 908: LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) ! 909: { ! 910: emit_byte(0x88); ! 911: emit_byte(0x40+8*s+d); ! 912: emit_byte(offset); ! 913: } ! 914: LENDFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) ! 915: ! 916: LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) ! 917: { ! 918: emit_byte(0x8d); ! 919: emit_byte(0x80+8*d+s); ! 920: emit_long(offset); ! 921: } ! 922: LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) ! 923: ! 924: LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) ! 925: { ! 926: emit_byte(0x8d); ! 927: if (!offset) { ! 928: if (s!=5) { ! 929: emit_byte(0x04+8*d); ! 930: emit_byte(0x40*factor+8*index+s); ! 931: return; ! 932: } ! 933: emit_byte(0x44+8*d); ! 934: emit_byte(0x40*factor+8*index+s); ! 935: emit_byte(0); ! 936: return; ! 937: } ! 938: emit_byte(0x84+8*d); ! 939: emit_byte(0x40*factor+8*index+s); ! 940: emit_long(offset); ! 941: } ! 942: LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) ! 943: ! 944: LOWFUNC(NONE,NONE,3,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index)) ! 945: { ! 946: emit_byte(0x8d); ! 947: if (s==5) { ! 948: emit_byte(0x44+8*d); ! 949: emit_byte(8*index+s); ! 950: emit_byte(0); ! 951: return; ! 952: } ! 953: emit_byte(0x04+8*d); ! 954: emit_byte(8*index+s); ! 955: } ! 956: LENDFUNC(NONE,NONE,3,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index)) ! 957: ! 958: LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) ! 959: { ! 960: emit_byte(0x89); ! 961: emit_byte(0x80+8*s+d); ! 962: emit_long(offset); ! 963: } ! 964: LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) ! 965: ! 966: LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) ! 967: { ! 968: emit_byte(0x66); ! 969: emit_byte(0x89); ! 970: emit_byte(0x80+8*s+d); ! 971: emit_long(offset); ! 972: } ! 973: LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) ! 974: ! 975: LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) ! 976: { ! 977: emit_byte(0x88); ! 978: emit_byte(0x80+8*s+d); ! 979: emit_long(offset); ! 980: } ! 981: LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) ! 982: ! 983: LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) ! 984: { ! 985: emit_byte(0x0f); ! 986: emit_byte(0xc8+r); ! 987: } ! 988: LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) ! 989: ! 990: LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) ! 991: { ! 992: emit_byte(0x66); ! 993: emit_byte(0xc1); ! 994: emit_byte(0xc0+r); ! 995: emit_byte(0x08); ! 996: } ! 997: LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) ! 998: ! 999: LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) ! 1000: { ! 1001: emit_byte(0x89); ! 1002: emit_byte(0xc0+8*s+d); ! 1003: } ! 1004: LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) ! 1005: ! 1006: LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) ! 1007: { ! 1008: emit_byte(0x89); ! 1009: emit_byte(0x05+8*s); ! 1010: emit_long(d); ! 1011: } ! 1012: LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) ! 1013: ! 1014: LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) ! 1015: { ! 1016: emit_byte(0x8b); ! 1017: emit_byte(0x05+8*d); ! 1018: emit_long(s); ! 1019: } ! 1020: LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) ! 1021: ! 1022: LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) ! 1023: { ! 1024: emit_byte(0x66); ! 1025: emit_byte(0x89); ! 1026: emit_byte(0x05+8*s); ! 1027: emit_long(d); ! 1028: } ! 1029: LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) ! 1030: ! 1031: LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) ! 1032: { ! 1033: emit_byte(0x66); ! 1034: emit_byte(0x8b); ! 1035: emit_byte(0x05+8*d); ! 1036: emit_long(s); ! 1037: } ! 1038: LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) ! 1039: ! 1040: LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) ! 1041: { ! 1042: emit_byte(0x88); ! 1043: emit_byte(0x05+8*s); ! 1044: emit_long(d); ! 1045: } ! 1046: LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) ! 1047: ! 1048: LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) ! 1049: { ! 1050: emit_byte(0x8a); ! 1051: emit_byte(0x05+8*d); ! 1052: emit_long(s); ! 1053: } ! 1054: LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) ! 1055: ! 1056: LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) ! 1057: { ! 1058: emit_byte(0xb8+d); ! 1059: emit_long(s); ! 1060: } ! 1061: LENDFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) ! 1062: ! 1063: LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) ! 1064: { ! 1065: emit_byte(0x66); ! 1066: emit_byte(0xb8+d); ! 1067: emit_word(s); ! 1068: } ! 1069: LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) ! 1070: ! 1071: LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) ! 1072: { ! 1073: emit_byte(0xb0+d); ! 1074: emit_byte(s); ! 1075: } ! 1076: LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) ! 1077: ! 1078: LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) ! 1079: { ! 1080: emit_byte(0x81); ! 1081: emit_byte(0x15); ! 1082: emit_long(d); ! 1083: emit_long(s); ! 1084: } ! 1085: LENDFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) ! 1086: ! 1087: LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) ! 1088: { ! 1089: emit_byte(0x81); ! 1090: emit_byte(0x05); ! 1091: emit_long(d); ! 1092: emit_long(s); ! 1093: } ! 1094: LENDFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) ! 1095: ! 1096: LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) ! 1097: { ! 1098: emit_byte(0x66); ! 1099: emit_byte(0x81); ! 1100: emit_byte(0x05); ! 1101: emit_long(d); ! 1102: emit_word(s); ! 1103: } ! 1104: LENDFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) ! 1105: ! 1106: LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) ! 1107: { ! 1108: emit_byte(0x80); ! 1109: emit_byte(0x05); ! 1110: emit_long(d); ! 1111: emit_byte(s); ! 1112: } ! 1113: LENDFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) ! 1114: ! 1115: LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) ! 1116: { ! 1117: emit_byte(0xf7); ! 1118: emit_byte(0xc0+d); ! 1119: emit_long(i); ! 1120: } ! 1121: LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) ! 1122: ! 1123: LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) ! 1124: { ! 1125: emit_byte(0x85); ! 1126: emit_byte(0xc0+8*s+d); ! 1127: } ! 1128: LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) ! 1129: ! 1130: LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) ! 1131: { ! 1132: emit_byte(0x66); ! 1133: emit_byte(0x85); ! 1134: emit_byte(0xc0+8*s+d); ! 1135: } ! 1136: LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) ! 1137: ! 1138: LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) ! 1139: { ! 1140: emit_byte(0x84); ! 1141: emit_byte(0xc0+8*s+d); ! 1142: } ! 1143: LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) ! 1144: ! 1145: LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) ! 1146: { ! 1147: emit_byte(0x81); ! 1148: emit_byte(0xe0+d); ! 1149: emit_long(i); ! 1150: } ! 1151: LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) ! 1152: ! 1153: LOWFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) ! 1154: { ! 1155: emit_byte(0x66); ! 1156: emit_byte(0x81); ! 1157: emit_byte(0xe0+d); ! 1158: emit_word(i); ! 1159: } ! 1160: LENDFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) ! 1161: ! 1162: LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) ! 1163: { ! 1164: emit_byte(0x21); ! 1165: emit_byte(0xc0+8*s+d); ! 1166: } ! 1167: LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) ! 1168: ! 1169: LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) ! 1170: { ! 1171: emit_byte(0x66); ! 1172: emit_byte(0x21); ! 1173: emit_byte(0xc0+8*s+d); ! 1174: } ! 1175: LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) ! 1176: ! 1177: LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) ! 1178: { ! 1179: emit_byte(0x20); ! 1180: emit_byte(0xc0+8*s+d); ! 1181: } ! 1182: LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) ! 1183: ! 1184: LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) ! 1185: { ! 1186: emit_byte(0x81); ! 1187: emit_byte(0xc8+d); ! 1188: emit_long(i); ! 1189: } ! 1190: LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) ! 1191: ! 1192: LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) ! 1193: { ! 1194: emit_byte(0x09); ! 1195: emit_byte(0xc0+8*s+d); ! 1196: } ! 1197: LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) ! 1198: ! 1199: LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) ! 1200: { ! 1201: emit_byte(0x66); ! 1202: emit_byte(0x09); ! 1203: emit_byte(0xc0+8*s+d); ! 1204: } ! 1205: LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) ! 1206: ! 1207: LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) ! 1208: { ! 1209: emit_byte(0x08); ! 1210: emit_byte(0xc0+8*s+d); ! 1211: } ! 1212: LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) ! 1213: ! 1214: LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) ! 1215: { ! 1216: emit_byte(0x11); ! 1217: emit_byte(0xc0+8*s+d); ! 1218: } ! 1219: LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) ! 1220: ! 1221: LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) ! 1222: { ! 1223: emit_byte(0x66); ! 1224: emit_byte(0x11); ! 1225: emit_byte(0xc0+8*s+d); ! 1226: } ! 1227: LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) ! 1228: ! 1229: LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) ! 1230: { ! 1231: emit_byte(0x10); ! 1232: emit_byte(0xc0+8*s+d); ! 1233: } ! 1234: LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) ! 1235: ! 1236: LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) ! 1237: { ! 1238: emit_byte(0x01); ! 1239: emit_byte(0xc0+8*s+d); ! 1240: } ! 1241: LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) ! 1242: ! 1243: LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) ! 1244: { ! 1245: emit_byte(0x66); ! 1246: emit_byte(0x01); ! 1247: emit_byte(0xc0+8*s+d); ! 1248: } ! 1249: LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) ! 1250: ! 1251: LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) ! 1252: { ! 1253: emit_byte(0x00); ! 1254: emit_byte(0xc0+8*s+d); ! 1255: } ! 1256: LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) ! 1257: ! 1258: LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) ! 1259: { ! 1260: if (isbyte(i)) { ! 1261: emit_byte(0x83); ! 1262: emit_byte(0xe8+d); ! 1263: emit_byte(i); ! 1264: } ! 1265: else { ! 1266: emit_byte(0x81); ! 1267: emit_byte(0xe8+d); ! 1268: emit_long(i); ! 1269: } ! 1270: } ! 1271: LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) ! 1272: ! 1273: LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) ! 1274: { ! 1275: emit_byte(0x80); ! 1276: emit_byte(0xe8+d); ! 1277: emit_byte(i); ! 1278: } ! 1279: LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) ! 1280: ! 1281: LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) ! 1282: { ! 1283: if (isbyte(i)) { ! 1284: emit_byte(0x83); ! 1285: emit_byte(0xc0+d); ! 1286: emit_byte(i); ! 1287: } ! 1288: else { ! 1289: emit_byte(0x81); ! 1290: emit_byte(0xc0+d); ! 1291: emit_long(i); ! 1292: } ! 1293: } ! 1294: LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) ! 1295: ! 1296: LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) ! 1297: { ! 1298: if (isbyte(i)) { ! 1299: emit_byte(0x66); ! 1300: emit_byte(0x83); ! 1301: emit_byte(0xc0+d); ! 1302: emit_byte(i); ! 1303: } ! 1304: else { ! 1305: emit_byte(0x66); ! 1306: emit_byte(0x81); ! 1307: emit_byte(0xc0+d); ! 1308: emit_word(i); ! 1309: } ! 1310: } ! 1311: LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) ! 1312: ! 1313: LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) ! 1314: { ! 1315: emit_byte(0x80); ! 1316: emit_byte(0xc0+d); ! 1317: emit_byte(i); ! 1318: } ! 1319: LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) ! 1320: ! 1321: LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) ! 1322: { ! 1323: emit_byte(0x19); ! 1324: emit_byte(0xc0+8*s+d); ! 1325: } ! 1326: LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) ! 1327: ! 1328: LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) ! 1329: { ! 1330: emit_byte(0x66); ! 1331: emit_byte(0x19); ! 1332: emit_byte(0xc0+8*s+d); ! 1333: } ! 1334: LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) ! 1335: ! 1336: LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) ! 1337: { ! 1338: emit_byte(0x18); ! 1339: emit_byte(0xc0+8*s+d); ! 1340: } ! 1341: LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) ! 1342: ! 1343: LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) ! 1344: { ! 1345: emit_byte(0x29); ! 1346: emit_byte(0xc0+8*s+d); ! 1347: } ! 1348: LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) ! 1349: ! 1350: LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) ! 1351: { ! 1352: emit_byte(0x66); ! 1353: emit_byte(0x29); ! 1354: emit_byte(0xc0+8*s+d); ! 1355: } ! 1356: LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) ! 1357: ! 1358: LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) ! 1359: { ! 1360: emit_byte(0x28); ! 1361: emit_byte(0xc0+8*s+d); ! 1362: } ! 1363: LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) ! 1364: ! 1365: LOWFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) ! 1366: { ! 1367: emit_byte(0x39); ! 1368: emit_byte(0xc0+8*s+d); ! 1369: } ! 1370: LENDFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) ! 1371: ! 1372: LOWFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) ! 1373: { ! 1374: emit_byte(0x81); ! 1375: emit_byte(0xf8+r); ! 1376: emit_long(i); ! 1377: } ! 1378: LENDFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) ! 1379: ! 1380: LOWFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) ! 1381: { ! 1382: emit_byte(0x66); ! 1383: emit_byte(0x39); ! 1384: emit_byte(0xc0+8*s+d); ! 1385: } ! 1386: LENDFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) ! 1387: ! 1388: LOWFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) ! 1389: { ! 1390: emit_byte(0x80); ! 1391: emit_byte(0xf8+d); ! 1392: emit_byte(i); ! 1393: } ! 1394: LENDFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) ! 1395: ! 1396: LOWFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) ! 1397: { ! 1398: emit_byte(0x38); ! 1399: emit_byte(0xc0+8*s+d); ! 1400: } ! 1401: LENDFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) ! 1402: ! 1403: LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) ! 1404: { ! 1405: emit_byte(0x31); ! 1406: emit_byte(0xc0+8*s+d); ! 1407: } ! 1408: LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) ! 1409: ! 1410: LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) ! 1411: { ! 1412: emit_byte(0x66); ! 1413: emit_byte(0x31); ! 1414: emit_byte(0xc0+8*s+d); ! 1415: } ! 1416: LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) ! 1417: ! 1418: LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) ! 1419: { ! 1420: emit_byte(0x30); ! 1421: emit_byte(0xc0+8*s+d); ! 1422: } ! 1423: LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) ! 1424: ! 1425: LOWFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) ! 1426: { ! 1427: emit_byte(0x81); ! 1428: emit_byte(0x2d); ! 1429: emit_long(d); ! 1430: emit_long(s); ! 1431: } ! 1432: LENDFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) ! 1433: ! 1434: LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) ! 1435: { ! 1436: emit_byte(0x81); ! 1437: emit_byte(0x3d); ! 1438: emit_long(d); ! 1439: emit_long(s); ! 1440: } ! 1441: LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) ! 1442: ! 1443: LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) ! 1444: { ! 1445: emit_byte(0x87); ! 1446: emit_byte(0xc0+8*r1+r2); ! 1447: } ! 1448: LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) ! 1449: ! 1450: LOWFUNC(READ,WRITE,0,raw_pushfl,(void)) ! 1451: { ! 1452: emit_byte(0x9c); ! 1453: } ! 1454: LENDFUNC(READ,WRITE,0,raw_pushfl,(void)) ! 1455: ! 1456: LOWFUNC(WRITE,READ,0,raw_popfl,(void)) ! 1457: { ! 1458: emit_byte(0x9d); ! 1459: } ! 1460: LENDFUNC(WRITE,READ,0,raw_popfl,(void)) ! 1461: ! 1462: /************************************************************************* ! 1463: * Unoptimizable stuff --- jump * ! 1464: *************************************************************************/ ! 1465: ! 1466: STATIC_INLINE void raw_call_r(R4 r) ! 1467: { ! 1468: lopt_emit_all(); ! 1469: emit_byte(0xff); ! 1470: emit_byte(0xd0+r); ! 1471: } ! 1472: ! 1473: STATIC_INLINE void raw_jmp_r(R4 r) ! 1474: { ! 1475: lopt_emit_all(); ! 1476: emit_byte(0xff); ! 1477: emit_byte(0xe0+r); ! 1478: } ! 1479: ! 1480: STATIC_INLINE void raw_jmp_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) ! 1481: { ! 1482: int sib; ! 1483: ! 1484: switch (m) { ! 1485: case 1: sib = 0x05; break; ! 1486: case 2: sib = 0x45; break; ! 1487: case 4: sib = 0x85; break; ! 1488: case 8: sib = 0xC5; break; ! 1489: default: abort(); ! 1490: } ! 1491: lopt_emit_all(); ! 1492: emit_byte(0xff); ! 1493: emit_byte(0x24); ! 1494: emit_byte(8*r+sib); ! 1495: emit_long(base); ! 1496: } ! 1497: ! 1498: STATIC_INLINE void raw_jmp_m(uae_u32 base) ! 1499: { ! 1500: lopt_emit_all(); ! 1501: emit_byte(0xff); ! 1502: emit_byte(0x25); ! 1503: emit_long(base); ! 1504: } ! 1505: ! 1506: STATIC_INLINE void raw_call(uae_u32 t) ! 1507: { ! 1508: lopt_emit_all(); ! 1509: emit_byte(0xe8); ! 1510: emit_long(t-(uae_u32)target-4); ! 1511: } ! 1512: ! 1513: STATIC_INLINE void raw_jmp(uae_u32 t) ! 1514: { ! 1515: lopt_emit_all(); ! 1516: emit_byte(0xe9); ! 1517: emit_long(t-(uae_u32)target-4); ! 1518: } ! 1519: ! 1520: STATIC_INLINE void raw_jl(uae_u32 t) ! 1521: { ! 1522: lopt_emit_all(); ! 1523: emit_byte(0x0f); ! 1524: emit_byte(0x8c); ! 1525: emit_long(t-(uae_u32)target-4); ! 1526: } ! 1527: ! 1528: STATIC_INLINE void raw_jz(uae_u32 t) ! 1529: { ! 1530: lopt_emit_all(); ! 1531: emit_byte(0x0f); ! 1532: emit_byte(0x84); ! 1533: emit_long(t-(uae_u32)target-4); ! 1534: } ! 1535: ! 1536: STATIC_INLINE void raw_jnz(uae_u32 t) ! 1537: { ! 1538: lopt_emit_all(); ! 1539: emit_byte(0x0f); ! 1540: emit_byte(0x85); ! 1541: emit_long(t-(uae_u32)target-4); ! 1542: } ! 1543: ! 1544: STATIC_INLINE void raw_jnz_l_oponly(void) ! 1545: { ! 1546: lopt_emit_all(); ! 1547: emit_byte(0x0f); ! 1548: emit_byte(0x85); ! 1549: } ! 1550: ! 1551: STATIC_INLINE void raw_jcc_l_oponly(int cc) ! 1552: { ! 1553: lopt_emit_all(); ! 1554: emit_byte(0x0f); ! 1555: emit_byte(0x80+cc); ! 1556: } ! 1557: ! 1558: STATIC_INLINE void raw_jnz_b_oponly(void) ! 1559: { ! 1560: lopt_emit_all(); ! 1561: emit_byte(0x75); ! 1562: } ! 1563: ! 1564: STATIC_INLINE void raw_jz_b_oponly(void) ! 1565: { ! 1566: lopt_emit_all(); ! 1567: emit_byte(0x74); ! 1568: } ! 1569: ! 1570: STATIC_INLINE void raw_jmp_l_oponly(void) ! 1571: { ! 1572: lopt_emit_all(); ! 1573: emit_byte(0xe9); ! 1574: } ! 1575: ! 1576: STATIC_INLINE void raw_jmp_b_oponly(void) ! 1577: { ! 1578: lopt_emit_all(); ! 1579: emit_byte(0xeb); ! 1580: } ! 1581: ! 1582: STATIC_INLINE void raw_ret(void) ! 1583: { ! 1584: lopt_emit_all(); ! 1585: emit_byte(0xc3); ! 1586: } ! 1587: ! 1588: STATIC_INLINE void raw_nop(void) ! 1589: { ! 1590: lopt_emit_all(); ! 1591: emit_byte(0x90); ! 1592: } ! 1593: ! 1594: ! 1595: /************************************************************************* ! 1596: * Flag handling, to and fro UAE flag register * ! 1597: *************************************************************************/ ! 1598: ! 1599: ! 1600: #define FLAG_NREG1 0 /* Set to -1 if any register will do */ ! 1601: ! 1602: STATIC_INLINE void raw_flags_to_reg(int r) ! 1603: { ! 1604: raw_lahf(0); /* Most flags in AH */ ! 1605: //raw_setcc(r,0); /* V flag in AL */ ! 1606: raw_setcc_m((uae_u32)live.state[FLAGTMP].mem,0); ! 1607: ! 1608: #if 1 /* Let's avoid those nasty partial register stalls */ ! 1609: //raw_mov_b_mr((uae_u32)live.state[FLAGTMP].mem,r); ! 1610: raw_mov_b_mr(((uae_u32)live.state[FLAGTMP].mem)+1,r+4); ! 1611: //live.state[FLAGTMP].status=CLEAN; ! 1612: live.state[FLAGTMP].status=INMEM; ! 1613: live.state[FLAGTMP].realreg=-1; ! 1614: /* We just "evicted" FLAGTMP. */ ! 1615: if (live.nat[r].nholds!=1) { ! 1616: /* Huh? */ ! 1617: abort(); ! 1618: } ! 1619: live.nat[r].nholds=0; ! 1620: #endif ! 1621: } ! 1622: ! 1623: #define FLAG_NREG2 0 /* Set to -1 if any register will do */ ! 1624: STATIC_INLINE void raw_reg_to_flags(int r) ! 1625: { ! 1626: raw_cmp_b_ri(r,-127); /* set V */ ! 1627: raw_sahf(0); ! 1628: } ! 1629: ! 1630: /* Apparently, there are enough instructions between flag store and ! 1631: flag reload to avoid the partial memory stall */ ! 1632: STATIC_INLINE void raw_load_flagreg(uae_u32 target, uae_u32 r) ! 1633: { ! 1634: #if 1 ! 1635: raw_mov_l_rm(target,(uae_u32)live.state[r].mem); ! 1636: #else ! 1637: raw_mov_b_rm(target,(uae_u32)live.state[r].mem); ! 1638: raw_mov_b_rm(target+4,((uae_u32)live.state[r].mem)+1); ! 1639: #endif ! 1640: } ! 1641: ! 1642: /* FLAGX is word-sized */ ! 1643: STATIC_INLINE void raw_load_flagx(uae_u32 target, uae_u32 r) ! 1644: { ! 1645: if (live.nat[target].canword) ! 1646: raw_mov_w_rm(target,(uae_u32)live.state[r].mem); ! 1647: else ! 1648: raw_mov_l_rm(target,(uae_u32)live.state[r].mem); ! 1649: } ! 1650: ! 1651: #define NATIVE_FLAG_Z 0x40 ! 1652: #define NATIVE_CC_EQ 4 ! 1653: STATIC_INLINE void raw_flags_set_zero(int f, int r, int t) ! 1654: { ! 1655: // FIXME: this is really suboptimal ! 1656: raw_pushfl(); ! 1657: raw_pop_l_r(f); ! 1658: raw_and_l_ri(f,~NATIVE_FLAG_Z); ! 1659: raw_test_l_rr(r,r); ! 1660: raw_mov_l_ri(r,0); ! 1661: raw_mov_l_ri(t,NATIVE_FLAG_Z); ! 1662: raw_cmov_l_rr(r,t,NATIVE_CC_EQ); ! 1663: raw_or_l(f,r); ! 1664: raw_push_l_r(f); ! 1665: raw_popfl(); ! 1666: } ! 1667: ! 1668: STATIC_INLINE void raw_inc_sp(int off) ! 1669: { ! 1670: raw_add_l_ri(4,off); ! 1671: } ! 1672: ! 1673: /************************************************************************* ! 1674: * Handling mistaken direct memory access * ! 1675: *************************************************************************/ ! 1676: ! 1677: ! 1678: #ifdef NATMEM_OFFSET ! 1679: #ifdef _WIN32 // %%% BRIAN KING WAS HERE %%% ! 1680: #include <winbase.h> ! 1681: #else ! 1682: #include <asm/sigcontext.h> ! 1683: #endif ! 1684: #include <signal.h> ! 1685: ! 1686: #define SIG_READ 1 ! 1687: #define SIG_WRITE 2 ! 1688: ! 1689: static int in_handler=0; ! 1690: static uae_u8 *veccode; ! 1691: ! 1692: #ifdef _WIN32 ! 1693: ! 1694: #if defined(CPU_64_BIT) ! 1695: #define ctxPC (pContext->Rip) ! 1696: #else ! 1697: #define ctxPC (pContext->Eip) ! 1698: #endif ! 1699: ! 1700: int EvalException (LPEXCEPTION_POINTERS blah, int n_except) ! 1701: { ! 1702: PEXCEPTION_RECORD pExceptRecord = NULL; ! 1703: PCONTEXT pContext = NULL; ! 1704: ! 1705: uae_u8* i = NULL; ! 1706: uae_u32 addr = 0; ! 1707: int r=-1; ! 1708: int size=4; ! 1709: int dir=-1; ! 1710: int len=0; ! 1711: ! 1712: if (n_except != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0) ! 1713: return EXCEPTION_CONTINUE_SEARCH; ! 1714: ! 1715: pExceptRecord = blah->ExceptionRecord; ! 1716: pContext = blah->ContextRecord; ! 1717: ! 1718: if (pContext) ! 1719: i = (uae_u8 *)ctxPC; ! 1720: if (pExceptRecord) ! 1721: addr = (uae_u32)(pExceptRecord->ExceptionInformation[1]); ! 1722: #ifdef JIT_DEBUG ! 1723: write_log (L"JIT: fault address is 0x%x at 0x%x\n",addr,i); ! 1724: #endif ! 1725: if (!canbang || !currprefs.cachesize) ! 1726: return EXCEPTION_CONTINUE_SEARCH; ! 1727: ! 1728: if (in_handler) ! 1729: write_log (L"JIT: Argh --- Am already in a handler. Shouldn't happen!\n"); ! 1730: ! 1731: if (canbang && i>=compiled_code && i<=current_compile_p) { ! 1732: if (*i==0x66) { ! 1733: i++; ! 1734: size=2; ! 1735: len++; ! 1736: } ! 1737: ! 1738: switch(i[0]) { ! 1739: case 0x8a: ! 1740: if ((i[1]&0xc0)==0x80) { ! 1741: r=(i[1]>>3)&7; ! 1742: dir=SIG_READ; ! 1743: size=1; ! 1744: len+=6; ! 1745: break; ! 1746: } ! 1747: break; ! 1748: case 0x88: ! 1749: if ((i[1]&0xc0)==0x80) { ! 1750: r=(i[1]>>3)&7; ! 1751: dir=SIG_WRITE; ! 1752: size=1; ! 1753: len+=6; ! 1754: break; ! 1755: } ! 1756: break; ! 1757: case 0x8b: ! 1758: switch(i[1]&0xc0) { ! 1759: case 0x80: ! 1760: r=(i[1]>>3)&7; ! 1761: dir=SIG_READ; ! 1762: len+=6; ! 1763: break; ! 1764: case 0x40: ! 1765: r=(i[1]>>3)&7; ! 1766: dir=SIG_READ; ! 1767: len+=3; ! 1768: break; ! 1769: case 0x00: ! 1770: r=(i[1]>>3)&7; ! 1771: dir=SIG_READ; ! 1772: len+=2; ! 1773: break; ! 1774: default: ! 1775: break; ! 1776: } ! 1777: break; ! 1778: case 0x89: ! 1779: switch(i[1]&0xc0) { ! 1780: case 0x80: ! 1781: r=(i[1]>>3)&7; ! 1782: dir=SIG_WRITE; ! 1783: len+=6; ! 1784: break; ! 1785: case 0x40: ! 1786: r=(i[1]>>3)&7; ! 1787: dir=SIG_WRITE; ! 1788: len+=3; ! 1789: break; ! 1790: case 0x00: ! 1791: r=(i[1]>>3)&7; ! 1792: dir=SIG_WRITE; ! 1793: len+=2; ! 1794: break; ! 1795: } ! 1796: break; ! 1797: } ! 1798: } ! 1799: ! 1800: if (r!=-1) { ! 1801: void* pr=NULL; ! 1802: #ifdef JIT_DEBUG ! 1803: write_log (L"JIT: register was %d, direction was %d, size was %d\n",r,dir,size); ! 1804: #endif ! 1805: ! 1806: switch(r) { ! 1807: #if defined(CPU_64_BIT) ! 1808: case 0: pr=&(pContext->Rax); break; ! 1809: case 1: pr=&(pContext->Rcx); break; ! 1810: case 2: pr=&(pContext->Rdx); break; ! 1811: case 3: pr=&(pContext->Rbx); break; ! 1812: case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Rax))+1); break; ! 1813: case 5: pr=(size>1)? ! 1814: (void*)(&(pContext->Rbp)): ! 1815: (void*)(((uae_u8*)&(pContext->Rcx))+1); break; ! 1816: case 6: pr=(size>1)? ! 1817: (void*)(&(pContext->Rsi)): ! 1818: (void*)(((uae_u8*)&(pContext->Rdx))+1); break; ! 1819: case 7: pr=(size>1)? ! 1820: (void*)(&(pContext->Rdi)): ! 1821: (void*)(((uae_u8*)&(pContext->Rbx))+1); break; ! 1822: #else ! 1823: case 0: pr=&(pContext->Eax); break; ! 1824: case 1: pr=&(pContext->Ecx); break; ! 1825: case 2: pr=&(pContext->Edx); break; ! 1826: case 3: pr=&(pContext->Ebx); break; ! 1827: case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Eax))+1); break; ! 1828: case 5: pr=(size>1)? ! 1829: (void*)(&(pContext->Ebp)): ! 1830: (void*)(((uae_u8*)&(pContext->Ecx))+1); break; ! 1831: case 6: pr=(size>1)? ! 1832: (void*)(&(pContext->Esi)): ! 1833: (void*)(((uae_u8*)&(pContext->Edx))+1); break; ! 1834: case 7: pr=(size>1)? ! 1835: (void*)(&(pContext->Edi)): ! 1836: (void*)(((uae_u8*)&(pContext->Ebx))+1); break; ! 1837: #endif ! 1838: default: abort(); ! 1839: } ! 1840: if (pr) { ! 1841: blockinfo* bi; ! 1842: ! 1843: if (currprefs.comp_oldsegv) { ! 1844: addr-=(uae_u32)NATMEM_OFFSET; ! 1845: ! 1846: #ifdef JIT_DEBUG ! 1847: if ((addr>=0x10000000 && addr<0x40000000) || ! 1848: (addr>=0x50000000)) { ! 1849: write_log (L"JIT: Suspicious address 0x%x in SEGV handler.\n",addr); ! 1850: } ! 1851: #endif ! 1852: if (dir==SIG_READ) { ! 1853: switch (size) { ! 1854: case 1: *((uae_u8*)pr)=get_byte (addr); break; ! 1855: case 2: *((uae_u16*)pr)=swap16(get_word (addr)); break; ! 1856: case 4: *((uae_u32*)pr)=swap32(get_long (addr)); break; ! 1857: default: abort(); ! 1858: } ! 1859: } ! 1860: else { /* write */ ! 1861: switch (size) { ! 1862: case 1: put_byte (addr,*((uae_u8*)pr)); break; ! 1863: case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; ! 1864: case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; ! 1865: default: abort(); ! 1866: } ! 1867: } ! 1868: #ifdef JIT_DEBUG ! 1869: write_log (L"JIT: Handled one access!\n"); ! 1870: #endif ! 1871: fflush(stdout); ! 1872: segvcount++; ! 1873: ctxPC+=len; ! 1874: } ! 1875: else { ! 1876: void* tmp=target; ! 1877: int i; ! 1878: uae_u8 vecbuf[5]; ! 1879: ! 1880: addr-=(uae_u32)NATMEM_OFFSET; ! 1881: ! 1882: #ifdef JIT_DEBUG ! 1883: if ((addr>=0x10000000 && addr<0x40000000) || ! 1884: (addr>=0x50000000)) { ! 1885: write_log (L"JIT: Suspicious address 0x%x in SEGV handler.\n",addr); ! 1886: } ! 1887: #endif ! 1888: ! 1889: target=(uae_u8*)ctxPC; ! 1890: for (i=0;i<5;i++) ! 1891: vecbuf[i]=target[i]; ! 1892: emit_byte(0xe9); ! 1893: emit_long((uae_u32)veccode-(uae_u32)target-4); ! 1894: #ifdef JIT_DEBUG ! 1895: ! 1896: write_log (L"JIT: Create jump to %p\n",veccode); ! 1897: write_log (L"JIT: Handled one access!\n"); ! 1898: #endif ! 1899: segvcount++; ! 1900: ! 1901: target=veccode; ! 1902: ! 1903: if (dir==SIG_READ) { ! 1904: switch(size) { ! 1905: case 1: raw_mov_b_ri(r,get_byte (addr)); break; ! 1906: case 2: raw_mov_w_ri(r,swap16(get_word (addr))); break; ! 1907: case 4: raw_mov_l_ri(r,swap32(get_long (addr))); break; ! 1908: default: abort(); ! 1909: } ! 1910: } ! 1911: else { /* write */ ! 1912: switch(size) { ! 1913: case 1: put_byte (addr,*((uae_u8*)pr)); break; ! 1914: case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; ! 1915: case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; ! 1916: default: abort(); ! 1917: } ! 1918: } ! 1919: for (i=0;i<5;i++) ! 1920: raw_mov_b_mi(ctxPC+i,vecbuf[i]); ! 1921: raw_mov_l_mi((uae_u32)&in_handler,0); ! 1922: emit_byte(0xe9); ! 1923: emit_long(ctxPC+len-(uae_u32)target-4); ! 1924: in_handler=1; ! 1925: target=(uae_u8*)tmp; ! 1926: } ! 1927: bi=active; ! 1928: while (bi) { ! 1929: if (bi->handler && ! 1930: (uae_u8*)bi->direct_handler<=i && ! 1931: (uae_u8*)bi->nexthandler>i) { ! 1932: #ifdef JIT_DEBUG ! 1933: write_log (L"JIT: deleted trigger (%p<%p<%p) %p\n", ! 1934: bi->handler, ! 1935: i, ! 1936: bi->nexthandler, ! 1937: bi->pc_p); ! 1938: #endif ! 1939: invalidate_block(bi); ! 1940: raise_in_cl_list(bi); ! 1941: set_special(0); ! 1942: return EXCEPTION_CONTINUE_EXECUTION; ! 1943: } ! 1944: bi=bi->next; ! 1945: } ! 1946: /* Not found in the active list. Might be a rom routine that ! 1947: is in the dormant list */ ! 1948: bi=dormant; ! 1949: while (bi) { ! 1950: if (bi->handler && ! 1951: (uae_u8*)bi->direct_handler<=i && ! 1952: (uae_u8*)bi->nexthandler>i) { ! 1953: #ifdef JIT_DEBUG ! 1954: write_log (L"JIT: deleted trigger (%p<%p<%p) %p\n", ! 1955: bi->handler, ! 1956: i, ! 1957: bi->nexthandler, ! 1958: bi->pc_p); ! 1959: #endif ! 1960: invalidate_block(bi); ! 1961: raise_in_cl_list(bi); ! 1962: set_special(0); ! 1963: return EXCEPTION_CONTINUE_EXECUTION; ! 1964: } ! 1965: bi=bi->next; ! 1966: } ! 1967: #ifdef JIT_DEBUG ! 1968: write_log (L"JIT: Huh? Could not find trigger!\n"); ! 1969: #endif ! 1970: return EXCEPTION_CONTINUE_EXECUTION; ! 1971: } ! 1972: } ! 1973: write_log (L"JIT: Can't handle access %08X!\n", i); ! 1974: #if 0 ! 1975: if (i) ! 1976: { ! 1977: int j; ! 1978: ! 1979: for (j=0;j<10;j++) { ! 1980: write_log (L"JIT: instruction byte %2d is 0x%02x\n",j,i[j]); ! 1981: } ! 1982: } ! 1983: write_log (L"Please send the above info (starting at \"fault address\") to\n" ! 1984: L"[email protected]\n" ! 1985: L"This shouldn't happen ;-)\n"); ! 1986: #endif ! 1987: return EXCEPTION_CONTINUE_SEARCH; ! 1988: } ! 1989: #else ! 1990: static void vec(int x, struct sigcontext sc) ! 1991: { ! 1992: uae_u8* i=(uae_u8*)sc.eip; ! 1993: uae_u32 addr=sc.cr2; ! 1994: int r=-1; ! 1995: int size=4; ! 1996: int dir=-1; ! 1997: int len=0; ! 1998: int j; ! 1999: ! 2000: write_log (L"JIT: fault address is %08x at %08x\n",sc.cr2,sc.eip); ! 2001: if (!canbang) ! 2002: write_log (L"JIT: Not happy! Canbang is 0 in SIGSEGV handler!\n"); ! 2003: if (in_handler) ! 2004: write_log (L"JIT: Argh --- Am already in a handler. Shouldn't happen!\n"); ! 2005: ! 2006: if (canbang && i>=compiled_code && i<=current_compile_p) { ! 2007: if (*i==0x66) { ! 2008: i++; ! 2009: size=2; ! 2010: len++; ! 2011: } ! 2012: ! 2013: switch(i[0]) { ! 2014: case 0x8a: ! 2015: if ((i[1]&0xc0)==0x80) { ! 2016: r=(i[1]>>3)&7; ! 2017: dir=SIG_READ; ! 2018: size=1; ! 2019: len+=6; ! 2020: break; ! 2021: } ! 2022: break; ! 2023: case 0x88: ! 2024: if ((i[1]&0xc0)==0x80) { ! 2025: r=(i[1]>>3)&7; ! 2026: dir=SIG_WRITE; ! 2027: size=1; ! 2028: len+=6; ! 2029: break; ! 2030: } ! 2031: break; ! 2032: ! 2033: case 0x8b: ! 2034: switch(i[1]&0xc0) { ! 2035: case 0x80: ! 2036: r=(i[1]>>3)&7; ! 2037: dir=SIG_READ; ! 2038: len+=6; ! 2039: break; ! 2040: case 0x40: ! 2041: r=(i[1]>>3)&7; ! 2042: dir=SIG_READ; ! 2043: len+=3; ! 2044: break; ! 2045: case 0x00: ! 2046: r=(i[1]>>3)&7; ! 2047: dir=SIG_READ; ! 2048: len+=2; ! 2049: break; ! 2050: default: ! 2051: break; ! 2052: } ! 2053: break; ! 2054: ! 2055: case 0x89: ! 2056: switch(i[1]&0xc0) { ! 2057: case 0x80: ! 2058: r=(i[1]>>3)&7; ! 2059: dir=SIG_WRITE; ! 2060: len+=6; ! 2061: break; ! 2062: case 0x40: ! 2063: r=(i[1]>>3)&7; ! 2064: dir=SIG_WRITE; ! 2065: len+=3; ! 2066: break; ! 2067: case 0x00: ! 2068: r=(i[1]>>3)&7; ! 2069: dir=SIG_WRITE; ! 2070: len+=2; ! 2071: break; ! 2072: } ! 2073: break; ! 2074: } ! 2075: } ! 2076: ! 2077: if (r!=-1) { ! 2078: void* pr=NULL; ! 2079: write_log (L"JIT: register was %d, direction was %d, size was %d\n",r,dir,size); ! 2080: ! 2081: switch(r) { ! 2082: case 0: pr=&(sc.eax); break; ! 2083: case 1: pr=&(sc.ecx); break; ! 2084: case 2: pr=&(sc.edx); break; ! 2085: case 3: pr=&(sc.ebx); break; ! 2086: case 4: pr=(size>1)?NULL:(((uae_u8*)&(sc.eax))+1); break; ! 2087: case 5: pr=(size>1)? ! 2088: (void*)(&(sc.ebp)): ! 2089: (void*)(((uae_u8*)&(sc.ecx))+1); break; ! 2090: case 6: pr=(size>1)? ! 2091: (void*)(&(sc.esi)): ! 2092: (void*)(((uae_u8*)&(sc.edx))+1); break; ! 2093: case 7: pr=(size>1)? ! 2094: (void*)(&(sc.edi)): ! 2095: (void*)(((uae_u8*)&(sc.ebx))+1); break; ! 2096: default: abort(); ! 2097: } ! 2098: if (pr) { ! 2099: blockinfo* bi; ! 2100: ! 2101: if (currprefs.comp_oldsegv) { ! 2102: addr-=NATMEM_OFFSET; ! 2103: ! 2104: if ((addr>=0x10000000 && addr<0x40000000) || ! 2105: (addr>=0x50000000)) { ! 2106: write_log (L"JIT: Suspicious address in %x SEGV handler.\n",addr); ! 2107: } ! 2108: if (dir==SIG_READ) { ! 2109: switch(size) { ! 2110: case 1: *((uae_u8*)pr)=get_byte (addr); break; ! 2111: case 2: *((uae_u16*)pr)=get_word (addr); break; ! 2112: case 4: *((uae_u32*)pr)=get_long (addr); break; ! 2113: default: abort(); ! 2114: } ! 2115: } ! 2116: else { /* write */ ! 2117: switch(size) { ! 2118: case 1: put_byte (addr,*((uae_u8*)pr)); break; ! 2119: case 2: put_word (addr,*((uae_u16*)pr)); break; ! 2120: case 4: put_long (addr,*((uae_u32*)pr)); break; ! 2121: default: abort(); ! 2122: } ! 2123: } ! 2124: write_log (L"JIT: Handled one access!\n"); ! 2125: fflush(stdout); ! 2126: segvcount++; ! 2127: sc.eip+=len; ! 2128: } ! 2129: else { ! 2130: void* tmp=target; ! 2131: int i; ! 2132: uae_u8 vecbuf[5]; ! 2133: ! 2134: addr-=NATMEM_OFFSET; ! 2135: ! 2136: if ((addr>=0x10000000 && addr<0x40000000) || ! 2137: (addr>=0x50000000)) { ! 2138: write_log (L"JIT: Suspicious address 0x%x in SEGV handler.\n",addr); ! 2139: } ! 2140: ! 2141: target=(uae_u8*)sc.eip; ! 2142: for (i=0;i<5;i++) ! 2143: vecbuf[i]=target[i]; ! 2144: emit_byte(0xe9); ! 2145: emit_long((uae_u32)veccode-(uae_u32)target-4); ! 2146: write_log (L"JIT: Create jump to %p\n",veccode); ! 2147: ! 2148: write_log (L"JIT: Handled one access!\n"); ! 2149: segvcount++; ! 2150: ! 2151: target=veccode; ! 2152: ! 2153: if (dir==SIG_READ) { ! 2154: switch(size) { ! 2155: case 1: raw_mov_b_ri(r,get_byte (addr)); break; ! 2156: case 2: raw_mov_w_ri(r,get_word (addr)); break; ! 2157: case 4: raw_mov_l_ri(r,get_long (addr)); break; ! 2158: default: abort(); ! 2159: } ! 2160: } ! 2161: else { /* write */ ! 2162: switch(size) { ! 2163: case 1: put_byte (addr,*((uae_u8*)pr)); break; ! 2164: case 2: put_word (addr,*((uae_u16*)pr)); break; ! 2165: case 4: put_long (addr,*((uae_u32*)pr)); break; ! 2166: default: abort(); ! 2167: } ! 2168: } ! 2169: for (i=0;i<5;i++) ! 2170: raw_mov_b_mi(sc.eip+i,vecbuf[i]); ! 2171: raw_mov_l_mi((uae_u32)&in_handler,0); ! 2172: emit_byte(0xe9); ! 2173: emit_long(sc.eip+len-(uae_u32)target-4); ! 2174: in_handler=1; ! 2175: target=tmp; ! 2176: } ! 2177: bi=active; ! 2178: while (bi) { ! 2179: if (bi->handler && ! 2180: (uae_u8*)bi->direct_handler<=i && ! 2181: (uae_u8*)bi->nexthandler>i) { ! 2182: write_log (L"JIT: deleted trigger (%p<%p<%p) %p\n", ! 2183: bi->handler, ! 2184: i, ! 2185: bi->nexthandler, ! 2186: bi->pc_p); ! 2187: invalidate_block(bi); ! 2188: raise_in_cl_list(bi); ! 2189: set_special(0); ! 2190: return; ! 2191: } ! 2192: bi=bi->next; ! 2193: } ! 2194: /* Not found in the active list. Might be a rom routine that ! 2195: is in the dormant list */ ! 2196: bi=dormant; ! 2197: while (bi) { ! 2198: if (bi->handler && ! 2199: (uae_u8*)bi->direct_handler<=i && ! 2200: (uae_u8*)bi->nexthandler>i) { ! 2201: write_log (L"JIT: deleted trigger (%p<%p<%p) %p\n", ! 2202: bi->handler, ! 2203: i, ! 2204: bi->nexthandler, ! 2205: bi->pc_p); ! 2206: invalidate_block(bi); ! 2207: raise_in_cl_list(bi); ! 2208: set_special(0); ! 2209: return; ! 2210: } ! 2211: bi=bi->next; ! 2212: } ! 2213: write_log (L"JIT: Huh? Could not find trigger!\n"); ! 2214: return; ! 2215: } ! 2216: } ! 2217: write_log (L"JIT: Can't handle access!\n"); ! 2218: for (j=0;j<10;j++) { ! 2219: write_log (L"JIT: instruction byte %2d is %02x\n",j,i[j]); ! 2220: } ! 2221: #if 0 ! 2222: write_log (L"Please send the above info (starting at \"fault address\") to\n" ! 2223: "[email protected]\n" ! 2224: "This shouldn't happen ;-)\n"); ! 2225: fflush(stdout); ! 2226: #endif ! 2227: signal(SIGSEGV,SIG_DFL); /* returning here will cause a "real" SEGV */ ! 2228: } ! 2229: #endif ! 2230: #endif ! 2231: ! 2232: /************************************************************************* ! 2233: * Checking for CPU features * ! 2234: *************************************************************************/ ! 2235: ! 2236: struct cpuinfo_x86 { ! 2237: uae_u8 x86; // CPU family ! 2238: uae_u8 x86_vendor; // CPU vendor ! 2239: uae_u8 x86_processor; // CPU canonical processor type ! 2240: uae_u8 x86_brand_id; // CPU BrandID if supported, yield 0 otherwise ! 2241: uae_u32 x86_hwcap; ! 2242: uae_u8 x86_model; ! 2243: uae_u8 x86_mask; ! 2244: int cpuid_level; // Maximum supported CPUID level, -1=no CPUID ! 2245: char x86_vendor_id[16]; ! 2246: }; ! 2247: struct cpuinfo_x86 cpuinfo; ! 2248: ! 2249: enum { ! 2250: X86_VENDOR_INTEL = 0, ! 2251: X86_VENDOR_CYRIX = 1, ! 2252: X86_VENDOR_AMD = 2, ! 2253: X86_VENDOR_UMC = 3, ! 2254: X86_VENDOR_NEXGEN = 4, ! 2255: X86_VENDOR_CENTAUR = 5, ! 2256: X86_VENDOR_RISE = 6, ! 2257: X86_VENDOR_TRANSMETA = 7, ! 2258: X86_VENDOR_NSC = 8, ! 2259: X86_VENDOR_UNKNOWN = 0xff ! 2260: }; ! 2261: ! 2262: enum { ! 2263: X86_PROCESSOR_I386, /* 80386 */ ! 2264: X86_PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */ ! 2265: X86_PROCESSOR_PENTIUM, ! 2266: X86_PROCESSOR_PENTIUMPRO, ! 2267: X86_PROCESSOR_K6, ! 2268: X86_PROCESSOR_ATHLON, ! 2269: X86_PROCESSOR_PENTIUM4, ! 2270: X86_PROCESSOR_K8, ! 2271: X86_PROCESSOR_max ! 2272: }; ! 2273: ! 2274: static struct ptt { ! 2275: const int align_loop; ! 2276: const int align_loop_max_skip; ! 2277: const int align_jump; ! 2278: const int align_jump_max_skip; ! 2279: const int align_func; ! 2280: } ! 2281: x86_alignments[X86_PROCESSOR_max + 1] = { ! 2282: { 4, 3, 4, 3, 4 }, ! 2283: { 16, 15, 16, 15, 16 }, ! 2284: { 16, 7, 16, 7, 16 }, ! 2285: { 16, 15, 16, 7, 16 }, ! 2286: { 32, 7, 32, 7, 32 }, ! 2287: { 16, 7, 16, 7, 16 }, ! 2288: { 0, 0, 0, 0, 0 }, ! 2289: { 16, 7, 16, 7, 16 }, ! 2290: { 0, 0, 0, 0, 0 } ! 2291: }; ! 2292: ! 2293: static void ! 2294: x86_get_cpu_vendor(struct cpuinfo_x86 *c) ! 2295: { ! 2296: char *v = c->x86_vendor_id; ! 2297: ! 2298: if (!strcmp(v, "GenuineIntel")) ! 2299: c->x86_vendor = X86_VENDOR_INTEL; ! 2300: else if (!strcmp(v, "AuthenticAMD")) ! 2301: c->x86_vendor = X86_VENDOR_AMD; ! 2302: else if (!strcmp(v, "CyrixInstead")) ! 2303: c->x86_vendor = X86_VENDOR_CYRIX; ! 2304: else if (!strcmp(v, "Geode by NSC")) ! 2305: c->x86_vendor = X86_VENDOR_NSC; ! 2306: else if (!strcmp(v, "UMC UMC UMC ")) ! 2307: c->x86_vendor = X86_VENDOR_UMC; ! 2308: else if (!strcmp(v, "CentaurHauls")) ! 2309: c->x86_vendor = X86_VENDOR_CENTAUR; ! 2310: else if (!strcmp(v, "NexGenDriven")) ! 2311: c->x86_vendor = X86_VENDOR_NEXGEN; ! 2312: else if (!strcmp(v, "RiseRiseRise")) ! 2313: c->x86_vendor = X86_VENDOR_RISE; ! 2314: else if (!strcmp(v, "GenuineTMx86") || ! 2315: !strcmp(v, "TransmetaCPU")) ! 2316: c->x86_vendor = X86_VENDOR_TRANSMETA; ! 2317: else ! 2318: c->x86_vendor = X86_VENDOR_UNKNOWN; ! 2319: } ! 2320: ! 2321: static void cpuid(uae_u32 op, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 *edx) ! 2322: { ! 2323: const int CPUID_SPACE = 4096; ! 2324: uae_u8* cpuid_space = (uae_u8*)cache_alloc(CPUID_SPACE); ! 2325: static uae_u32 s_op, s_eax, s_ebx, s_ecx, s_edx; ! 2326: uae_u8* tmp=get_target(); ! 2327: ! 2328: s_op = op; ! 2329: set_target(cpuid_space); ! 2330: raw_push_l_r(0); /* eax */ ! 2331: raw_push_l_r(1); /* ecx */ ! 2332: raw_push_l_r(2); /* edx */ ! 2333: raw_push_l_r(3); /* ebx */ ! 2334: raw_mov_l_rm(0,(uintptr)&s_op); ! 2335: raw_cpuid(0); ! 2336: raw_mov_l_mr((uintptr)&s_eax,0); ! 2337: raw_mov_l_mr((uintptr)&s_ebx,3); ! 2338: raw_mov_l_mr((uintptr)&s_ecx,1); ! 2339: raw_mov_l_mr((uintptr)&s_edx,2); ! 2340: raw_pop_l_r(3); ! 2341: raw_pop_l_r(2); ! 2342: raw_pop_l_r(1); ! 2343: raw_pop_l_r(0); ! 2344: raw_ret(); ! 2345: set_target(tmp); ! 2346: ! 2347: ((compop_func*)cpuid_space)(0); ! 2348: if (eax != NULL) *eax = s_eax; ! 2349: if (ebx != NULL) *ebx = s_ebx; ! 2350: if (ecx != NULL) *ecx = s_ecx; ! 2351: if (edx != NULL) *edx = s_edx; ! 2352: ! 2353: cache_free (cpuid_space); ! 2354: } ! 2355: ! 2356: static void raw_init_cpu(void) ! 2357: { ! 2358: struct cpuinfo_x86 *c = &cpuinfo; ! 2359: uae_u32 xlvl; ! 2360: ! 2361: /* Defaults */ ! 2362: c->x86_processor = X86_PROCESSOR_max; ! 2363: c->x86_vendor = X86_VENDOR_UNKNOWN; ! 2364: c->cpuid_level = -1; /* CPUID not detected */ ! 2365: c->x86_model = c->x86_mask = 0; /* So far unknown... */ ! 2366: c->x86_vendor_id[0] = '\0'; /* Unset */ ! 2367: c->x86_hwcap = 0; ! 2368: ! 2369: /* Get vendor name */ ! 2370: c->x86_vendor_id[12] = '\0'; ! 2371: cpuid(0x00000000, ! 2372: (uae_u32 *)&c->cpuid_level, ! 2373: (uae_u32 *)&c->x86_vendor_id[0], ! 2374: (uae_u32 *)&c->x86_vendor_id[8], ! 2375: (uae_u32 *)&c->x86_vendor_id[4]); ! 2376: x86_get_cpu_vendor(c); ! 2377: ! 2378: /* Intel-defined flags: level 0x00000001 */ ! 2379: c->x86_brand_id = 0; ! 2380: if ( c->cpuid_level >= 0x00000001 ) { ! 2381: uae_u32 tfms, brand_id; ! 2382: cpuid(0x00000001, &tfms, &brand_id, NULL, &c->x86_hwcap); ! 2383: c->x86 = (tfms >> 8) & 15; ! 2384: c->x86_model = (tfms >> 4) & 15; ! 2385: c->x86_brand_id = brand_id & 0xff; ! 2386: if ( (c->x86_vendor == X86_VENDOR_AMD) && ! 2387: (c->x86 == 0xf)) { ! 2388: /* AMD Extended Family and Model Values */ ! 2389: c->x86 += (tfms >> 20) & 0xff; ! 2390: c->x86_model += (tfms >> 12) & 0xf0; ! 2391: } ! 2392: c->x86_mask = tfms & 15; ! 2393: } else { ! 2394: /* Have CPUID level 0 only - unheard of */ ! 2395: c->x86 = 4; ! 2396: } ! 2397: ! 2398: /* AMD-defined flags: level 0x80000001 */ ! 2399: cpuid(0x80000000, &xlvl, NULL, NULL, NULL); ! 2400: if ( (xlvl & 0xffff0000) == 0x80000000 ) { ! 2401: if ( xlvl >= 0x80000001 ) { ! 2402: uae_u32 features; ! 2403: cpuid(0x80000001, NULL, NULL, NULL, &features); ! 2404: if (features & (1 << 29)) { ! 2405: /* Assume x86-64 if long mode is supported */ ! 2406: c->x86_processor = X86_PROCESSOR_K8; ! 2407: } ! 2408: } ! 2409: } ! 2410: ! 2411: /* Canonicalize processor ID */ ! 2412: switch (c->x86) { ! 2413: case 3: ! 2414: c->x86_processor = X86_PROCESSOR_I386; ! 2415: break; ! 2416: case 4: ! 2417: c->x86_processor = X86_PROCESSOR_I486; ! 2418: break; ! 2419: case 5: ! 2420: if (c->x86_vendor == X86_VENDOR_AMD) ! 2421: c->x86_processor = X86_PROCESSOR_K6; ! 2422: else ! 2423: c->x86_processor = X86_PROCESSOR_PENTIUM; ! 2424: break; ! 2425: case 6: ! 2426: if (c->x86_vendor == X86_VENDOR_AMD) ! 2427: c->x86_processor = X86_PROCESSOR_ATHLON; ! 2428: else ! 2429: c->x86_processor = X86_PROCESSOR_PENTIUMPRO; ! 2430: break; ! 2431: case 15: ! 2432: if (c->x86_vendor == X86_VENDOR_INTEL) { ! 2433: /* Assume any BrandID >= 8 and family == 15 yields a Pentium 4 */ ! 2434: if (c->x86_brand_id >= 8) ! 2435: c->x86_processor = X86_PROCESSOR_PENTIUM4; ! 2436: } ! 2437: if (c->x86_vendor == X86_VENDOR_AMD) { ! 2438: /* Assume an Athlon processor if family == 15 and it was not ! 2439: detected as an x86-64 so far */ ! 2440: if (c->x86_processor == X86_PROCESSOR_max) ! 2441: c->x86_processor = X86_PROCESSOR_ATHLON; ! 2442: } ! 2443: break; ! 2444: } ! 2445: ! 2446: /* Have CMOV support? */ ! 2447: have_cmov = c->x86_hwcap & (1 << 15); ! 2448: ! 2449: #if 0 ! 2450: /* Can the host CPU suffer from partial register stalls? */ ! 2451: have_rat_stall = (c->x86_vendor == X86_VENDOR_INTEL); ! 2452: /* It appears that partial register writes are a bad idea even on ! 2453: AMD K7 cores, even though they are not supposed to have the ! 2454: dreaded rat stall. Why? Anyway, that's why we lie about it ;-) */ ! 2455: if (c->x86_processor == X86_PROCESSOR_ATHLON) ! 2456: have_rat_stall = 1; ! 2457: #endif ! 2458: have_rat_stall = 1; ! 2459: ! 2460: /* Alignments */ ! 2461: if (tune_alignment) { ! 2462: align_loops = x86_alignments[c->x86_processor].align_loop; ! 2463: align_jumps = x86_alignments[c->x86_processor].align_jump; ! 2464: } ! 2465: { ! 2466: TCHAR *s = au (c->x86_vendor_id); ! 2467: write_log (L"CPUID level=%d, Family=%d, Model=%d, Mask=%d, Vendor=%s [%d]\n", ! 2468: c->cpuid_level, c->x86, c->x86_model, c->x86_mask, s, c->x86_vendor); ! 2469: xfree (s); ! 2470: } ! 2471: } ! 2472: ! 2473: #if 0 ! 2474: static int target_check_bsf(void) ! 2475: { ! 2476: int mismatch = 0; ! 2477: for (int g_ZF = 0; g_ZF <= 1; g_ZF++) { ! 2478: for (int g_CF = 0; g_CF <= 1; g_CF++) { ! 2479: for (int g_OF = 0; g_OF <= 1; g_OF++) { ! 2480: for (int g_SF = 0; g_SF <= 1; g_SF++) { ! 2481: for (int value = -1; value <= 1; value++) { ! 2482: unsigned long flags = (g_SF << 7) | (g_OF << 11) | (g_ZF << 6) | g_CF; ! 2483: unsigned long tmp = value; ! 2484: __asm__ __volatile__ ("push %0; popf; bsf %1,%1; pushf; pop %0" ! 2485: : "+r" (flags), "+r" (tmp) : : "cc"); ! 2486: int OF = (flags >> 11) & 1; ! 2487: int SF = (flags >> 7) & 1; ! 2488: int ZF = (flags >> 6) & 1; ! 2489: int CF = flags & 1; ! 2490: tmp = (value == 0); ! 2491: if (ZF != tmp || SF != g_SF || OF != g_OF || CF != g_CF) ! 2492: mismatch = true; ! 2493: } ! 2494: }}}} ! 2495: if (mismatch) ! 2496: write_log (L"Target CPU defines all flags on BSF instruction\n"); ! 2497: return !mismatch; ! 2498: } ! 2499: #endif ! 2500: ! 2501: #if 0 ! 2502: ! 2503: /************************************************************************* ! 2504: * Checking for CPU features * ! 2505: *************************************************************************/ ! 2506: ! 2507: typedef struct { ! 2508: uae_u32 eax; ! 2509: uae_u32 ecx; ! 2510: uae_u32 edx; ! 2511: uae_u32 ebx; ! 2512: } x86_regs; ! 2513: ! 2514: ! 2515: /* This could be so much easier if it could make assumptions about the ! 2516: compiler... */ ! 2517: ! 2518: static uae_u32 cpuid_ptr; ! 2519: static uae_u32 cpuid_level; ! 2520: ! 2521: static x86_regs cpuid(uae_u32 level) ! 2522: { ! 2523: x86_regs answer; ! 2524: uae_u8 *cpuid_space; ! 2525: void* tmp=get_target(); ! 2526: ! 2527: cpuid_ptr=(uae_u32)&answer; ! 2528: cpuid_level=level; ! 2529: ! 2530: cpuid_space = cache_alloc (256); ! 2531: set_target(cpuid_space); ! 2532: raw_push_l_r(0); /* eax */ ! 2533: raw_push_l_r(1); /* ecx */ ! 2534: raw_push_l_r(2); /* edx */ ! 2535: raw_push_l_r(3); /* ebx */ ! 2536: raw_push_l_r(7); /* edi */ ! 2537: raw_mov_l_rm(0,(uae_u32)&cpuid_level); ! 2538: raw_cpuid(0); ! 2539: raw_mov_l_rm(7,(uae_u32)&cpuid_ptr); ! 2540: raw_mov_l_Rr(7,0,0); ! 2541: raw_mov_l_Rr(7,1,4); ! 2542: raw_mov_l_Rr(7,2,8); ! 2543: raw_mov_l_Rr(7,3,12); ! 2544: raw_pop_l_r(7); ! 2545: raw_pop_l_r(3); ! 2546: raw_pop_l_r(2); ! 2547: raw_pop_l_r(1); ! 2548: raw_pop_l_r(0); ! 2549: raw_ret(); ! 2550: set_target(tmp); ! 2551: ! 2552: ((cpuop_func*)cpuid_space)(0); ! 2553: cache_free (cpuid_space); ! 2554: return answer; ! 2555: } ! 2556: ! 2557: static void raw_init_cpu(void) ! 2558: { ! 2559: x86_regs x; ! 2560: uae_u32 maxlev; ! 2561: ! 2562: x=cpuid(0); ! 2563: maxlev=x.eax; ! 2564: write_log (L"Max CPUID level=%d Processor is %c%c%c%c%c%c%c%c%c%c%c%c\n", ! 2565: maxlev, ! 2566: x.ebx, ! 2567: x.ebx>>8, ! 2568: x.ebx>>16, ! 2569: x.ebx>>24, ! 2570: x.edx, ! 2571: x.edx>>8, ! 2572: x.edx>>16, ! 2573: x.edx>>24, ! 2574: x.ecx, ! 2575: x.ecx>>8, ! 2576: x.ecx>>16, ! 2577: x.ecx>>24 ! 2578: ); ! 2579: have_rat_stall=(x.ecx==0x6c65746e); ! 2580: ! 2581: if (maxlev>=1) { ! 2582: x=cpuid(1); ! 2583: if (x.edx&(1<<15)) ! 2584: have_cmov=1; ! 2585: } ! 2586: have_rat_stall=1; ! 2587: #if 0 ! 2588: if (!have_cmov) ! 2589: have_rat_stall=0; ! 2590: #endif ! 2591: #if 0 ! 2592: write_log (L"have_cmov=%d, avoid_cmov=%d, have_rat_stall=%d\n", ! 2593: have_cmov,currprefs.avoid_cmov,have_rat_stall); ! 2594: if (currprefs.avoid_cmov) { ! 2595: write_log (L"Disabling cmov use despite processor claiming to support it!\n"); ! 2596: have_cmov=0; ! 2597: } ! 2598: #else ! 2599: /* Dear Bernie, I don't want to keep around options which are useless, and not ! 2600: represented in the GUI anymore... Is this okay? */ ! 2601: write_log (L"have_cmov=%d, have_rat_stall=%d\n", have_cmov, have_rat_stall); ! 2602: #endif ! 2603: #if 0 /* For testing of non-cmov code! */ ! 2604: have_cmov=0; ! 2605: #endif ! 2606: #if 0 /* It appears that partial register writes are a bad idea even on ! 2607: AMD K7 cores, even though they are not supposed to have the ! 2608: dreaded rat stall. Why? Anyway, that's why we lie about it ;-) */ ! 2609: if (have_cmov) ! 2610: have_rat_stall=1; ! 2611: #endif ! 2612: } ! 2613: #endif ! 2614: ! 2615: /************************************************************************* ! 2616: * FPU stuff * ! 2617: *************************************************************************/ ! 2618: ! 2619: ! 2620: STATIC_INLINE void raw_fp_init(void) ! 2621: { ! 2622: int i; ! 2623: ! 2624: for (i=0;i<N_FREGS;i++) ! 2625: live.spos[i]=-2; ! 2626: live.tos=-1; /* Stack is empty */ ! 2627: } ! 2628: ! 2629: STATIC_INLINE void raw_fp_cleanup_drop(void) ! 2630: { ! 2631: #if 0 ! 2632: /* using FINIT instead of popping all the entries. ! 2633: Seems to have side effects --- there is display corruption in ! 2634: Quake when this is used */ ! 2635: if (live.tos>1) { ! 2636: emit_byte(0x9b); ! 2637: emit_byte(0xdb); ! 2638: emit_byte(0xe3); ! 2639: live.tos=-1; ! 2640: } ! 2641: #endif ! 2642: while (live.tos>=1) { ! 2643: emit_byte(0xde); ! 2644: emit_byte(0xd9); ! 2645: live.tos-=2; ! 2646: } ! 2647: while (live.tos>=0) { ! 2648: emit_byte(0xdd); ! 2649: emit_byte(0xd8); ! 2650: live.tos--; ! 2651: } ! 2652: raw_fp_init(); ! 2653: } ! 2654: ! 2655: STATIC_INLINE void make_tos(int r) ! 2656: { ! 2657: int p,q; ! 2658: ! 2659: if (live.spos[r]<0) { /* Register not yet on stack */ ! 2660: emit_byte(0xd9); ! 2661: emit_byte(0xe8); /* Push '1' on the stack, just to grow it */ ! 2662: live.tos++; ! 2663: live.spos[r]=live.tos; ! 2664: live.onstack[live.tos]=r; ! 2665: return; ! 2666: } ! 2667: /* Register is on stack */ ! 2668: if (live.tos==live.spos[r]) ! 2669: return; ! 2670: p=live.spos[r]; ! 2671: q=live.onstack[live.tos]; ! 2672: ! 2673: emit_byte(0xd9); ! 2674: emit_byte(0xc8+live.tos-live.spos[r]); /* exchange it with top of stack */ ! 2675: live.onstack[live.tos]=r; ! 2676: live.spos[r]=live.tos; ! 2677: live.onstack[p]=q; ! 2678: live.spos[q]=p; ! 2679: } ! 2680: ! 2681: STATIC_INLINE int stackpos(int r) ! 2682: { ! 2683: if (live.spos[r]<0) ! 2684: abort(); ! 2685: if (live.tos<live.spos[r]) { ! 2686: write_log (L"JIT: Looking for spos for fnreg %d\n",r); ! 2687: abort(); ! 2688: } ! 2689: return live.tos-live.spos[r]; ! 2690: } ! 2691: ! 2692: /* IMO, calling usereg(r) makes no sense, if the register r should supply our function with ! 2693: an argument, because I would expect all arguments to be on the stack already, won't they? ! 2694: Thus, usereg(s) is always useless and also for every FRW d it's too late here now. PeterK ! 2695: */ ! 2696: STATIC_INLINE void usereg(int r) ! 2697: { ! 2698: ! 2699: if (live.spos[r]<0) { ! 2700: // write_log (L"usereg wants to push reg %d onto the x87 stack calling make_tos\n", r); ! 2701: make_tos(r); ! 2702: } ! 2703: } ! 2704: ! 2705: /* This is called with one FP value in a reg *above* tos, ! 2706: which it will pop off the stack if necessary */ ! 2707: STATIC_INLINE void tos_make(int r) ! 2708: { ! 2709: if (live.spos[r]<0) { ! 2710: live.tos++; ! 2711: live.spos[r]=live.tos; ! 2712: live.onstack[live.tos]=r; ! 2713: return; ! 2714: } ! 2715: emit_byte(0xdd); ! 2716: emit_byte(0xd8+(live.tos+1)-live.spos[r]); ! 2717: /* store top of stack in reg and pop it*/ ! 2718: } ! 2719: ! 2720: ! 2721: LOWFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) ! 2722: { ! 2723: make_tos(r); ! 2724: emit_byte(0xdd); ! 2725: emit_byte(0x15); ! 2726: emit_long(m); ! 2727: } ! 2728: LENDFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) ! 2729: ! 2730: LOWFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMW m, FR r)) ! 2731: { ! 2732: make_tos(r); ! 2733: emit_byte(0xdd); ! 2734: emit_byte(0x1d); ! 2735: emit_long(m); ! 2736: live.onstack[live.tos]=-1; ! 2737: live.tos--; ! 2738: live.spos[r]=-2; ! 2739: } ! 2740: LENDFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) ! 2741: ! 2742: LOWFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) ! 2743: { ! 2744: emit_byte(0xdd); ! 2745: emit_byte(0x05); ! 2746: emit_long(m); ! 2747: tos_make(r); ! 2748: } ! 2749: LENDFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) ! 2750: ! 2751: LOWFUNC(NONE,READ,2,raw_fmovi_rm,(FW r, MEMR m)) ! 2752: { ! 2753: emit_byte(0xdb); ! 2754: emit_byte(0x05); ! 2755: emit_long(m); ! 2756: tos_make(r); ! 2757: } ! 2758: LENDFUNC(NONE,READ,2,raw_fmovi_rm,(FW r, MEMR m)) ! 2759: ! 2760: LOWFUNC(NONE,WRITE,3,raw_fmovi_mrb,(MEMW m, FR r, double *bounds)) ! 2761: { ! 2762: /* Clamp value to the given range and convert to integer. ! 2763: ideally, the clamping should be done using two FCMOVs, but ! 2764: this requires two free fp registers, and we can only be sure ! 2765: of having one. Using a jump for the lower bound and an FCMOV ! 2766: for the upper bound, we can do it with one scratch register. ! 2767: */ ! 2768: ! 2769: int rs; ! 2770: usereg(r); ! 2771: rs = stackpos(r)+1; ! 2772: ! 2773: /* Lower bound onto stack */ ! 2774: emit_byte(0xdd); ! 2775: emit_byte(0x05); ! 2776: emit_long((uae_u32)&bounds[0]); /* fld double from lower */ ! 2777: ! 2778: /* Clamp to lower */ ! 2779: emit_byte(0xdb); ! 2780: emit_byte(0xf0+rs); /* fcomi lower,r */ ! 2781: emit_byte(0x73); ! 2782: emit_byte(12); /* jae to writeback */ ! 2783: ! 2784: /* Upper bound onto stack */ ! 2785: emit_byte(0xdd); ! 2786: emit_byte(0xd8); /* fstp st(0) */ ! 2787: emit_byte(0xdd); ! 2788: emit_byte(0x05); ! 2789: emit_long((uae_u32)&bounds[1]); /* fld double from upper */ ! 2790: ! 2791: /* Clamp to upper */ ! 2792: emit_byte(0xdb); ! 2793: emit_byte(0xf0+rs); /* fcomi upper,r */ ! 2794: emit_byte(0xdb); ! 2795: emit_byte(0xd0+rs); /* fcmovnbe upper,r */ ! 2796: ! 2797: /* Store to destination */ ! 2798: emit_byte(0xdb); ! 2799: emit_byte(0x1d); ! 2800: emit_long(m); ! 2801: } ! 2802: LENDFUNC(NONE,WRITE,3,raw_fmovi_mrb,(MEMW m, FR r, double *bounds)) ! 2803: ! 2804: LOWFUNC(NONE,READ,2,raw_fmovs_rm,(FW r, MEMR m)) ! 2805: { ! 2806: emit_byte(0xd9); ! 2807: emit_byte(0x05); ! 2808: emit_long(m); ! 2809: tos_make(r); ! 2810: } ! 2811: LENDFUNC(NONE,READ,2,raw_fmovs_rm,(FW r, MEMR m)) ! 2812: ! 2813: LOWFUNC(NONE,WRITE,2,raw_fmovs_mr,(MEMW m, FR r)) ! 2814: { ! 2815: make_tos(r); ! 2816: emit_byte(0xd9); ! 2817: emit_byte(0x15); ! 2818: emit_long(m); ! 2819: } ! 2820: LENDFUNC(NONE,WRITE,2,raw_fmovs_mr,(MEMW m, FR r)) ! 2821: ! 2822: LOWFUNC(NONE,NONE,1,raw_fcuts_r,(FRW r)) ! 2823: { ! 2824: make_tos(r); /* TOS = r */ ! 2825: emit_byte(0x83); ! 2826: emit_byte(0xc4); ! 2827: emit_byte(0xfc); /* add -4 to esp */ ! 2828: emit_byte(0xd9); ! 2829: emit_byte(0x1c); ! 2830: emit_byte(0x24); /* fstp store r as SINGLE to [esp] and pop */ ! 2831: emit_byte(0xd9); ! 2832: emit_byte(0x04); ! 2833: emit_byte(0x24); /* fld load r as SINGLE from [esp] */ ! 2834: emit_byte(0x83); ! 2835: emit_byte(0xc4); ! 2836: emit_byte(0x04); /* add +4 to esp */ ! 2837: } ! 2838: LENDFUNC(NONE,NONE,1,raw_fcuts_r,(FRW r)) ! 2839: ! 2840: LOWFUNC(NONE,NONE,1,raw_fcut_r,(FRW r)) ! 2841: { ! 2842: make_tos(r); /* TOS = r */ ! 2843: emit_byte(0x83); ! 2844: emit_byte(0xc4); ! 2845: emit_byte(0xf8); /* add -8 to esp */ ! 2846: emit_byte(0xdd); ! 2847: emit_byte(0x1c); ! 2848: emit_byte(0x24); /* fstp store r as DOUBLE to [esp] and pop */ ! 2849: emit_byte(0xdd); ! 2850: emit_byte(0x04); ! 2851: emit_byte(0x24); /* fld load r as DOUBLE from [esp] */ ! 2852: emit_byte(0x83); ! 2853: emit_byte(0xc4); ! 2854: emit_byte(0x08); /* add +8 to esp */ ! 2855: } ! 2856: LENDFUNC(NONE,NONE,1,raw_fcut_r,(FRW r)) ! 2857: ! 2858: LOWFUNC(NONE,READ,2,raw_fmovl_ri,(FW r, IMMS i)) ! 2859: { ! 2860: emit_byte(0x68); ! 2861: emit_long(i); /* push immediate32 onto [esp] */ ! 2862: emit_byte(0xdb); ! 2863: emit_byte(0x04); ! 2864: emit_byte(0x24); /* fild load m32int from [esp] */ ! 2865: emit_byte(0x83); ! 2866: emit_byte(0xc4); ! 2867: emit_byte(0x04); /* add +4 to esp */ ! 2868: tos_make(r); ! 2869: } ! 2870: LENDFUNC(NONE,READ,2,raw_fmovl_ri,(FW r, IMMS i)) ! 2871: ! 2872: LOWFUNC(NONE,READ,2,raw_fmovs_ri,(FW r, IMM i)) ! 2873: { ! 2874: emit_byte(0x68); ! 2875: emit_long(i); /* push immediate32 onto [esp] */ ! 2876: emit_byte(0xd9); ! 2877: emit_byte(0x04); ! 2878: emit_byte(0x24); /* fld load m32real from [esp] */ ! 2879: emit_byte(0x83); ! 2880: emit_byte(0xc4); ! 2881: emit_byte(0x04); /* add +4 to esp */ ! 2882: tos_make(r); ! 2883: } ! 2884: LENDFUNC(NONE,READ,2,raw_fmovs_ri,(FW r, IMM i)) ! 2885: ! 2886: LOWFUNC(NONE,READ,3,raw_fmov_ri,(FW r, IMM i1, IMM i2)) ! 2887: { ! 2888: emit_byte(0x68); ! 2889: emit_long(i2); /* push immediate32 onto [esp] */ ! 2890: emit_byte(0x68); ! 2891: emit_long(i1); /* push immediate32 onto [esp] */ ! 2892: emit_byte(0xdd); ! 2893: emit_byte(0x04); ! 2894: emit_byte(0x24); /* fld load m64real from [esp] */ ! 2895: emit_byte(0x83); ! 2896: emit_byte(0xc4); ! 2897: emit_byte(0x08); /* add +8 to esp */ ! 2898: tos_make(r); ! 2899: } ! 2900: LENDFUNC(NONE,READ,3,raw_fmov_ri,(FW r, IMM i1, IMM i2)) ! 2901: ! 2902: LOWFUNC(NONE,READ,4,raw_fmov_ext_ri,(FW r, IMM i1, IMM i2, IMM i3)) ! 2903: { ! 2904: emit_byte(0x68); ! 2905: emit_long(i3); /* push immediate32 onto [esp] */ ! 2906: emit_byte(0x68); ! 2907: emit_long(i2); /* push immediate32 onto [esp] */ ! 2908: emit_byte(0x68); ! 2909: emit_long(i1); /* push immediate32 onto [esp] */ ! 2910: emit_byte(0xdb); ! 2911: emit_byte(0x2c); ! 2912: emit_byte(0x24); /* fld load m80real from [esp] */ ! 2913: emit_byte(0x83); ! 2914: emit_byte(0xc4); ! 2915: emit_byte(0x0c); /* add +12 to esp */ ! 2916: tos_make(r); ! 2917: } ! 2918: LENDFUNC(NONE,READ,4,raw_fmov_ext_ri,(FW r, IMM i1, IMM i2, IMMi3)) ! 2919: ! 2920: LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) ! 2921: { ! 2922: int rs; ! 2923: ! 2924: /* Stupid x87 can't write a long double to mem without popping the ! 2925: stack! */ ! 2926: usereg(r); ! 2927: rs=stackpos(r); ! 2928: emit_byte(0xd9); /* Get a copy to the top of stack */ ! 2929: emit_byte(0xc0+rs); ! 2930: ! 2931: emit_byte(0xdb); /* store and pop it */ ! 2932: emit_byte(0x3d); ! 2933: emit_long(m); ! 2934: } ! 2935: LENDFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) ! 2936: ! 2937: LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr_drop,(MEMW m, FR r)) ! 2938: { ! 2939: make_tos(r); ! 2940: emit_byte(0xdb); /* store and pop it */ ! 2941: emit_byte(0x3d); ! 2942: emit_long(m); ! 2943: live.onstack[live.tos]=-1; ! 2944: live.tos--; ! 2945: live.spos[r]=-2; ! 2946: } ! 2947: LENDFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) ! 2948: ! 2949: LOWFUNC(NONE,READ,2,raw_fmov_ext_rm,(FW r, MEMR m)) ! 2950: { ! 2951: emit_byte(0xdb); ! 2952: emit_byte(0x2d); ! 2953: emit_long(m); ! 2954: tos_make(r); ! 2955: } ! 2956: LENDFUNC(NONE,READ,2,raw_fmov_ext_rm,(FW r, MEMR m)) ! 2957: ! 2958: LOWFUNC(NONE,NONE,1,raw_fmov_pi,(FW r)) ! 2959: { ! 2960: emit_byte(0xd9); ! 2961: emit_byte(0xeb); ! 2962: tos_make(r); ! 2963: } ! 2964: LENDFUNC(NONE,NONE,1,raw_fmov_pi,(FW r)) ! 2965: ! 2966: LOWFUNC(NONE,NONE,1,raw_fmov_log10_2,(FW r)) ! 2967: { ! 2968: emit_byte(0xd9); ! 2969: emit_byte(0xec); ! 2970: tos_make(r); ! 2971: } ! 2972: LENDFUNC(NONE,NONE,1,raw_fmov_log10_2,(FW r)) ! 2973: ! 2974: LOWFUNC(NONE,NONE,1,raw_fmov_log2_e,(FW r)) ! 2975: { ! 2976: emit_byte(0xd9); ! 2977: emit_byte(0xea); ! 2978: tos_make(r); ! 2979: } ! 2980: LENDFUNC(NONE,NONE,1,raw_fmov_log2_e,(FW r)) ! 2981: ! 2982: LOWFUNC(NONE,NONE,1,raw_fmov_loge_2,(FW r)) ! 2983: { ! 2984: emit_byte(0xd9); ! 2985: emit_byte(0xed); ! 2986: tos_make(r); ! 2987: } ! 2988: LENDFUNC(NONE,NONE,1,raw_fmov_loge_2,(FW r)) ! 2989: ! 2990: LOWFUNC(NONE,NONE,1,raw_fmov_1,(FW r)) ! 2991: { ! 2992: emit_byte(0xd9); ! 2993: emit_byte(0xe8); ! 2994: tos_make(r); ! 2995: } ! 2996: LENDFUNC(NONE,NONE,1,raw_fmov_1,(FW r)) ! 2997: ! 2998: LOWFUNC(NONE,NONE,1,raw_fmov_0,(FW r)) ! 2999: { ! 3000: emit_byte(0xd9); ! 3001: emit_byte(0xee); ! 3002: tos_make(r); ! 3003: } ! 3004: LENDFUNC(NONE,NONE,1,raw_fmov_0,(FW r)) ! 3005: ! 3006: LOWFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) ! 3007: { ! 3008: int ds; ! 3009: ! 3010: ds=stackpos(s); ! 3011: if (ds==0 && live.spos[d]>=0) { ! 3012: /* source is on top of stack, and we already have the dest */ ! 3013: int dd=stackpos(d); ! 3014: emit_byte(0xdd); ! 3015: emit_byte(0xd0+dd); ! 3016: } ! 3017: else { ! 3018: emit_byte(0xd9); ! 3019: emit_byte(0xc0+ds); /* duplicate source on tos */ ! 3020: tos_make(d); /* store to destination, pop if necessary */ ! 3021: } ! 3022: } ! 3023: LENDFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) ! 3024: ! 3025: LOWFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base)) ! 3026: { ! 3027: emit_byte(0xd9); ! 3028: emit_byte(0xa8+index); ! 3029: emit_long(base); ! 3030: } ! 3031: LENDFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base)) ! 3032: ! 3033: LOWFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) ! 3034: { ! 3035: int ds; ! 3036: ! 3037: if (d!=s) { ! 3038: ds=stackpos(s); ! 3039: emit_byte(0xd9); ! 3040: emit_byte(0xc0+ds); /* fld x */ ! 3041: emit_byte(0xd9); ! 3042: emit_byte(0xfa); /* fsqrt sqrt(x) */ ! 3043: tos_make(d); /* store to destination */ ! 3044: } ! 3045: else { ! 3046: make_tos(d); ! 3047: emit_byte(0xd9); ! 3048: emit_byte(0xfa); /* fsqrt y=sqrt(x) */ ! 3049: } ! 3050: } ! 3051: LENDFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) ! 3052: ! 3053: LOWFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) ! 3054: { ! 3055: int ds; ! 3056: ! 3057: if (d!=s) { ! 3058: ds=stackpos(s); ! 3059: emit_byte(0xd9); ! 3060: emit_byte(0xc0+ds); /* fld x */ ! 3061: emit_byte(0xd9); ! 3062: emit_byte(0xe1); /* fabs abs(x) */ ! 3063: tos_make(d); /* store to destination */ ! 3064: } ! 3065: else { ! 3066: make_tos(d); ! 3067: emit_byte(0xd9); ! 3068: emit_byte(0xe1); /* fabs y=abs(x) */ ! 3069: } ! 3070: } ! 3071: LENDFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) ! 3072: ! 3073: LOWFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) ! 3074: { ! 3075: int ds; ! 3076: ! 3077: if (d!=s) { ! 3078: ds=stackpos(s); ! 3079: emit_byte(0xd9); ! 3080: emit_byte(0xc0+ds); /* fld x */ ! 3081: emit_byte(0xd9); ! 3082: emit_byte(0xfc); /* frndint int(x) */ ! 3083: tos_make(d); /* store to destination */ ! 3084: } ! 3085: else { ! 3086: make_tos(d); ! 3087: emit_byte(0xd9); ! 3088: emit_byte(0xfc); /* frndint y=int(x) */ ! 3089: } ! 3090: } ! 3091: LENDFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) ! 3092: ! 3093: LOWFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s)) ! 3094: { ! 3095: int ds; ! 3096: ! 3097: if (d!=s) { ! 3098: ds=stackpos(s); ! 3099: emit_byte(0xd9); ! 3100: emit_byte(0xc0+ds); /* fld x */ ! 3101: emit_byte(0xd9); ! 3102: emit_byte(0xf4); /* fxtract exp push man */ ! 3103: emit_byte(0xdd); ! 3104: emit_byte(0xd8); /* fstp just pop man */ ! 3105: tos_make(d); /* store exp to destination */ ! 3106: } ! 3107: else { ! 3108: make_tos(d); /* tos=x=y */ ! 3109: emit_byte(0xd9); ! 3110: emit_byte(0xf4); /* fxtract exp push man */ ! 3111: emit_byte(0xdd); ! 3112: emit_byte(0xd8); /* fstp just pop man */ ! 3113: } ! 3114: } ! 3115: LENDFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s)) ! 3116: ! 3117: LOWFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s)) ! 3118: { ! 3119: int ds; ! 3120: ! 3121: if (d!=s) { ! 3122: ds=stackpos(s); ! 3123: emit_byte(0xd9); ! 3124: emit_byte(0xc0+ds); /* fld x */ ! 3125: emit_byte(0xd9); ! 3126: emit_byte(0xf4); /* fxtract exp push man */ ! 3127: emit_byte(0xdd); ! 3128: emit_byte(0xd9); /* fstp copy man up & pop */ ! 3129: tos_make(d); /* store man to destination */ ! 3130: } ! 3131: else { ! 3132: make_tos(d); /* tos=x=y */ ! 3133: emit_byte(0xd9); ! 3134: emit_byte(0xf4); /* fxtract exp push man */ ! 3135: emit_byte(0xdd); ! 3136: emit_byte(0xd9); /* fstp copy man up & pop */ ! 3137: } ! 3138: } ! 3139: LENDFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s)) ! 3140: ! 3141: LOWFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) ! 3142: { ! 3143: int ds; ! 3144: ! 3145: if (d!=s) { ! 3146: ds=stackpos(s); ! 3147: emit_byte(0xd9); ! 3148: emit_byte(0xc0+ds); /* fld x */ ! 3149: emit_byte(0xd9); ! 3150: emit_byte(0xfe); /* fsin sin(x) */ ! 3151: tos_make(d); /* store to destination */ ! 3152: } ! 3153: else { ! 3154: make_tos(d); ! 3155: emit_byte(0xd9); ! 3156: emit_byte(0xfe); /* fsin y=sin(x) */ ! 3157: } ! 3158: } ! 3159: LENDFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) ! 3160: ! 3161: LOWFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) ! 3162: { ! 3163: int ds; ! 3164: ! 3165: if (d!=s) { ! 3166: ds=stackpos(s); ! 3167: emit_byte(0xd9); ! 3168: emit_byte(0xc0+ds); /* fld x */ ! 3169: emit_byte(0xd9); ! 3170: emit_byte(0xff); /* fcos cos(x) */ ! 3171: tos_make(d); /* store to destination */ ! 3172: } ! 3173: else { ! 3174: make_tos(d); ! 3175: emit_byte(0xd9); ! 3176: emit_byte(0xff); /* fcos y=cos(x) */ ! 3177: } ! 3178: } ! 3179: LENDFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) ! 3180: ! 3181: LOWFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s)) ! 3182: { ! 3183: int ds; ! 3184: ! 3185: if (d!=s) { ! 3186: ds=stackpos(s); ! 3187: emit_byte(0xd9); ! 3188: emit_byte(0xc0+ds); /* fld x */ ! 3189: emit_byte(0xd9); ! 3190: emit_byte(0xf2); /* fptan tan(x)=y/1.0 */ ! 3191: emit_byte(0xdd); ! 3192: emit_byte(0xd8); /* fstp pop 1.0 */ ! 3193: tos_make(d); /* store to destination */ ! 3194: } ! 3195: else { ! 3196: make_tos(d); ! 3197: emit_byte(0xd9); ! 3198: emit_byte(0xf2); /* fptan tan(x)=y/1.0 */ ! 3199: emit_byte(0xdd); ! 3200: emit_byte(0xd8); /* fstp pop 1.0 */ ! 3201: } ! 3202: } ! 3203: LENDFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s)) ! 3204: ! 3205: LOWFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s)) ! 3206: { ! 3207: int ds; ! 3208: ! 3209: if (s==d) { ! 3210: //write_log (L"FSINCOS src = dest\n"); ! 3211: make_tos(s); ! 3212: emit_byte(0xd9); ! 3213: emit_byte(0xfb); /* fsincos sin(x) push cos(x) */ ! 3214: tos_make(c); /* store cos(x) to c */ ! 3215: return; ! 3216: } ! 3217: ! 3218: ds=stackpos(s); ! 3219: emit_byte(0xd9); ! 3220: emit_byte(0xc0+ds); /* fld x */ ! 3221: emit_byte(0xd9); ! 3222: emit_byte(0xfb); /* fsincos sin(x) push cos(x) */ ! 3223: if (live.spos[c]<0) { ! 3224: if (live.spos[d]<0) { /* occupy both regs directly */ ! 3225: live.tos++; ! 3226: live.spos[d]=live.tos; ! 3227: live.onstack[live.tos]=d; /* sin(x) comes first */ ! 3228: live.tos++; ! 3229: live.spos[c]=live.tos; ! 3230: live.onstack[live.tos]=c; ! 3231: } ! 3232: else { ! 3233: emit_byte(0xd9); ! 3234: emit_byte(0xc9); /* fxch swap cos(x) with sin(x) */ ! 3235: emit_byte(0xdd); /* store sin(x) to d & pop */ ! 3236: emit_byte(0xd8+(live.tos+2)-live.spos[d]); ! 3237: live.tos++; /* occupy a reg for cos(x) here */ ! 3238: live.spos[c]=live.tos; ! 3239: live.onstack[live.tos]=c; ! 3240: } ! 3241: } ! 3242: else { ! 3243: emit_byte(0xdd); /* store cos(x) to c & pop */ ! 3244: emit_byte(0xd8+(live.tos+2)-live.spos[c]); ! 3245: tos_make(d); /* store sin(x) to destination */ ! 3246: } ! 3247: } ! 3248: LENDFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s)) ! 3249: ! 3250: float one=1; ! 3251: ! 3252: LOWFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s)) ! 3253: { ! 3254: int ds; ! 3255: ! 3256: if (live.spos[d]==live.tos && live.spos[s]==live.tos-1) { ! 3257: //write_log (L"fscale found x in TOS-1 and y in TOS\n"); ! 3258: emit_byte(0xd9); ! 3259: emit_byte(0xfd); /* fscale y*(2^x) */ ! 3260: } ! 3261: else { ! 3262: make_tos(s); /* tos=x */ ! 3263: ds=stackpos(d); ! 3264: emit_byte(0xd9); ! 3265: emit_byte(0xc0+ds); /* fld y */ ! 3266: emit_byte(0xd9); ! 3267: emit_byte(0xfd); /* fscale y*(2^x) */ ! 3268: tos_make(d); /* store y=y*(2^x) */ ! 3269: } ! 3270: } ! 3271: LENDFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s)) ! 3272: ! 3273: LOWFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) ! 3274: { ! 3275: int ds; ! 3276: ! 3277: ds=stackpos(s); ! 3278: emit_byte(0xd9); ! 3279: emit_byte(0xc0+ds); /* fld x */ ! 3280: emit_byte(0xd9); ! 3281: emit_byte(0xfc); /* frndint int(x) */ ! 3282: emit_byte(0xd9); ! 3283: emit_byte(0xc1+ds); /* fld x again */ ! 3284: emit_byte(0xd8); ! 3285: emit_byte(0xe1); /* fsub frac(x) = x - int(x) */ ! 3286: emit_byte(0xd9); ! 3287: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3288: emit_byte(0xd8); ! 3289: emit_byte(0x05); ! 3290: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */ ! 3291: emit_byte(0xd9); ! 3292: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x) */ ! 3293: emit_byte(0xdd); ! 3294: emit_byte(0xd9); /* fstp copy & pop */ ! 3295: tos_make(d); /* store y=2^x */ ! 3296: } ! 3297: LENDFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) ! 3298: ! 3299: LOWFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) ! 3300: { ! 3301: int ds; ! 3302: ! 3303: if (s==d) ! 3304: make_tos(s); ! 3305: else { ! 3306: ds=stackpos(s); ! 3307: emit_byte(0xd9); ! 3308: emit_byte(0xc0+ds); /* fld x */ ! 3309: } ! 3310: emit_byte(0xd9); ! 3311: emit_byte(0xea); /* fldl2e log2(e) */ ! 3312: emit_byte(0xd8); ! 3313: emit_byte(0xc9); /* fmul x*log2(e) */ ! 3314: emit_byte(0xdd); ! 3315: emit_byte(0xd1); /* fst copy up */ ! 3316: emit_byte(0xd9); ! 3317: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 3318: emit_byte(0xd9); ! 3319: emit_byte(0xc9); /* fxch swap top two elements */ ! 3320: emit_byte(0xd8); ! 3321: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 3322: emit_byte(0xd9); ! 3323: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3324: emit_byte(0xd8); ! 3325: emit_byte(0x05); ! 3326: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */ ! 3327: emit_byte(0xd9); ! 3328: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 3329: emit_byte(0xdd); ! 3330: emit_byte(0xd9); /* fstp copy & pop */ ! 3331: if (s!=d) ! 3332: tos_make(d); /* store y=e^x */ ! 3333: } ! 3334: LENDFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) ! 3335: ! 3336: LOWFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s)) ! 3337: { ! 3338: int ds; ! 3339: ! 3340: if (s==d) ! 3341: make_tos(s); ! 3342: else { ! 3343: ds=stackpos(s); ! 3344: emit_byte(0xd9); ! 3345: emit_byte(0xc0+ds); /* fld x */ ! 3346: } ! 3347: emit_byte(0xd9); ! 3348: emit_byte(0xea); /* fldl2e log2(e) */ ! 3349: emit_byte(0xd8); ! 3350: emit_byte(0xc9); /* fmul x*log2(e) */ ! 3351: emit_byte(0xdd); ! 3352: emit_byte(0xd1); /* fst copy up */ ! 3353: emit_byte(0xd9); ! 3354: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 3355: emit_byte(0xd9); ! 3356: emit_byte(0xc9); /* fxch swap top two elements */ ! 3357: emit_byte(0xd8); ! 3358: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 3359: emit_byte(0xd9); ! 3360: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3361: emit_byte(0xd9); ! 3362: emit_byte(0xfd); /* fscale ((2^frac(x))-1)*2^int(x*log2(e)) */ ! 3363: emit_byte(0xdd); ! 3364: emit_byte(0xd9); /* fstp copy & pop */ ! 3365: if (s!=d) ! 3366: tos_make(d); /* store y=(e^x)-1 */ ! 3367: } ! 3368: LENDFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s)) ! 3369: ! 3370: LOWFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s)) ! 3371: { ! 3372: int ds; ! 3373: ! 3374: if (s==d) ! 3375: make_tos(s); ! 3376: else { ! 3377: ds=stackpos(s); ! 3378: emit_byte(0xd9); ! 3379: emit_byte(0xc0+ds); /* fld x */ ! 3380: } ! 3381: emit_byte(0xd9); ! 3382: emit_byte(0xe9); /* fldl2t log2(10) */ ! 3383: emit_byte(0xd8); ! 3384: emit_byte(0xc9); /* fmul x*log2(10) */ ! 3385: emit_byte(0xdd); ! 3386: emit_byte(0xd1); /* fst copy up */ ! 3387: emit_byte(0xd9); ! 3388: emit_byte(0xfc); /* frndint int(x*log2(10)) */ ! 3389: emit_byte(0xd9); ! 3390: emit_byte(0xc9); /* fxch swap top two elements */ ! 3391: emit_byte(0xd8); ! 3392: emit_byte(0xe1); /* fsub x*log2(10) - int(x*log2(10)) */ ! 3393: emit_byte(0xd9); ! 3394: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3395: emit_byte(0xd8); ! 3396: emit_byte(0x05); ! 3397: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */ ! 3398: emit_byte(0xd9); ! 3399: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(10)) */ ! 3400: emit_byte(0xdd); ! 3401: emit_byte(0xd9); /* fstp copy & pop */ ! 3402: if (s!=d) ! 3403: tos_make(d); /* store y=10^x */ ! 3404: } ! 3405: LENDFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s)) ! 3406: ! 3407: LOWFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) ! 3408: { ! 3409: int ds; ! 3410: ! 3411: if (s==d) ! 3412: make_tos(s); ! 3413: else { ! 3414: ds=stackpos(s); ! 3415: emit_byte(0xd9); ! 3416: emit_byte(0xc0+ds); /* fld x */ ! 3417: } ! 3418: emit_byte(0xd9); ! 3419: emit_byte(0xe8); /* fld1 1 */ ! 3420: emit_byte(0xd9); ! 3421: emit_byte(0xc9); /* fxch swap 1 with x */ ! 3422: emit_byte(0xd9); ! 3423: emit_byte(0xf1); /* fyl2x 1*log2(x) */ ! 3424: if (s!=d) ! 3425: tos_make(d); /* store y=log2(x) */ ! 3426: } ! 3427: LENDFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) ! 3428: ! 3429: LOWFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s)) ! 3430: { ! 3431: int ds; ! 3432: ! 3433: if (s==d) ! 3434: make_tos(s); ! 3435: else { ! 3436: ds=stackpos(s); ! 3437: emit_byte(0xd9); ! 3438: emit_byte(0xc0+ds); /* fld x */ ! 3439: } ! 3440: emit_byte(0xd9); ! 3441: emit_byte(0xed); /* fldln2 logN(2) */ ! 3442: emit_byte(0xd9); ! 3443: emit_byte(0xc9); /* fxch swap logN(2) with x */ ! 3444: emit_byte(0xd9); ! 3445: emit_byte(0xf1); /* fyl2x logN(2)*log2(x) */ ! 3446: if (s!=d) ! 3447: tos_make(d); /* store y=logN(x) */ ! 3448: } ! 3449: LENDFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s)) ! 3450: ! 3451: LOWFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s)) ! 3452: { ! 3453: int ds; ! 3454: ! 3455: if (s==d) ! 3456: make_tos(s); ! 3457: else { ! 3458: ds=stackpos(s); ! 3459: emit_byte(0xd9); ! 3460: emit_byte(0xc0+ds); /* fld x */ ! 3461: } ! 3462: emit_byte(0xd9); ! 3463: emit_byte(0xed); /* fldln2 logN(2) */ ! 3464: emit_byte(0xd9); ! 3465: emit_byte(0xc9); /* fxch swap logN(2) with x */ ! 3466: emit_byte(0xd9); ! 3467: emit_byte(0xf9); /* fyl2xp1 logN(2)*log2(x+1) */ ! 3468: if (s!=d) ! 3469: tos_make(d); /* store y=logN(x+1) */ ! 3470: } ! 3471: LENDFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s)) ! 3472: ! 3473: LOWFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s)) ! 3474: { ! 3475: int ds; ! 3476: ! 3477: if (s==d) ! 3478: make_tos(s); ! 3479: else { ! 3480: ds=stackpos(s); ! 3481: emit_byte(0xd9); ! 3482: emit_byte(0xc0+ds); /* fld x */ ! 3483: } ! 3484: emit_byte(0xd9); ! 3485: emit_byte(0xec); /* fldlg2 log10(2) */ ! 3486: emit_byte(0xd9); ! 3487: emit_byte(0xc9); /* fxch swap log10(2) with x */ ! 3488: emit_byte(0xd9); ! 3489: emit_byte(0xf1); /* fyl2x log10(2)*log2(x) */ ! 3490: if (s!=d) ! 3491: tos_make(d); /* store y=log10(x) */ ! 3492: } ! 3493: LENDFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s)) ! 3494: ! 3495: LOWFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s)) ! 3496: { ! 3497: int ds; ! 3498: ! 3499: ds=stackpos(s); ! 3500: emit_byte(0xd9); ! 3501: emit_byte(0xc0+ds); /* fld x */ ! 3502: emit_byte(0xd8); ! 3503: emit_byte(0xc8); /* fmul x*x */ ! 3504: emit_byte(0xd9); ! 3505: emit_byte(0xe8); /* fld 1.0 */ ! 3506: emit_byte(0xde); ! 3507: emit_byte(0xe1); /* fsubrp 1 - (x^2) */ ! 3508: emit_byte(0xd9); ! 3509: emit_byte(0xfa); /* fsqrt sqrt(1-(x^2)) */ ! 3510: emit_byte(0xd9); ! 3511: emit_byte(0xc1+ds); /* fld x again */ ! 3512: emit_byte(0xd9); ! 3513: emit_byte(0xc9); /* fxch swap x with sqrt(1-(x^2)) */ ! 3514: emit_byte(0xd9); ! 3515: emit_byte(0xf3); /* fpatan atan(x/sqrt(1-(x^2))) & pop */ ! 3516: tos_make(d); /* store y=asin(x) */ ! 3517: } ! 3518: LENDFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s)) ! 3519: ! 3520: static uae_u32 pihalf[] = {0x2168c234, 0xc90fdaa2, 0x3fff}; // LSB=0 to get acos(1)=0 ! 3521: LOWFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s)) ! 3522: { ! 3523: int ds; ! 3524: ! 3525: ds=stackpos(s); ! 3526: emit_byte(0xd9); ! 3527: emit_byte(0xc0+ds); /* fld x */ ! 3528: emit_byte(0xd8); ! 3529: emit_byte(0xc8); /* fmul x*x */ ! 3530: emit_byte(0xd9); ! 3531: emit_byte(0xe8); /* fld 1.0 */ ! 3532: emit_byte(0xde); ! 3533: emit_byte(0xe1); /* fsubrp 1 - (x^2) */ ! 3534: emit_byte(0xd9); ! 3535: emit_byte(0xfa); /* fsqrt sqrt(1-(x^2)) */ ! 3536: emit_byte(0xd9); ! 3537: emit_byte(0xc1+ds); /* fld x again */ ! 3538: emit_byte(0xd9); ! 3539: emit_byte(0xc9); /* fxch swap x with sqrt(1-(x^2)) */ ! 3540: emit_byte(0xd9); ! 3541: emit_byte(0xf3); /* fpatan atan(x/sqrt(1-(x^2))) & pop */ ! 3542: emit_byte(0xdb); ! 3543: emit_byte(0x2d); ! 3544: emit_long((uae_u32)&pihalf); /* fld load pi/2 from pihalf */ ! 3545: emit_byte(0xde); ! 3546: emit_byte(0xe1); /* fsubrp pi/2 - asin(x) & pop */ ! 3547: tos_make(d); /* store y=acos(x) */ ! 3548: } ! 3549: LENDFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s)) ! 3550: ! 3551: LOWFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s)) ! 3552: { ! 3553: int ds; ! 3554: ! 3555: if (s==d) ! 3556: make_tos(s); ! 3557: else { ! 3558: ds=stackpos(s); ! 3559: emit_byte(0xd9); ! 3560: emit_byte(0xc0+ds); /* fld x */ ! 3561: } ! 3562: emit_byte(0xd9); ! 3563: emit_byte(0xe8); /* fld 1.0 */ ! 3564: emit_byte(0xd9); ! 3565: emit_byte(0xf3); /* fpatan atan(x)/1 & pop*/ ! 3566: if (s!=d) ! 3567: tos_make(d); /* store y=atan(x) */ ! 3568: } ! 3569: LENDFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s)) ! 3570: ! 3571: LOWFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s)) ! 3572: { ! 3573: int ds; ! 3574: ! 3575: ds=stackpos(s); ! 3576: emit_byte(0xd9); ! 3577: emit_byte(0xc0+ds); /* fld x */ ! 3578: emit_byte(0xd9); ! 3579: emit_byte(0xe8); /* fld 1.0 */ ! 3580: emit_byte(0xdc); ! 3581: emit_byte(0xc1); /* fadd 1 + x */ ! 3582: emit_byte(0xd8); ! 3583: emit_byte(0xe2+ds); /* fsub 1 - x */ ! 3584: emit_byte(0xde); ! 3585: emit_byte(0xf9); /* fdivp (1+x)/(1-x) */ ! 3586: emit_byte(0xd9); ! 3587: emit_byte(0xed); /* fldl2e logN(2) */ ! 3588: emit_byte(0xd9); ! 3589: emit_byte(0xc9); /* fxch swap logN(2) with (1+x)/(1-x) */ ! 3590: emit_byte(0xd9); ! 3591: emit_byte(0xf1); /* fyl2x logN(2)*log2((1+x)/(1-x)) pop */ ! 3592: emit_byte(0xd9); ! 3593: emit_byte(0xe8); /* fld 1.0 */ ! 3594: emit_byte(0xd9); ! 3595: emit_byte(0xe0); /* fchs -1.0 */ ! 3596: emit_byte(0xd9); ! 3597: emit_byte(0xc9); /* fxch swap */ ! 3598: emit_byte(0xd9); ! 3599: emit_byte(0xfd); /* fscale logN((1+x)/(1-x)) * 2^(-1) */ ! 3600: emit_byte(0xdd); ! 3601: emit_byte(0xd9); /* fstp copy & pop */ ! 3602: tos_make(d); /* store y=atanh(x) */ ! 3603: } ! 3604: LENDFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s)) ! 3605: ! 3606: LOWFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s)) ! 3607: { ! 3608: int ds,tr; ! 3609: ! 3610: tr=live.onstack[live.tos+3]; ! 3611: if (s==d) ! 3612: make_tos(s); ! 3613: else { ! 3614: ds=stackpos(s); ! 3615: emit_byte(0xd9); ! 3616: emit_byte(0xc0+ds); /* fld x */ ! 3617: } ! 3618: emit_byte(0xd9); ! 3619: emit_byte(0xea); /* fldl2e log2(e) */ ! 3620: emit_byte(0xd8); ! 3621: emit_byte(0xc9); /* fmul x*log2(e) */ ! 3622: emit_byte(0xdd); ! 3623: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 3624: if (tr>=0) { ! 3625: emit_byte(0xd9); ! 3626: emit_byte(0xca); /* fxch swap with temp-reg */ ! 3627: emit_byte(0x83); ! 3628: emit_byte(0xc4); ! 3629: emit_byte(0xf4); /* add -12 to esp */ ! 3630: emit_byte(0xdb); ! 3631: emit_byte(0x3c); ! 3632: emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */ ! 3633: } ! 3634: emit_byte(0xd9); ! 3635: emit_byte(0xe0); /* fchs -x*log2(e) */ ! 3636: emit_byte(0xd9); ! 3637: emit_byte(0xc0); /* fld -x*log2(e) again */ ! 3638: emit_byte(0xd9); ! 3639: emit_byte(0xfc); /* frndint int(-x*log2(e)) */ ! 3640: emit_byte(0xd9); ! 3641: emit_byte(0xc9); /* fxch swap */ ! 3642: emit_byte(0xd8); ! 3643: emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */ ! 3644: emit_byte(0xd9); ! 3645: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3646: emit_byte(0xd8); ! 3647: emit_byte(0x05); ! 3648: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */ ! 3649: emit_byte(0xd9); ! 3650: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 3651: emit_byte(0xd9); ! 3652: emit_byte(0xca); /* fxch swap e^-x with x*log2(e) in tr */ ! 3653: emit_byte(0xdd); ! 3654: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 3655: emit_byte(0xd9); ! 3656: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 3657: emit_byte(0xd9); ! 3658: emit_byte(0xc9); /* fxch swap */ ! 3659: emit_byte(0xd8); ! 3660: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 3661: emit_byte(0xd9); ! 3662: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3663: emit_byte(0xd8); ! 3664: emit_byte(0x05); ! 3665: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */ ! 3666: emit_byte(0xd9); ! 3667: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 3668: emit_byte(0xdd); ! 3669: emit_byte(0xd9); /* fstp copy e^x & pop */ ! 3670: if (tr>=0) { ! 3671: emit_byte(0xdb); ! 3672: emit_byte(0x2c); ! 3673: emit_byte(0x24); /* fld load temp-reg from [esp] */ ! 3674: emit_byte(0x83); ! 3675: emit_byte(0xc4); ! 3676: emit_byte(0x0c); /* add +12 to esp */ ! 3677: emit_byte(0xd9); ! 3678: emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */ ! 3679: emit_byte(0xde); ! 3680: emit_byte(0xe9); /* fsubp (e^x)-(e^-x) */ ! 3681: } ! 3682: else { ! 3683: emit_byte(0xde); ! 3684: emit_byte(0xe1); /* fsubrp (e^x)-(e^-x) */ ! 3685: } ! 3686: emit_byte(0xd9); ! 3687: emit_byte(0xe8); /* fld 1.0 */ ! 3688: emit_byte(0xd9); ! 3689: emit_byte(0xe0); /* fchs -1.0 */ ! 3690: emit_byte(0xd9); ! 3691: emit_byte(0xc9); /* fxch swap */ ! 3692: emit_byte(0xd9); ! 3693: emit_byte(0xfd); /* fscale ((e^x)-(e^-x))/2 */ ! 3694: emit_byte(0xdd); ! 3695: emit_byte(0xd9); /* fstp copy & pop */ ! 3696: if (s!=d) ! 3697: tos_make(d); /* store y=sinh(x) */ ! 3698: } ! 3699: LENDFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s)) ! 3700: ! 3701: LOWFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s)) ! 3702: { ! 3703: int ds,tr; ! 3704: ! 3705: tr=live.onstack[live.tos+3]; ! 3706: if (s==d) ! 3707: make_tos(s); ! 3708: else { ! 3709: ds=stackpos(s); ! 3710: emit_byte(0xd9); ! 3711: emit_byte(0xc0+ds); /* fld x */ ! 3712: } ! 3713: emit_byte(0xd9); ! 3714: emit_byte(0xea); /* fldl2e log2(e) */ ! 3715: emit_byte(0xd8); ! 3716: emit_byte(0xc9); /* fmul x*log2(e) */ ! 3717: emit_byte(0xdd); ! 3718: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 3719: if (tr>=0) { ! 3720: emit_byte(0xd9); ! 3721: emit_byte(0xca); /* fxch swap with temp-reg */ ! 3722: emit_byte(0x83); ! 3723: emit_byte(0xc4); ! 3724: emit_byte(0xf4); /* add -12 to esp */ ! 3725: emit_byte(0xdb); ! 3726: emit_byte(0x3c); ! 3727: emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */ ! 3728: } ! 3729: emit_byte(0xd9); ! 3730: emit_byte(0xe0); /* fchs -x*log2(e) */ ! 3731: emit_byte(0xd9); ! 3732: emit_byte(0xc0); /* fld -x*log2(e) again */ ! 3733: emit_byte(0xd9); ! 3734: emit_byte(0xfc); /* frndint int(-x*log2(e)) */ ! 3735: emit_byte(0xd9); ! 3736: emit_byte(0xc9); /* fxch swap */ ! 3737: emit_byte(0xd8); ! 3738: emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */ ! 3739: emit_byte(0xd9); ! 3740: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3741: emit_byte(0xd8); ! 3742: emit_byte(0x05); ! 3743: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */ ! 3744: emit_byte(0xd9); ! 3745: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 3746: emit_byte(0xd9); ! 3747: emit_byte(0xca); /* fxch swap e^-x with x*log2(e) in tr */ ! 3748: emit_byte(0xdd); ! 3749: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 3750: emit_byte(0xd9); ! 3751: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 3752: emit_byte(0xd9); ! 3753: emit_byte(0xc9); /* fxch swap */ ! 3754: emit_byte(0xd8); ! 3755: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 3756: emit_byte(0xd9); ! 3757: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3758: emit_byte(0xd8); ! 3759: emit_byte(0x05); ! 3760: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */ ! 3761: emit_byte(0xd9); ! 3762: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 3763: emit_byte(0xdd); ! 3764: emit_byte(0xd9); /* fstp copy e^x & pop */ ! 3765: if (tr>=0) { ! 3766: emit_byte(0xdb); ! 3767: emit_byte(0x2c); ! 3768: emit_byte(0x24); /* fld load temp-reg from [esp] */ ! 3769: emit_byte(0x83); ! 3770: emit_byte(0xc4); ! 3771: emit_byte(0x0c); /* add +12 to esp */ ! 3772: emit_byte(0xd9); ! 3773: emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */ ! 3774: } ! 3775: emit_byte(0xde); ! 3776: emit_byte(0xc1); /* faddp (e^x)+(e^-x) */ ! 3777: emit_byte(0xd9); ! 3778: emit_byte(0xe8); /* fld 1.0 */ ! 3779: emit_byte(0xd9); ! 3780: emit_byte(0xe0); /* fchs -1.0 */ ! 3781: emit_byte(0xd9); ! 3782: emit_byte(0xc9); /* fxch swap */ ! 3783: emit_byte(0xd9); ! 3784: emit_byte(0xfd); /* fscale ((e^x)+(e^-x))/2 */ ! 3785: emit_byte(0xdd); ! 3786: emit_byte(0xd9); /* fstp copy & pop */ ! 3787: if (s!=d) ! 3788: tos_make(d); /* store y=cosh(x) */ ! 3789: } ! 3790: LENDFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s)) ! 3791: ! 3792: LOWFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s)) ! 3793: { ! 3794: int ds,tr; ! 3795: ! 3796: tr=live.onstack[live.tos+3]; ! 3797: if (s==d) ! 3798: make_tos(s); ! 3799: else { ! 3800: ds=stackpos(s); ! 3801: emit_byte(0xd9); ! 3802: emit_byte(0xc0+ds); /* fld x */ ! 3803: } ! 3804: emit_byte(0xd9); ! 3805: emit_byte(0xea); /* fldl2e log2(e) */ ! 3806: emit_byte(0xd8); ! 3807: emit_byte(0xc9); /* fmul x*log2(e) */ ! 3808: emit_byte(0xdd); ! 3809: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 3810: if (tr>=0) { ! 3811: emit_byte(0xd9); ! 3812: emit_byte(0xca); /* fxch swap with temp-reg */ ! 3813: emit_byte(0x83); ! 3814: emit_byte(0xc4); ! 3815: emit_byte(0xf4); /* add -12 to esp */ ! 3816: emit_byte(0xdb); ! 3817: emit_byte(0x3c); ! 3818: emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */ ! 3819: } ! 3820: emit_byte(0xd9); ! 3821: emit_byte(0xe0); /* fchs -x*log2(e) */ ! 3822: emit_byte(0xd9); ! 3823: emit_byte(0xc0); /* fld -x*log2(e) again */ ! 3824: emit_byte(0xd9); ! 3825: emit_byte(0xfc); /* frndint int(-x*log2(e)) */ ! 3826: emit_byte(0xd9); ! 3827: emit_byte(0xc9); /* fxch swap */ ! 3828: emit_byte(0xd8); ! 3829: emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */ ! 3830: emit_byte(0xd9); ! 3831: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3832: emit_byte(0xd8); ! 3833: emit_byte(0x05); ! 3834: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */ ! 3835: emit_byte(0xd9); ! 3836: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 3837: emit_byte(0xd9); ! 3838: emit_byte(0xca); /* fxch swap e^-x with x*log2(e) */ ! 3839: emit_byte(0xdd); ! 3840: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 3841: emit_byte(0xd9); ! 3842: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 3843: emit_byte(0xd9); ! 3844: emit_byte(0xc9); /* fxch swap */ ! 3845: emit_byte(0xd8); ! 3846: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 3847: emit_byte(0xd9); ! 3848: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 3849: emit_byte(0xd8); ! 3850: emit_byte(0x05); ! 3851: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */ ! 3852: emit_byte(0xd9); ! 3853: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 3854: emit_byte(0xdd); ! 3855: emit_byte(0xd1); /* fst copy e^x */ ! 3856: emit_byte(0xd8); ! 3857: emit_byte(0xc2); /* fadd (e^x)+(e^-x) */ ! 3858: emit_byte(0xd9); ! 3859: emit_byte(0xca); /* fxch swap with e^-x */ ! 3860: emit_byte(0xde); ! 3861: emit_byte(0xe9); /* fsubp (e^x)-(e^-x) */ ! 3862: if (tr>=0) { ! 3863: emit_byte(0xdb); ! 3864: emit_byte(0x2c); ! 3865: emit_byte(0x24); /* fld load temp-reg from [esp] */ ! 3866: emit_byte(0x83); ! 3867: emit_byte(0xc4); ! 3868: emit_byte(0x0c); /* add +12 to esp */ ! 3869: emit_byte(0xd9); ! 3870: emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */ ! 3871: emit_byte(0xde); ! 3872: emit_byte(0xf9); /* fdivp ((e^x)-(e^-x))/((e^x)+(e^-x)) */ ! 3873: } ! 3874: else { ! 3875: emit_byte(0xde); ! 3876: emit_byte(0xf1); /* fdivrp ((e^x)-(e^-x))/((e^x)+(e^-x)) */ ! 3877: } ! 3878: if (s!=d) ! 3879: tos_make(d); /* store y=tanh(x) */ ! 3880: } ! 3881: LENDFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s)) ! 3882: ! 3883: LOWFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) ! 3884: { ! 3885: int ds; ! 3886: ! 3887: if (d!=s) { ! 3888: ds=stackpos(s); ! 3889: emit_byte(0xd9); ! 3890: emit_byte(0xc0+ds); /* duplicate source */ ! 3891: emit_byte(0xd9); ! 3892: emit_byte(0xe0); /* take fchs */ ! 3893: tos_make(d); /* store to destination */ ! 3894: } ! 3895: else { ! 3896: make_tos(d); ! 3897: emit_byte(0xd9); ! 3898: emit_byte(0xe0); /* take fchs */ ! 3899: } ! 3900: } ! 3901: LENDFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) ! 3902: ! 3903: LOWFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) ! 3904: { ! 3905: int ds; ! 3906: ! 3907: if (live.spos[s]==live.tos) { ! 3908: /* Source is on top of stack */ ! 3909: ds=stackpos(d); ! 3910: emit_byte(0xdc); ! 3911: emit_byte(0xc0+ds); /* add source to dest*/ ! 3912: } ! 3913: else { ! 3914: make_tos(d); ! 3915: ds=stackpos(s); ! 3916: ! 3917: emit_byte(0xd8); ! 3918: emit_byte(0xc0+ds); /* add source to dest*/ ! 3919: } ! 3920: } ! 3921: LENDFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) ! 3922: ! 3923: LOWFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) ! 3924: { ! 3925: int ds; ! 3926: ! 3927: if (live.spos[s]==live.tos) { ! 3928: /* Source is on top of stack */ ! 3929: ds=stackpos(d); ! 3930: emit_byte(0xdc); ! 3931: emit_byte(0xe8+ds); /* sub source from dest*/ ! 3932: } ! 3933: else { ! 3934: make_tos(d); ! 3935: ds=stackpos(s); ! 3936: ! 3937: emit_byte(0xd8); ! 3938: emit_byte(0xe0+ds); /* sub src from dest */ ! 3939: } ! 3940: } ! 3941: LENDFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) ! 3942: ! 3943: LOWFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) ! 3944: { ! 3945: int ds; ! 3946: ! 3947: make_tos(d); ! 3948: ds=stackpos(s); ! 3949: ! 3950: emit_byte(0xdd); ! 3951: emit_byte(0xe0+ds); /* cmp dest with source*/ ! 3952: } ! 3953: LENDFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) ! 3954: ! 3955: LOWFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) ! 3956: { ! 3957: int ds; ! 3958: ! 3959: if (live.spos[s]==live.tos) { ! 3960: /* Source is on top of stack */ ! 3961: ds=stackpos(d); ! 3962: emit_byte(0xdc); ! 3963: emit_byte(0xc8+ds); /* mul dest by source*/ ! 3964: } ! 3965: else { ! 3966: make_tos(d); ! 3967: ds=stackpos(s); ! 3968: ! 3969: emit_byte(0xd8); ! 3970: emit_byte(0xc8+ds); /* mul dest by source*/ ! 3971: } ! 3972: } ! 3973: LENDFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) ! 3974: ! 3975: LOWFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) ! 3976: { ! 3977: int ds; ! 3978: ! 3979: if (live.spos[s]==live.tos) { ! 3980: /* Source is on top of stack */ ! 3981: ds=stackpos(d); ! 3982: emit_byte(0xdc); ! 3983: emit_byte(0xf8+ds); /* div dest by source */ ! 3984: } ! 3985: else { ! 3986: make_tos(d); ! 3987: ds=stackpos(s); ! 3988: ! 3989: emit_byte(0xd8); ! 3990: emit_byte(0xf0+ds); /* div dest by source*/ ! 3991: } ! 3992: } ! 3993: LENDFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) ! 3994: ! 3995: LOWFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) ! 3996: { ! 3997: int ds; ! 3998: ! 3999: if (live.spos[d]==live.tos && live.spos[s]==live.tos-1) { ! 4000: //write_log (L"frem found x in TOS-1 and y in TOS\n"); ! 4001: emit_byte(0xd9); ! 4002: emit_byte(0xf8); /* fprem rem(y/x) */ ! 4003: } ! 4004: else { ! 4005: make_tos(s); /* tos=x */ ! 4006: ds=stackpos(d); ! 4007: emit_byte(0xd9); ! 4008: emit_byte(0xc0+ds); /* fld y */ ! 4009: emit_byte(0xd9); ! 4010: emit_byte(0xf8); /* fprem rem(y/x) */ ! 4011: tos_make(d); /* store y=rem(y/x) */ ! 4012: } ! 4013: } ! 4014: LENDFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) ! 4015: ! 4016: LOWFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) ! 4017: { ! 4018: int ds; ! 4019: ! 4020: if (live.spos[d]==live.tos && live.spos[s]==live.tos-1) { ! 4021: //write_log (L"frem1 found x in TOS-1 and y in TOS\n"); ! 4022: emit_byte(0xd9); ! 4023: emit_byte(0xf5); /* fprem1 rem1(y/x) */ ! 4024: } ! 4025: else { ! 4026: make_tos(s); /* tos=x */ ! 4027: ds=stackpos(d); ! 4028: emit_byte(0xd9); ! 4029: emit_byte(0xc0+ds); /* fld y */ ! 4030: emit_byte(0xd9); ! 4031: emit_byte(0xf5); /* fprem1 rem1(y/x) */ ! 4032: tos_make(d); /* store y=rem(y/x) */ ! 4033: } ! 4034: } ! 4035: LENDFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) ! 4036: ! 4037: LOWFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) ! 4038: { ! 4039: make_tos(r); ! 4040: emit_byte(0xd9); /* ftst */ ! 4041: emit_byte(0xe4); ! 4042: } ! 4043: LENDFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) ! 4044: ! 4045: STATIC_INLINE void raw_fflags_into_flags(int r) ! 4046: { ! 4047: int p; ! 4048: ! 4049: usereg(r); ! 4050: p=stackpos(r); ! 4051: ! 4052: emit_byte(0xd9); ! 4053: emit_byte(0xee); /* Push 0 */ ! 4054: emit_byte(0xd9); ! 4055: emit_byte(0xc9+p); /* swap top two around */ ! 4056: if (have_cmov) { ! 4057: // gb-- fucomi is for P6 cores only, not K6-2 then... ! 4058: emit_byte(0xdb); ! 4059: emit_byte(0xe9+p); /* fucomi them */ ! 4060: } ! 4061: else { ! 4062: emit_byte(0xdd); ! 4063: emit_byte(0xe1+p); /* fucom them */ ! 4064: emit_byte(0x9b); ! 4065: emit_byte(0xdf); ! 4066: emit_byte(0xe0); /* fstsw ax */ ! 4067: raw_sahf(0); /* sahf */ ! 4068: } ! 4069: emit_byte(0xdd); ! 4070: emit_byte(0xd9+p); /* store value back, and get rid of 0 */ ! 4071: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.