|
|
1.1 root 1: /* 1.1.1.2 ! root 2: * compiler/codegen_x86.cpp - IA-32 and AMD64 code generator 1.1 root 3: * 1.1.1.2 ! root 4: * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) ! 5: * ! 6: * Inspired by Christian Bauer's Basilisk II 1.1 root 7: * 1.1.1.2 ! root 8: * This file is part of the ARAnyM project which builds a new and powerful ! 9: * TOS/FreeMiNT compatible virtual machine running on almost any hardware. 1.1 root 10: * 1.1.1.2 ! root 11: * JIT compiler m68k -> IA-32 and AMD64 1.1 root 12: * 1.1.1.2 ! root 13: * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer ! 14: * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne ! 15: * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c 1.1 root 16: * 1.1.1.2 ! root 17: * This program is free software; you can redistribute it and/or modify ! 18: * it under the terms of the GNU General Public License as published by ! 19: * the Free Software Foundation; either version 2 of the License, or ! 20: * (at your option) any later version. 1.1 root 21: * 1.1.1.2 ! root 22: * This program is distributed in the hope that it will be useful, ! 23: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 24: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 25: * GNU General Public License for more details. ! 26: * ! 27: * You should have received a copy of the GNU General Public License ! 28: * along with this program; if not, write to the Free Software ! 29: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1.1 root 30: */ 31: 32: /* This should eventually end up in machdep/, but for now, x86 is the 1.1.1.2 ! root 33: only target, and it's easier this way... */ 1.1 root 34: 35: #include "flags_x86.h" 36: 37: /************************************************************************* 1.1.1.2 ! root 38: * Some basic information about the the target CPU * ! 39: *************************************************************************/ ! 40: ! 41: #define R1 RR1 ! 42: #define R2 RR2 ! 43: #define R4 RR4 1.1 root 44: 45: #define EAX_INDEX 0 46: #define ECX_INDEX 1 47: #define EDX_INDEX 2 48: #define EBX_INDEX 3 49: #define ESP_INDEX 4 50: #define EBP_INDEX 5 51: #define ESI_INDEX 6 52: #define EDI_INDEX 7 1.1.1.2 ! root 53: #if defined(CPU_x86_64) 1.1 root 54: #define R8_INDEX 8 55: #define R9_INDEX 9 56: #define R10_INDEX 10 57: #define R11_INDEX 11 58: #define R12_INDEX 12 59: #define R13_INDEX 13 60: #define R14_INDEX 14 61: #define R15_INDEX 15 62: #endif 63: /* XXX this has to match X86_Reg8H_Base + 4 */ 64: #define AH_INDEX (0x10+4+EAX_INDEX) 65: #define CH_INDEX (0x10+4+ECX_INDEX) 66: #define DH_INDEX (0x10+4+EDX_INDEX) 67: #define BH_INDEX (0x10+4+EBX_INDEX) 68: 69: /* The register in which subroutines return an integer return value */ 70: #define REG_RESULT EAX_INDEX 71: 72: /* The registers subroutines take their first and second argument in */ 1.1.1.2 ! root 73: #ifdef _WIN32 1.1 root 74: /* Handle the _fastcall parameters of ECX and EDX */ 75: #define REG_PAR1 ECX_INDEX 76: #define REG_PAR2 EDX_INDEX 1.1.1.2 ! root 77: #elif defined(CPU_x86_64) 1.1 root 78: #define REG_PAR1 EDI_INDEX 79: #define REG_PAR2 ESI_INDEX 80: #else 81: #define REG_PAR1 EAX_INDEX 82: #define REG_PAR2 EDX_INDEX 83: #endif 84: 85: #define REG_PC_PRE EAX_INDEX /* The register we use for preloading regs.pc_p */ 1.1.1.2 ! root 86: #ifdef _WIN32 ! 87: #define REG_PC_TMP ECX_INDEX 1.1 root 88: #else 89: #define REG_PC_TMP ECX_INDEX /* Another register that is not the above */ 90: #endif 91: 92: #define SHIFTCOUNT_NREG ECX_INDEX /* Register that can be used for shiftcount. 93: -1 if any reg will do */ 94: #define MUL_NREG1 EAX_INDEX /* %eax will hold the low 32 bits after a 32x32 mul */ 95: #define MUL_NREG2 EDX_INDEX /* %edx will hold the high 32 bits */ 96: 97: #define STACK_ALIGN 16 98: #define STACK_OFFSET sizeof(void *) 1.1.1.2 ! root 99: #ifdef _WIN64 ! 100: /* In the Microsoft x64 calling convention, it's the caller's responsibility ! 101: * to allocate 32 bytes of "shadow space" on the stack right before calling ! 102: * the function (regardless of the actual number of parameters used). */ ! 103: #define STACK_SHADOW_SPACE 32 ! 104: #else ! 105: #define STACK_SHADOW_SPACE 0 ! 106: #endif 1.1 root 107: 1.1.1.2 ! root 108: #if defined(CPU_x86_64) ! 109: uae_s8 always_used[] = { 4, 12, -1 }; 1.1 root 110: uae_s8 can_byte[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1}; 111: uae_s8 can_word[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1}; 112: #else 1.1.1.2 ! root 113: uae_s8 always_used[] = { 4, -1 }; 1.1 root 114: uae_s8 can_byte[]={0,1,2,3,-1}; 115: uae_s8 can_word[]={0,1,2,3,5,6,7,-1}; 116: #endif 117: 118: #if USE_OPTIMIZED_CALLS 119: /* Make sure interpretive core does not use cpuopti */ 120: uae_u8 call_saved[]={0,0,0,1,1,1,1,1}; 121: #error FIXME: code not ready 122: #else 123: /* cpuopti mutate instruction handlers to assume registers are saved 124: by the caller */ 125: uae_u8 call_saved[]={0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}; 126: #endif 127: 128: /* This *should* be the same as call_saved. But: 129: - We might not really know which registers are saved, and which aren't, 130: so we need to preserve some, but don't want to rely on everyone else 131: also saving those registers 132: - Special registers (such like the stack pointer) should not be "preserved" 133: by pushing, even though they are "saved" across function calls 134: */ 1.1.1.2 ! root 135: #if defined(CPU_x86_64) ! 136: #ifdef _WIN64 ! 137: /* https://msdn.microsoft.com/en-us/library/6t169e9c.aspx: ! 138: * "The registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 are ! 139: * considered nonvolatile and must be saved and restored by a function that ! 140: * uses them". Also saving r11 for now (see comment below). */ ! 141: static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,1,1,0,0,0,1,1,1,1,1}; ! 142: #else 1.1 root 143: /* callee-saved registers as defined by Linux AMD64 ABI: rbx, rbp, rsp, r12 - r15 */ 144: /* preserve r11 because it's generally used to hold pointers to functions */ 1.1.1.2 ! root 145: /* FIXME: not really sure what the point of saving r11 is (??). If functions ! 146: * cannot assume calle preserves it, it will not be used across calls anyway? */ 1.1 root 147: static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,0,0,0,0,0,1,1,1,1,1}; 1.1.1.2 ! root 148: #endif 1.1 root 149: #else 150: /* callee-saved registers as defined by System V IA-32 ABI: edi, esi, ebx, ebp */ 151: static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,1,1}; 152: #endif 153: 154: /* Whether classes of instructions do or don't clobber the native flags */ 155: #define CLOBBER_MOV 156: #define CLOBBER_LEA 157: #define CLOBBER_CMOV 158: #define CLOBBER_POP 159: #define CLOBBER_PUSH 160: #define CLOBBER_SUB clobber_flags() 161: #define CLOBBER_SBB clobber_flags() 162: #define CLOBBER_CMP clobber_flags() 163: #define CLOBBER_ADD clobber_flags() 164: #define CLOBBER_ADC clobber_flags() 165: #define CLOBBER_AND clobber_flags() 166: #define CLOBBER_OR clobber_flags() 167: #define CLOBBER_XOR clobber_flags() 168: 169: #define CLOBBER_ROL clobber_flags() 170: #define CLOBBER_ROR clobber_flags() 171: #define CLOBBER_SHLL clobber_flags() 172: #define CLOBBER_SHRL clobber_flags() 173: #define CLOBBER_SHRA clobber_flags() 174: #define CLOBBER_TEST clobber_flags() 1.1.1.2 ! root 175: #define CLOBBER_CL16 ! 176: #define CLOBBER_CL8 1.1 root 177: #define CLOBBER_SE32 178: #define CLOBBER_SE16 179: #define CLOBBER_SE8 180: #define CLOBBER_ZE32 181: #define CLOBBER_ZE16 182: #define CLOBBER_ZE8 183: #define CLOBBER_SW16 clobber_flags() 184: #define CLOBBER_SW32 185: #define CLOBBER_SETCC 186: #define CLOBBER_MUL clobber_flags() 187: #define CLOBBER_BT clobber_flags() 188: #define CLOBBER_BSF clobber_flags() 189: 190: /* The older code generator is now deprecated. */ 191: #define USE_NEW_RTASM 1 192: 193: #if USE_NEW_RTASM 194: 1.1.1.2 ! root 195: #if defined(CPU_x86_64) 1.1 root 196: #define X86_TARGET_64BIT 1 197: /* The address override prefix causes a 5 cycles penalty on Intel Core 198: processors. Another solution would be to decompose the load in an LEA, 199: MOV (to zero-extend), MOV (from memory): is it better? */ 200: #define ADDR32 x86_emit_byte(0x67), 201: #else 1.1.1.2 ! root 202: #define ADDR32 1.1 root 203: #endif 204: #define X86_FLAT_REGISTERS 0 205: #define X86_OPTIMIZE_ALU 1 206: #define X86_OPTIMIZE_ROTSHI 1 207: #include "codegen_x86.h" 208: 209: #define x86_emit_byte(B) emit_byte(B) 210: #define x86_emit_word(W) emit_word(W) 211: #define x86_emit_long(L) emit_long(L) 212: #define x86_emit_quad(Q) emit_quad(Q) 213: #define x86_get_target() get_target() 214: #define x86_emit_failure(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__) 215: 1.1.1.2 ! root 216: static inline void x86_64_addr32(void) ! 217: { ! 218: #ifdef CPU_x86_64 ! 219: emit_byte(0x67); ! 220: #endif ! 221: } ! 222: ! 223: static inline void x86_64_rex(bool w, uae_u32 *r, uae_u32 *x, uae_u32 *b) ! 224: { ! 225: #ifdef CPU_x86_64 ! 226: int rex_byte = 0x40; ! 227: if (*b >= R8_INDEX) { ! 228: *b -= R8_INDEX; ! 229: rex_byte |= 1; ! 230: } ! 231: if (rex_byte != 0x40) { ! 232: emit_byte(rex_byte); ! 233: } ! 234: #endif ! 235: } ! 236: ! 237: static inline void x86_64_prefix( ! 238: bool addr32, bool w, uae_u32 *r, uae_u32 *x, uae_u32 *b) ! 239: { ! 240: if (addr32) { ! 241: x86_64_addr32(); ! 242: } ! 243: x86_64_rex(w, r, x, b); ! 244: } ! 245: ! 246: // Some mappings to mark compemu_support calls as only used by compemu ! 247: // These are still mainly x86 minded. Should be more CPU independent in the future ! 248: #define compemu_raw_add_l_mi(a,b) raw_add_l_mi(a,b) ! 249: #define compemu_raw_and_l_ri(a,b) raw_and_l_ri(a,b) ! 250: #define compemu_raw_bswap_32(a) raw_bswap_32(a) ! 251: #define compemu_raw_bt_l_ri(a,b) raw_bt_l_ri(a,b) ! 252: #define compemu_raw_call(a) raw_call(a) ! 253: #define compemu_raw_cmov_l_rm_indexed(a,b,c,d,e) raw_cmov_l_rm_indexed(a,b,c,d,e) ! 254: #define compemu_raw_cmp_l_mi(a,b) raw_cmp_l_mi(a,b) ! 255: #define compemu_raw_cmp_l_mi8(a,b) raw_cmp_l_mi(a,b) ! 256: #define compemu_raw_jcc_b_oponly(a) raw_jcc_b_oponly(a) ! 257: #define compemu_raw_jcc_l_oponly(a) raw_jcc_l_oponly(a) ! 258: #define compemu_raw_jl(a) raw_jl(a) ! 259: #define compemu_raw_jmp(a) raw_jmp(a) ! 260: #define compemu_raw_jmp_m_indexed(a,b,c) raw_jmp_m_indexed(a,b,c) ! 261: #define compemu_raw_jmp_r(a) raw_jmp_r(a) ! 262: #define compemu_raw_jnz(a) raw_jnz(a) ! 263: #define compemu_raw_jz_b_oponly() raw_jz_b_oponly() ! 264: #define compemu_raw_lea_l_brr(a,b,c) raw_lea_l_brr(a,b,c) ! 265: #define compemu_raw_lea_l_brr_indexed(a,b,c,d,e) raw_lea_l_brr_indexed(a,b,c,d,e) ! 266: #define compemu_raw_mov_b_mr(a,b) raw_mov_b_mr(a,b) ! 267: #define compemu_raw_mov_l_mi(a,b) raw_mov_l_mi(a,b) ! 268: #define compemu_raw_mov_l_mr(a,b) raw_mov_l_mr(a,b) ! 269: #define compemu_raw_mov_l_ri(a,b) raw_mov_l_ri(a,b) ! 270: #define compemu_raw_mov_l_rm(a,b) raw_mov_l_rm(a,b) ! 271: #define compemu_raw_mov_l_rr(a,b) raw_mov_l_rr(a,b) ! 272: #define compemu_raw_mov_w_mr(a,b) raw_mov_w_mr(a,b) ! 273: #define compemu_raw_sub_l_mi(a,b) raw_sub_l_mi(a,b) ! 274: #define compemu_raw_test_l_rr(a,b) raw_test_l_rr(a,b) ! 275: #define compemu_raw_zero_extend_16_rr(a,b) raw_zero_extend_16_rr(a,b) ! 276: #define compemu_raw_lea_l_rr_indexed(a,b,c,d) raw_lea_l_rr_indexed(a,b,c,d) ! 277: 1.1 root 278: static void jit_fail(const char *msg, const char *file, int line, const char *function) 279: { 1.1.1.2 ! root 280: jit_abort("failure in function %s from file %s at line %d: %s", 1.1 root 281: function, file, line, msg); 282: } 283: 284: LOWFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) 285: { 1.1.1.2 ! root 286: #if defined(CPU_x86_64) 1.1 root 287: PUSHQr(r); 288: #else 289: PUSHLr(r); 290: #endif 291: } 292: LENDFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) 293: 294: LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) 295: { 1.1.1.2 ! root 296: #if defined(CPU_x86_64) 1.1 root 297: POPQr(r); 298: #else 299: POPLr(r); 300: #endif 301: } 302: LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) 303: 304: LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) 305: { 1.1.1.2 ! root 306: #if defined(CPU_x86_64) 1.1 root 307: POPQm(d, X86_NOREG, X86_NOREG, 1); 308: #else 309: POPLm(d, X86_NOREG, X86_NOREG, 1); 310: #endif 311: } 312: LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) 313: 314: LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) 315: { 316: BTLir(i, r); 317: } 318: LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) 319: 320: LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) 321: { 322: BTLrr(b, r); 323: } 324: LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) 325: 326: LOWFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) 327: { 328: BTCLir(i, r); 329: } 330: LENDFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) 331: 332: LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) 333: { 334: BTCLrr(b, r); 335: } 336: LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) 337: 338: LOWFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) 339: { 340: BTRLir(i, r); 341: } 342: LENDFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) 343: 344: LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) 345: { 346: BTRLrr(b, r); 347: } 348: LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) 349: 350: LOWFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) 351: { 352: BTSLir(i, r); 353: } 354: LENDFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) 355: 356: LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) 357: { 358: BTSLrr(b, r); 359: } 360: LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) 361: 362: LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) 363: { 364: SUBWir(i, d); 365: } 366: LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) 367: 368: LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) 369: { 1.1.1.2 ! root 370: ADDR32 MOVLmr(s, X86_NOREG, X86_NOREG, 1, d); 1.1 root 371: } 372: LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) 373: 374: LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) 375: { 1.1.1.2 ! root 376: ADDR32 MOVLim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 377: } 378: LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) 379: 380: LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) 381: { 1.1.1.2 ! root 382: ADDR32 MOVWim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 383: } 384: LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) 385: 386: LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) 387: { 1.1.1.2 ! root 388: ADDR32 MOVBim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 389: } 390: LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) 391: 392: LOWFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) 393: { 1.1.1.2 ! root 394: ADDR32 ROLBim(i, d, X86_NOREG, X86_NOREG, 1); 1.1 root 395: } 396: LENDFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) 397: 398: LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) 399: { 400: ROLBir(i, r); 401: } 402: LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) 403: 404: LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) 405: { 406: ROLWir(i, r); 407: } 408: LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) 409: 410: LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) 411: { 412: ROLLir(i, r); 413: } 414: LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) 415: 416: LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) 417: { 418: ROLLrr(r, d); 419: } 420: LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) 421: 422: LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) 423: { 424: ROLWrr(r, d); 425: } 426: LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) 427: 428: LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) 429: { 430: ROLBrr(r, d); 431: } 432: LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) 433: 434: LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) 435: { 436: SHLLrr(r, d); 437: } 438: LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) 439: 440: LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) 441: { 442: SHLWrr(r, d); 443: } 444: LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) 445: 446: LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) 447: { 448: SHLBrr(r, d); 449: } 450: LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) 451: 452: LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) 453: { 454: RORBir(i, r); 455: } 456: LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) 457: 458: LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) 459: { 460: RORWir(i, r); 461: } 462: LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) 463: 464: LOWFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) 465: { 1.1.1.2 ! root 466: ADDR32 ORLmr(s, X86_NOREG, X86_NOREG, 1, d); 1.1 root 467: } 468: LENDFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) 469: 470: LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) 471: { 472: RORLir(i, r); 473: } 474: LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) 475: 476: LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) 477: { 478: RORLrr(r, d); 479: } 480: LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) 481: 482: LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) 483: { 484: RORWrr(r, d); 485: } 486: LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) 487: 488: LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) 489: { 490: RORBrr(r, d); 491: } 492: LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) 493: 494: LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) 495: { 496: SHRLrr(r, d); 497: } 498: LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) 499: 500: LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) 501: { 502: SHRWrr(r, d); 503: } 504: LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) 505: 506: LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) 507: { 508: SHRBrr(r, d); 509: } 510: LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) 511: 512: LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) 513: { 514: SARLrr(r, d); 515: } 516: LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) 517: 518: LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) 519: { 520: SARWrr(r, d); 521: } 522: LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) 523: 524: LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) 525: { 526: SARBrr(r, d); 527: } 528: LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) 529: 530: LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) 531: { 532: SHLLir(i, r); 533: } 534: LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) 535: 536: LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) 537: { 538: SHLWir(i, r); 539: } 540: LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) 541: 542: LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) 543: { 544: SHLBir(i, r); 545: } 546: LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) 547: 548: LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) 549: { 550: SHRLir(i, r); 551: } 552: LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) 553: 554: LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) 555: { 556: SHRWir(i, r); 557: } 558: LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) 559: 560: LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) 561: { 562: SHRBir(i, r); 563: } 564: LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) 565: 566: LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) 567: { 568: SARLir(i, r); 569: } 570: LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) 571: 572: LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) 573: { 574: SARWir(i, r); 575: } 576: LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) 577: 578: LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) 579: { 580: SARBir(i, r); 581: } 582: LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) 583: 1.1.1.2 ! root 584: LOWFUNC(WRITE,NONE,1,raw_sahf,(R2)) 1.1 root 585: { 586: SAHF(); 587: } 588: LENDFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) 589: 1.1.1.2 ! root 590: LOWFUNC(NONE,NONE,1,raw_cpuid,(R4)) 1.1 root 591: { 592: CPUID(); 593: } 594: LENDFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) 595: 1.1.1.2 ! root 596: LOWFUNC(READ,NONE,1,raw_lahf,(W2)) 1.1 root 597: { 598: LAHF(); 599: } 600: LENDFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) 601: 602: LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) 603: { 604: SETCCir(cc, d); 605: } 606: LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) 607: 608: LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) 609: { 1.1.1.2 ! root 610: ADDR32 SETCCim(cc, d, X86_NOREG, X86_NOREG, 1); 1.1 root 611: } 612: LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) 613: 614: LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) 615: { 616: if (have_cmov) 617: CMOVLrr(cc, s, d); 618: else { /* replacement using branch and mov */ 1.1.1.2 ! root 619: uae_s8 *target_p = (uae_s8 *)x86_get_target() + 1; 1.1 root 620: JCCSii(cc^1, 0); 621: MOVLrr(s, d); 1.1.1.2 ! root 622: *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); 1.1 root 623: } 624: } 625: LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) 626: 627: LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) 628: { 629: BSFLrr(s, d); 630: } 631: LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) 632: 633: LOWFUNC(NONE,NONE,2,raw_sign_extend_32_rr,(W4 d, R4 s)) 634: { 635: MOVSLQrr(s, d); 636: } 637: LENDFUNC(NONE,NONE,2,raw_sign_extend_32_rr,(W4 d, R4 s)) 638: 639: LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) 640: { 641: MOVSWLrr(s, d); 642: } 643: LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) 644: 645: LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) 646: { 647: MOVSBLrr(s, d); 648: } 649: LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) 650: 651: LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) 652: { 653: MOVZWLrr(s, d); 654: } 655: LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) 656: 657: LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) 658: { 659: MOVZBLrr(s, d); 660: } 661: LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) 662: 663: LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) 664: { 665: IMULLrr(s, d); 666: } 667: LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) 668: 669: LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) 670: { 671: if (d!=MUL_NREG1 || s!=MUL_NREG2) { 1.1.1.2 ! root 672: jit_abort("Bad register in IMUL: d=%d, s=%d",d,s); 1.1 root 673: } 674: IMULLr(s); 675: } 676: LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) 677: 678: LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) 679: { 680: if (d!=MUL_NREG1 || s!=MUL_NREG2) { 1.1.1.2 ! root 681: jit_abort("Bad register in MUL: d=%d, s=%d",d,s); 1.1 root 682: } 683: MULLr(s); 684: } 685: LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) 686: 1.1.1.2 ! root 687: LOWFUNC(NONE,NONE,2,raw_mul_32_32,(RW4, R4)) 1.1 root 688: { 689: abort(); /* %^$&%^$%#^ x86! */ 690: } 691: LENDFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) 692: 693: LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) 694: { 695: MOVBrr(s, d); 696: } 697: LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) 698: 699: LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) 700: { 701: MOVWrr(s, d); 702: } 703: LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) 704: 705: LOWFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) 706: { 707: ADDR32 MOVLmr(0, baser, index, factor, d); 708: } 709: LENDFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) 710: 711: LOWFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) 712: { 713: ADDR32 MOVWmr(0, baser, index, factor, d); 714: } 715: LENDFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) 716: 717: LOWFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) 718: { 719: ADDR32 MOVBmr(0, baser, index, factor, d); 720: } 721: LENDFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) 722: 723: LOWFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) 724: { 725: ADDR32 MOVLrm(s, 0, baser, index, factor); 726: } 727: LENDFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) 728: 729: LOWFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) 730: { 731: ADDR32 MOVWrm(s, 0, baser, index, factor); 732: } 733: LENDFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) 734: 735: LOWFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) 736: { 737: ADDR32 MOVBrm(s, 0, baser, index, factor); 738: } 739: LENDFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) 740: 741: LOWFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) 742: { 743: ADDR32 MOVLrm(s, base, baser, index, factor); 744: } 745: LENDFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) 746: 747: LOWFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) 748: { 749: ADDR32 MOVWrm(s, base, baser, index, factor); 750: } 751: LENDFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) 752: 753: LOWFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) 754: { 755: ADDR32 MOVBrm(s, base, baser, index, factor); 756: } 757: LENDFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) 758: 759: LOWFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) 760: { 761: ADDR32 MOVLmr(base, baser, index, factor, d); 762: } 763: LENDFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) 764: 765: LOWFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) 766: { 767: ADDR32 MOVWmr(base, baser, index, factor, d); 768: } 769: LENDFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) 770: 771: LOWFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) 772: { 773: ADDR32 MOVBmr(base, baser, index, factor, d); 774: } 775: LENDFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) 776: 777: LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) 778: { 779: ADDR32 MOVLmr(base, X86_NOREG, index, factor, d); 780: } 781: LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) 782: 783: LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) 784: { 785: if (have_cmov) 786: ADDR32 CMOVLmr(cond, base, X86_NOREG, index, factor, d); 787: else { /* replacement using branch and mov */ 1.1.1.2 ! root 788: uae_s8 *target_p = (uae_s8 *)x86_get_target() + 1; 1.1 root 789: JCCSii(cond^1, 0); 790: ADDR32 MOVLmr(base, X86_NOREG, index, factor, d); 1.1.1.2 ! root 791: *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); 1.1 root 792: } 793: } 794: LENDFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) 795: 796: LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) 797: { 798: if (have_cmov) 799: CMOVLmr(cond, mem, X86_NOREG, X86_NOREG, 1, d); 800: else { /* replacement using branch and mov */ 1.1.1.2 ! root 801: uae_s8 *target_p = (uae_s8 *)x86_get_target() + 1; 1.1 root 802: JCCSii(cond^1, 0); 1.1.1.2 ! root 803: ADDR32 MOVLmr(mem, X86_NOREG, X86_NOREG, 1, d); ! 804: *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); 1.1 root 805: } 806: } 807: LENDFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) 808: 809: LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) 810: { 811: ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d); 812: } 813: LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) 814: 815: LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) 816: { 817: ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d); 818: } 819: LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) 820: 821: LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) 822: { 823: ADDR32 MOVBmr(offset, s, X86_NOREG, 1, d); 824: } 825: LENDFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) 826: 827: LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) 828: { 829: ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d); 830: } 831: LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) 832: 833: LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) 834: { 835: ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d); 836: } 837: LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) 838: 839: LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) 840: { 841: ADDR32 MOVBmr(offset, s, X86_NOREG, 1, d); 842: } 843: LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) 844: 845: LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) 846: { 847: ADDR32 MOVLim(i, offset, d, X86_NOREG, 1); 848: } 849: LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) 850: 851: LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) 852: { 853: ADDR32 MOVWim(i, offset, d, X86_NOREG, 1); 854: } 855: LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) 856: 857: LOWFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) 858: { 859: ADDR32 MOVBim(i, offset, d, X86_NOREG, 1); 860: } 861: LENDFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) 862: 863: LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) 864: { 865: ADDR32 MOVLrm(s, offset, d, X86_NOREG, 1); 866: } 867: LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) 868: 869: LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) 870: { 871: ADDR32 MOVWrm(s, offset, d, X86_NOREG, 1); 872: } 873: LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) 874: 875: LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) 876: { 877: ADDR32 MOVBrm(s, offset, d, X86_NOREG, 1); 878: } 879: LENDFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) 880: 881: LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) 882: { 1.1.1.2 ! root 883: ADDR32 LEALmr(offset, s, X86_NOREG, 1, d); 1.1 root 884: } 885: LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) 886: 887: LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) 888: { 1.1.1.2 ! root 889: ADDR32 LEALmr(offset, s, index, factor, d); 1.1 root 890: } 891: LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) 892: 893: LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) 894: { 1.1.1.2 ! root 895: ADDR32 LEALmr(0, s, index, factor, d); 1.1 root 896: } 897: LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) 898: 899: LOWFUNC(NONE,NONE,4,raw_lea_l_r_scaled,(W4 d, R4 index, IMM factor)) 900: { 1.1.1.2 ! root 901: ADDR32 LEALmr(0, X86_NOREG, index, factor, d); 1.1 root 902: } 903: LENDFUNC(NONE,NONE,4,raw_lea_l_r_scaled,(W4 d, R4 index, IMM factor)) 904: 905: LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) 906: { 907: ADDR32 MOVLrm(s, offset, d, X86_NOREG, 1); 908: } 909: LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) 910: 911: LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) 912: { 913: ADDR32 MOVWrm(s, offset, d, X86_NOREG, 1); 914: } 915: LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) 916: 917: LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) 918: { 919: ADDR32 MOVBrm(s, offset, d, X86_NOREG, 1); 920: } 921: LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) 922: 923: LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) 924: { 925: BSWAPLr(r); 926: } 927: LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) 928: 929: LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) 930: { 931: ROLWir(8, r); 932: } 933: LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) 934: 935: LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) 936: { 937: MOVLrr(s, d); 938: } 939: LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) 940: 941: LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) 942: { 1.1.1.2 ! root 943: ADDR32 MOVLrm(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 944: } 945: LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) 946: 947: LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) 948: { 1.1.1.2 ! root 949: ADDR32 MOVWrm(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 950: } 951: LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) 952: 953: LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) 954: { 1.1.1.2 ! root 955: ADDR32 MOVWmr(s, X86_NOREG, X86_NOREG, 1, d); 1.1 root 956: } 957: LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) 958: 959: LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) 960: { 1.1.1.2 ! root 961: ADDR32 MOVBrm(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 962: } 963: LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) 964: 965: LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) 966: { 1.1.1.2 ! root 967: ADDR32 MOVBmr(s, X86_NOREG, X86_NOREG, 1, d); 1.1 root 968: } 969: LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) 970: 971: LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) 972: { 973: MOVLir(s, d); 974: } 975: LENDFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) 976: 977: LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) 978: { 979: MOVWir(s, d); 980: } 981: LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) 982: 983: LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) 984: { 985: MOVBir(s, d); 986: } 987: LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) 988: 989: LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) 990: { 1.1.1.2 ! root 991: ADDR32 ADCLim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 992: } 993: LENDFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) 994: 995: LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) 996: { 1.1.1.2 ! root 997: ADDR32 ADDLim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 998: } 999: LENDFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) 1000: 1001: LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) 1002: { 1.1.1.2 ! root 1003: ADDR32 ADDWim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 1004: } 1005: LENDFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) 1006: 1007: LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) 1008: { 1.1.1.2 ! root 1009: ADDR32 ADDBim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 1010: } 1011: LENDFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) 1012: 1013: LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) 1014: { 1015: TESTLir(i, d); 1016: } 1017: LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) 1018: 1019: LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) 1020: { 1021: TESTLrr(s, d); 1022: } 1023: LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) 1024: 1025: LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) 1026: { 1027: TESTWrr(s, d); 1028: } 1029: LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) 1030: 1031: LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) 1032: { 1033: TESTBrr(s, d); 1034: } 1035: LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) 1036: 1037: LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) 1038: { 1039: XORLir(i, d); 1040: } 1041: LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) 1042: 1043: LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) 1044: { 1045: ANDLir(i, d); 1046: } 1047: LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) 1048: 1049: LOWFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) 1050: { 1051: ANDWir(i, d); 1052: } 1053: LENDFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) 1054: 1055: LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) 1056: { 1057: ANDLrr(s, d); 1058: } 1059: LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) 1060: 1061: LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) 1062: { 1063: ANDWrr(s, d); 1064: } 1065: LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) 1066: 1067: LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) 1068: { 1069: ANDBrr(s, d); 1070: } 1071: LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) 1072: 1073: LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) 1074: { 1075: ORLir(i, d); 1076: } 1077: LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) 1078: 1079: LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) 1080: { 1081: ORLrr(s, d); 1082: } 1083: LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) 1084: 1085: LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) 1086: { 1087: ORWrr(s, d); 1088: } 1089: LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) 1090: 1091: LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) 1092: { 1093: ORBrr(s, d); 1094: } 1095: LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) 1096: 1097: LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) 1098: { 1099: ADCLrr(s, d); 1100: } 1101: LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) 1102: 1103: LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) 1104: { 1105: ADCWrr(s, d); 1106: } 1107: LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) 1108: 1109: LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) 1110: { 1111: ADCBrr(s, d); 1112: } 1113: LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) 1114: 1115: LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) 1116: { 1117: ADDLrr(s, d); 1118: } 1119: LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) 1120: 1121: LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) 1122: { 1123: ADDWrr(s, d); 1124: } 1125: LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) 1126: 1127: LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) 1128: { 1129: ADDBrr(s, d); 1130: } 1131: LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) 1132: 1133: LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) 1134: { 1135: SUBLir(i, d); 1136: } 1137: LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) 1138: 1139: LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) 1140: { 1141: SUBBir(i, d); 1142: } 1143: LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) 1144: 1145: LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) 1146: { 1147: ADDLir(i, d); 1148: } 1149: LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) 1150: 1151: LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) 1152: { 1153: ADDWir(i, d); 1154: } 1155: LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) 1156: 1157: LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) 1158: { 1159: ADDBir(i, d); 1160: } 1161: LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) 1162: 1163: LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) 1164: { 1165: SBBLrr(s, d); 1166: } 1167: LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) 1168: 1169: LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) 1170: { 1171: SBBWrr(s, d); 1172: } 1173: LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) 1174: 1175: LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) 1176: { 1177: SBBBrr(s, d); 1178: } 1179: LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) 1180: 1181: LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) 1182: { 1183: SUBLrr(s, d); 1184: } 1185: LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) 1186: 1187: LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) 1188: { 1189: SUBWrr(s, d); 1190: } 1191: LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) 1192: 1193: LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) 1194: { 1195: SUBBrr(s, d); 1196: } 1197: LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) 1198: 1199: LOWFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) 1200: { 1201: CMPLrr(s, d); 1202: } 1203: LENDFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) 1204: 1205: LOWFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) 1206: { 1207: CMPLir(i, r); 1208: } 1209: LENDFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) 1210: 1211: LOWFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) 1212: { 1213: CMPWrr(s, d); 1214: } 1215: LENDFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) 1216: 1217: LOWFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) 1218: { 1.1.1.2 ! root 1219: ADDR32 CMPBim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 1220: } 1.1.1.2 ! root 1221: LENDFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) 1.1 root 1222: 1223: LOWFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) 1224: { 1225: CMPBir(i, d); 1226: } 1227: LENDFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) 1228: 1229: LOWFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) 1230: { 1231: CMPBrr(s, d); 1232: } 1233: LENDFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) 1234: 1235: LOWFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) 1236: { 1237: ADDR32 CMPLmr(offset, X86_NOREG, index, factor, d); 1238: } 1239: LENDFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) 1240: 1241: LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) 1242: { 1243: XORLrr(s, d); 1244: } 1245: LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) 1246: 1247: LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) 1248: { 1249: XORWrr(s, d); 1250: } 1251: LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) 1252: 1253: LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) 1254: { 1255: XORBrr(s, d); 1256: } 1257: LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) 1258: 1259: LOWFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) 1260: { 1.1.1.2 ! root 1261: ADDR32 SUBLim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 1262: } 1263: LENDFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) 1264: 1265: LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) 1266: { 1.1.1.2 ! root 1267: ADDR32 CMPLim(s, d, X86_NOREG, X86_NOREG, 1); 1.1 root 1268: } 1269: LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) 1270: 1271: LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) 1272: { 1273: XCHGLrr(r2, r1); 1274: } 1275: LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) 1276: 1277: LOWFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) 1278: { 1279: XCHGBrr(r2, r1); 1280: } 1281: LENDFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) 1282: 1283: LOWFUNC(READ,WRITE,0,raw_pushfl,(void)) 1284: { 1285: PUSHF(); 1286: } 1287: LENDFUNC(READ,WRITE,0,raw_pushfl,(void)) 1288: 1289: LOWFUNC(WRITE,READ,0,raw_popfl,(void)) 1290: { 1291: POPF(); 1292: } 1293: LENDFUNC(WRITE,READ,0,raw_popfl,(void)) 1294: 1295: /* Generate floating-point instructions */ 1296: static inline void x86_fadd_m(MEMR s) 1297: { 1.1.1.2 ! root 1298: ADDR32 FADDLm(s,X86_NOREG,X86_NOREG,1); 1.1 root 1299: } 1300: 1301: #else 1302: 1.1.1.2 ! root 1303: const bool optimize_accum = true; ! 1304: const bool optimize_imm8 = true; 1.1 root 1305: const bool optimize_shift_once = true; 1306: 1307: /************************************************************************* 1.1.1.2 ! root 1308: * Actual encoding of the instructions on the target CPU * ! 1309: *************************************************************************/ 1.1 root 1310: 1.1.1.2 ! root 1311: static inline int isaccum(int r) 1.1 root 1312: { 1313: return (r == EAX_INDEX); 1314: } 1315: 1.1.1.2 ! root 1316: static inline int isbyte(uae_s32 x) 1.1 root 1317: { 1318: return (x>=-128 && x<=127); 1319: } 1320: 1.1.1.2 ! root 1321: static inline int isword(uae_s32 x) 1.1 root 1322: { 1323: return (x>=-32768 && x<=32767); 1324: } 1325: 1326: LOWFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) 1327: { 1328: emit_byte(0x50+r); 1329: } 1330: LENDFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) 1331: 1332: LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) 1333: { 1334: emit_byte(0x58+r); 1335: } 1336: LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) 1337: 1338: LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) 1339: { 1340: emit_byte(0x8f); 1341: emit_byte(0x05); 1342: emit_long(d); 1343: } 1344: LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) 1345: 1346: LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) 1347: { 1348: emit_byte(0x0f); 1349: emit_byte(0xba); 1350: emit_byte(0xe0+r); 1351: emit_byte(i); 1352: } 1353: LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) 1354: 1355: LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) 1356: { 1357: emit_byte(0x0f); 1358: emit_byte(0xa3); 1359: emit_byte(0xc0+8*b+r); 1360: } 1361: LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) 1362: 1363: LOWFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) 1364: { 1365: emit_byte(0x0f); 1366: emit_byte(0xba); 1367: emit_byte(0xf8+r); 1368: emit_byte(i); 1369: } 1370: LENDFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) 1371: 1372: LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) 1373: { 1374: emit_byte(0x0f); 1375: emit_byte(0xbb); 1376: emit_byte(0xc0+8*b+r); 1377: } 1378: LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) 1379: 1380: 1381: LOWFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) 1382: { 1383: emit_byte(0x0f); 1384: emit_byte(0xba); 1385: emit_byte(0xf0+r); 1386: emit_byte(i); 1387: } 1388: LENDFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) 1389: 1390: LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) 1391: { 1392: emit_byte(0x0f); 1393: emit_byte(0xb3); 1394: emit_byte(0xc0+8*b+r); 1395: } 1396: LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) 1397: 1398: LOWFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) 1399: { 1400: emit_byte(0x0f); 1401: emit_byte(0xba); 1402: emit_byte(0xe8+r); 1403: emit_byte(i); 1404: } 1405: LENDFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) 1406: 1407: LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) 1408: { 1409: emit_byte(0x0f); 1410: emit_byte(0xab); 1411: emit_byte(0xc0+8*b+r); 1412: } 1413: LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) 1414: 1415: LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) 1416: { 1.1.1.2 ! root 1417: emit_byte(0x66); ! 1418: if (isbyte(i)) { ! 1419: emit_byte(0x83); ! 1420: emit_byte(0xe8+d); ! 1421: emit_byte(i); ! 1422: } 1.1 root 1423: else { 1.1.1.2 ! root 1424: if (optimize_accum && isaccum(d)) ! 1425: emit_byte(0x2d); ! 1426: else { ! 1427: emit_byte(0x81); ! 1428: emit_byte(0xe8+d); ! 1429: } ! 1430: emit_word(i); 1.1 root 1431: } 1432: } 1433: LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) 1434: 1435: 1436: LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) 1437: { 1.1.1.2 ! root 1438: emit_byte(0x8b); ! 1439: emit_byte(0x05+8*d); ! 1440: emit_long(s); 1.1 root 1441: } 1442: LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) 1443: 1444: LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) 1445: { 1.1.1.2 ! root 1446: emit_byte(0xc7); ! 1447: emit_byte(0x05); ! 1448: emit_long(d); ! 1449: emit_long(s); 1.1 root 1450: } 1451: LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) 1452: 1453: LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) 1454: { 1.1.1.2 ! root 1455: emit_byte(0x66); ! 1456: emit_byte(0xc7); ! 1457: emit_byte(0x05); ! 1458: emit_long(d); ! 1459: emit_word(s); 1.1 root 1460: } 1461: LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) 1462: 1463: LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) 1464: { 1.1.1.2 ! root 1465: emit_byte(0xc6); ! 1466: emit_byte(0x05); ! 1467: emit_long(d); ! 1468: emit_byte(s); 1.1 root 1469: } 1470: LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) 1471: 1472: LOWFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) 1473: { 1474: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1475: emit_byte(0xd0); ! 1476: emit_byte(0x05); ! 1477: emit_long(d); 1.1 root 1478: } 1479: else { 1.1.1.2 ! root 1480: emit_byte(0xc0); ! 1481: emit_byte(0x05); ! 1482: emit_long(d); ! 1483: emit_byte(i); 1.1 root 1484: } 1485: } 1486: LENDFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) 1487: 1488: LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) 1489: { 1490: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1491: emit_byte(0xd0); ! 1492: emit_byte(0xc0+r); 1.1 root 1493: } 1494: else { 1.1.1.2 ! root 1495: emit_byte(0xc0); ! 1496: emit_byte(0xc0+r); ! 1497: emit_byte(i); 1.1 root 1498: } 1499: } 1500: LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) 1501: 1502: LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) 1503: { 1.1.1.2 ! root 1504: emit_byte(0x66); ! 1505: emit_byte(0xc1); ! 1506: emit_byte(0xc0+r); ! 1507: emit_byte(i); 1.1 root 1508: } 1509: LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) 1510: 1511: LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) 1512: { 1513: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1514: emit_byte(0xd1); ! 1515: emit_byte(0xc0+r); 1.1 root 1516: } 1517: else { 1.1.1.2 ! root 1518: emit_byte(0xc1); ! 1519: emit_byte(0xc0+r); ! 1520: emit_byte(i); 1.1 root 1521: } 1522: } 1523: LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) 1524: 1525: LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) 1526: { 1.1.1.2 ! root 1527: emit_byte(0xd3); ! 1528: emit_byte(0xc0+d); 1.1 root 1529: } 1530: LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) 1531: 1532: LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) 1533: { 1.1.1.2 ! root 1534: emit_byte(0x66); ! 1535: emit_byte(0xd3); ! 1536: emit_byte(0xc0+d); 1.1 root 1537: } 1538: LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) 1539: 1540: LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) 1541: { 1.1.1.2 ! root 1542: emit_byte(0xd2); ! 1543: emit_byte(0xc0+d); 1.1 root 1544: } 1545: LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) 1546: 1547: LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) 1548: { 1.1.1.2 ! root 1549: emit_byte(0xd3); ! 1550: emit_byte(0xe0+d); 1.1 root 1551: } 1552: LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) 1553: 1554: LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) 1555: { 1.1.1.2 ! root 1556: emit_byte(0x66); ! 1557: emit_byte(0xd3); ! 1558: emit_byte(0xe0+d); 1.1 root 1559: } 1560: LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) 1561: 1562: LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) 1563: { 1.1.1.2 ! root 1564: emit_byte(0xd2); ! 1565: emit_byte(0xe0+d); 1.1 root 1566: } 1567: LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) 1568: 1569: LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) 1570: { 1571: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1572: emit_byte(0xd0); ! 1573: emit_byte(0xc8+r); 1.1 root 1574: } 1575: else { 1.1.1.2 ! root 1576: emit_byte(0xc0); ! 1577: emit_byte(0xc8+r); ! 1578: emit_byte(i); 1.1 root 1579: } 1580: } 1581: LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) 1582: 1583: LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) 1584: { 1.1.1.2 ! root 1585: emit_byte(0x66); ! 1586: emit_byte(0xc1); ! 1587: emit_byte(0xc8+r); ! 1588: emit_byte(i); 1.1 root 1589: } 1590: LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) 1591: 1592: // gb-- used for making an fpcr value in compemu_fpp.cpp 1593: LOWFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) 1594: { 1595: emit_byte(0x0b); 1596: emit_byte(0x05+8*d); 1597: emit_long(s); 1598: } 1599: LENDFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) 1600: 1601: LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) 1602: { 1603: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1604: emit_byte(0xd1); ! 1605: emit_byte(0xc8+r); 1.1 root 1606: } 1607: else { 1.1.1.2 ! root 1608: emit_byte(0xc1); ! 1609: emit_byte(0xc8+r); ! 1610: emit_byte(i); 1.1 root 1611: } 1612: } 1613: LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) 1614: 1615: LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) 1616: { 1.1.1.2 ! root 1617: emit_byte(0xd3); ! 1618: emit_byte(0xc8+d); 1.1 root 1619: } 1620: LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) 1621: 1622: LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) 1623: { 1.1.1.2 ! root 1624: emit_byte(0x66); ! 1625: emit_byte(0xd3); ! 1626: emit_byte(0xc8+d); 1.1 root 1627: } 1628: LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) 1629: 1630: LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) 1631: { 1.1.1.2 ! root 1632: emit_byte(0xd2); ! 1633: emit_byte(0xc8+d); 1.1 root 1634: } 1635: LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) 1636: 1637: LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) 1638: { 1.1.1.2 ! root 1639: emit_byte(0xd3); ! 1640: emit_byte(0xe8+d); 1.1 root 1641: } 1642: LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) 1643: 1644: LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) 1645: { 1.1.1.2 ! root 1646: emit_byte(0x66); ! 1647: emit_byte(0xd3); ! 1648: emit_byte(0xe8+d); 1.1 root 1649: } 1650: LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) 1651: 1652: LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) 1653: { 1.1.1.2 ! root 1654: emit_byte(0xd2); ! 1655: emit_byte(0xe8+d); 1.1 root 1656: } 1657: LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) 1658: 1659: LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) 1660: { 1.1.1.2 ! root 1661: emit_byte(0xd3); ! 1662: emit_byte(0xf8+d); 1.1 root 1663: } 1664: LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) 1665: 1666: LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) 1667: { 1.1.1.2 ! root 1668: emit_byte(0x66); ! 1669: emit_byte(0xd3); ! 1670: emit_byte(0xf8+d); 1.1 root 1671: } 1672: LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) 1673: 1674: LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) 1675: { 1.1.1.2 ! root 1676: emit_byte(0xd2); ! 1677: emit_byte(0xf8+d); 1.1 root 1678: } 1679: LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) 1680: 1681: LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) 1682: { 1683: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1684: emit_byte(0xd1); ! 1685: emit_byte(0xe0+r); 1.1 root 1686: } 1687: else { 1.1.1.2 ! root 1688: emit_byte(0xc1); ! 1689: emit_byte(0xe0+r); ! 1690: emit_byte(i); 1.1 root 1691: } 1692: } 1693: LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) 1694: 1695: LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) 1696: { 1.1.1.2 ! root 1697: emit_byte(0x66); ! 1698: emit_byte(0xc1); ! 1699: emit_byte(0xe0+r); ! 1700: emit_byte(i); 1.1 root 1701: } 1702: LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) 1703: 1704: LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) 1705: { 1706: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1707: emit_byte(0xd0); ! 1708: emit_byte(0xe0+r); 1.1 root 1709: } 1710: else { 1.1.1.2 ! root 1711: emit_byte(0xc0); ! 1712: emit_byte(0xe0+r); ! 1713: emit_byte(i); 1.1 root 1714: } 1715: } 1716: LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) 1717: 1718: LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) 1719: { 1720: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1721: emit_byte(0xd1); ! 1722: emit_byte(0xe8+r); 1.1 root 1723: } 1724: else { 1.1.1.2 ! root 1725: emit_byte(0xc1); ! 1726: emit_byte(0xe8+r); ! 1727: emit_byte(i); 1.1 root 1728: } 1729: } 1730: LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) 1731: 1732: LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) 1733: { 1.1.1.2 ! root 1734: emit_byte(0x66); ! 1735: emit_byte(0xc1); ! 1736: emit_byte(0xe8+r); ! 1737: emit_byte(i); 1.1 root 1738: } 1739: LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) 1740: 1741: LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) 1742: { 1743: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1744: emit_byte(0xd0); ! 1745: emit_byte(0xe8+r); 1.1 root 1746: } 1747: else { 1.1.1.2 ! root 1748: emit_byte(0xc0); ! 1749: emit_byte(0xe8+r); ! 1750: emit_byte(i); 1.1 root 1751: } 1752: } 1753: LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) 1754: 1755: LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) 1756: { 1757: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1758: emit_byte(0xd1); ! 1759: emit_byte(0xf8+r); 1.1 root 1760: } 1761: else { 1.1.1.2 ! root 1762: emit_byte(0xc1); ! 1763: emit_byte(0xf8+r); ! 1764: emit_byte(i); 1.1 root 1765: } 1766: } 1767: LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) 1768: 1769: LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) 1770: { 1.1.1.2 ! root 1771: emit_byte(0x66); ! 1772: emit_byte(0xc1); ! 1773: emit_byte(0xf8+r); ! 1774: emit_byte(i); 1.1 root 1775: } 1776: LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) 1777: 1778: LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) 1779: { 1780: if (optimize_shift_once && (i == 1)) { 1.1.1.2 ! root 1781: emit_byte(0xd0); ! 1782: emit_byte(0xf8+r); 1.1 root 1783: } 1784: else { 1.1.1.2 ! root 1785: emit_byte(0xc0); ! 1786: emit_byte(0xf8+r); ! 1787: emit_byte(i); 1.1 root 1788: } 1789: } 1790: LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) 1791: 1792: LOWFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) 1793: { 1.1.1.2 ! root 1794: emit_byte(0x9e); 1.1 root 1795: } 1796: LENDFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) 1797: 1798: LOWFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) 1799: { 1.1.1.2 ! root 1800: emit_byte(0x0f); ! 1801: emit_byte(0xa2); 1.1 root 1802: } 1803: LENDFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) 1804: 1805: LOWFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) 1806: { 1.1.1.2 ! root 1807: emit_byte(0x9f); 1.1 root 1808: } 1809: LENDFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) 1810: 1811: LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) 1812: { 1.1.1.2 ! root 1813: emit_byte(0x0f); ! 1814: emit_byte(0x90+cc); ! 1815: emit_byte(0xc0+d); 1.1 root 1816: } 1817: LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) 1818: 1819: LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) 1820: { 1821: emit_byte(0x0f); 1.1.1.2 ! root 1822: emit_byte(0x90+cc); ! 1823: emit_byte(0x05); ! 1824: emit_long(d); 1.1 root 1825: } 1.1.1.2 ! root 1826: LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) 1.1 root 1827: 1828: LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) 1829: { 1.1.1.2 ! root 1830: if (have_cmov) { ! 1831: emit_byte(0x0f); ! 1832: emit_byte(0x40+cc); ! 1833: emit_byte(0xc0+8*d+s); ! 1834: } ! 1835: else { /* replacement using branch and mov */ ! 1836: int uncc=(cc^1); ! 1837: emit_byte(0x70+uncc); ! 1838: emit_byte(2); /* skip next 2 bytes if not cc=true */ ! 1839: emit_byte(0x89); ! 1840: emit_byte(0xc0+8*s+d); ! 1841: } 1.1 root 1842: } 1843: LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) 1844: 1845: LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) 1846: { 1.1.1.2 ! root 1847: emit_byte(0x0f); ! 1848: emit_byte(0xbc); ! 1849: emit_byte(0xc0+8*d+s); 1.1 root 1850: } 1851: LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) 1852: 1853: LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) 1854: { 1.1.1.2 ! root 1855: emit_byte(0x0f); ! 1856: emit_byte(0xbf); ! 1857: emit_byte(0xc0+8*d+s); 1.1 root 1858: } 1859: LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) 1860: 1861: LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) 1862: { 1.1.1.2 ! root 1863: emit_byte(0x0f); ! 1864: emit_byte(0xbe); ! 1865: emit_byte(0xc0+8*d+s); 1.1 root 1866: } 1867: LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) 1868: 1869: LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) 1870: { 1.1.1.2 ! root 1871: emit_byte(0x0f); ! 1872: emit_byte(0xb7); ! 1873: emit_byte(0xc0+8*d+s); 1.1 root 1874: } 1875: LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) 1876: 1877: LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) 1878: { 1.1.1.2 ! root 1879: emit_byte(0x0f); ! 1880: emit_byte(0xb6); ! 1881: emit_byte(0xc0+8*d+s); 1.1 root 1882: } 1883: LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) 1884: 1885: LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) 1886: { 1.1.1.2 ! root 1887: emit_byte(0x0f); ! 1888: emit_byte(0xaf); ! 1889: emit_byte(0xc0+8*d+s); 1.1 root 1890: } 1891: LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) 1892: 1893: LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) 1894: { 1.1.1.2 ! root 1895: if (d!=MUL_NREG1 || s!=MUL_NREG2) { ! 1896: jit_abort("Bad register in IMUL: d=%d, s=%d\n",d,s); ! 1897: } ! 1898: emit_byte(0xf7); ! 1899: emit_byte(0xea); 1.1 root 1900: } 1901: LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) 1902: 1903: LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) 1904: { 1.1.1.2 ! root 1905: if (d!=MUL_NREG1 || s!=MUL_NREG2) { ! 1906: jit_abort("Bad register in MUL: d=%d, s=%d",d,s); ! 1907: } ! 1908: emit_byte(0xf7); ! 1909: emit_byte(0xe2); 1.1 root 1910: } 1911: LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) 1912: 1913: LOWFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) 1914: { 1915: abort(); /* %^$&%^$%#^ x86! */ 1916: emit_byte(0x0f); 1917: emit_byte(0xaf); 1918: emit_byte(0xc0+8*d+s); 1919: } 1920: LENDFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) 1921: 1922: LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) 1923: { 1.1.1.2 ! root 1924: emit_byte(0x88); ! 1925: emit_byte(0xc0+8*s+d); 1.1 root 1926: } 1927: LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) 1928: 1929: LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) 1930: { 1.1.1.2 ! root 1931: emit_byte(0x66); ! 1932: emit_byte(0x89); ! 1933: emit_byte(0xc0+8*s+d); 1.1 root 1934: } 1935: LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) 1936: 1937: LOWFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) 1938: { 1.1.1.2 ! root 1939: int isebp=(baser==5)?0x40:0; ! 1940: int fi; 1.1 root 1941: 1.1.1.2 ! root 1942: switch(factor) { ! 1943: case 1: fi=0; break; ! 1944: case 2: fi=1; break; ! 1945: case 4: fi=2; break; ! 1946: case 8: fi=3; break; ! 1947: default: abort(); ! 1948: } 1.1 root 1949: 1.1.1.2 ! root 1950: ! 1951: emit_byte(0x8b); ! 1952: emit_byte(0x04+8*d+isebp); ! 1953: emit_byte(baser+8*index+0x40*fi); ! 1954: if (isebp) ! 1955: emit_byte(0x00); 1.1 root 1956: } 1957: LENDFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) 1958: 1959: LOWFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) 1960: { 1.1.1.2 ! root 1961: int fi; ! 1962: int isebp; ! 1963: ! 1964: switch(factor) { ! 1965: case 1: fi=0; break; ! 1966: case 2: fi=1; break; ! 1967: case 4: fi=2; break; ! 1968: case 8: fi=3; break; ! 1969: default: abort(); ! 1970: } ! 1971: isebp=(baser==5)?0x40:0; ! 1972: ! 1973: emit_byte(0x66); ! 1974: emit_byte(0x8b); ! 1975: emit_byte(0x04+8*d+isebp); ! 1976: emit_byte(baser+8*index+0x40*fi); ! 1977: if (isebp) ! 1978: emit_byte(0x00); ! 1979: } 1.1 root 1980: LENDFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) 1981: 1982: LOWFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) 1983: { 1.1.1.2 ! root 1984: int fi; ! 1985: int isebp; 1.1 root 1986: 1.1.1.2 ! root 1987: switch(factor) { ! 1988: case 1: fi=0; break; ! 1989: case 2: fi=1; break; ! 1990: case 4: fi=2; break; ! 1991: case 8: fi=3; break; ! 1992: default: abort(); ! 1993: } ! 1994: isebp=(baser==5)?0x40:0; ! 1995: ! 1996: emit_byte(0x8a); ! 1997: emit_byte(0x04+8*d+isebp); ! 1998: emit_byte(baser+8*index+0x40*fi); ! 1999: if (isebp) ! 2000: emit_byte(0x00); 1.1 root 2001: } 2002: LENDFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) 2003: 2004: LOWFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) 2005: { 1.1.1.2 ! root 2006: int fi; ! 2007: int isebp; 1.1 root 2008: 1.1.1.2 ! root 2009: switch(factor) { ! 2010: case 1: fi=0; break; ! 2011: case 2: fi=1; break; ! 2012: case 4: fi=2; break; ! 2013: case 8: fi=3; break; ! 2014: default: abort(); ! 2015: } 1.1 root 2016: 2017: 1.1.1.2 ! root 2018: isebp=(baser==5)?0x40:0; ! 2019: ! 2020: emit_byte(0x89); ! 2021: emit_byte(0x04+8*s+isebp); ! 2022: emit_byte(baser+8*index+0x40*fi); ! 2023: if (isebp) ! 2024: emit_byte(0x00); 1.1 root 2025: } 2026: LENDFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) 2027: 2028: LOWFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) 2029: { 1.1.1.2 ! root 2030: int fi; ! 2031: int isebp; 1.1 root 2032: 1.1.1.2 ! root 2033: switch(factor) { ! 2034: case 1: fi=0; break; ! 2035: case 2: fi=1; break; ! 2036: case 4: fi=2; break; ! 2037: case 8: fi=3; break; ! 2038: default: abort(); ! 2039: } ! 2040: isebp=(baser==5)?0x40:0; 1.1 root 2041: 1.1.1.2 ! root 2042: emit_byte(0x66); ! 2043: emit_byte(0x89); ! 2044: emit_byte(0x04+8*s+isebp); ! 2045: emit_byte(baser+8*index+0x40*fi); ! 2046: if (isebp) ! 2047: emit_byte(0x00); 1.1 root 2048: } 2049: LENDFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) 2050: 2051: LOWFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) 2052: { 1.1.1.2 ! root 2053: int fi; ! 2054: int isebp; 1.1 root 2055: 1.1.1.2 ! root 2056: switch(factor) { ! 2057: case 1: fi=0; break; ! 2058: case 2: fi=1; break; ! 2059: case 4: fi=2; break; ! 2060: case 8: fi=3; break; ! 2061: default: abort(); ! 2062: } ! 2063: isebp=(baser==5)?0x40:0; ! 2064: ! 2065: emit_byte(0x88); ! 2066: emit_byte(0x04+8*s+isebp); ! 2067: emit_byte(baser+8*index+0x40*fi); ! 2068: if (isebp) ! 2069: emit_byte(0x00); 1.1 root 2070: } 2071: LENDFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) 2072: 2073: LOWFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) 2074: { 1.1.1.2 ! root 2075: int fi; 1.1 root 2076: 1.1.1.2 ! root 2077: switch(factor) { ! 2078: case 1: fi=0; break; ! 2079: case 2: fi=1; break; ! 2080: case 4: fi=2; break; ! 2081: case 8: fi=3; break; ! 2082: default: abort(); ! 2083: } 1.1 root 2084: 1.1.1.2 ! root 2085: emit_byte(0x89); ! 2086: emit_byte(0x84+8*s); ! 2087: emit_byte(baser+8*index+0x40*fi); ! 2088: emit_long(base); 1.1 root 2089: } 2090: LENDFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) 2091: 2092: LOWFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) 2093: { 1.1.1.2 ! root 2094: int fi; 1.1 root 2095: 1.1.1.2 ! root 2096: switch(factor) { ! 2097: case 1: fi=0; break; ! 2098: case 2: fi=1; break; ! 2099: case 4: fi=2; break; ! 2100: case 8: fi=3; break; ! 2101: default: abort(); ! 2102: } 1.1 root 2103: 1.1.1.2 ! root 2104: emit_byte(0x66); ! 2105: emit_byte(0x89); ! 2106: emit_byte(0x84+8*s); ! 2107: emit_byte(baser+8*index+0x40*fi); ! 2108: emit_long(base); 1.1 root 2109: } 2110: LENDFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) 2111: 2112: LOWFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) 2113: { 1.1.1.2 ! root 2114: int fi; 1.1 root 2115: 1.1.1.2 ! root 2116: switch(factor) { ! 2117: case 1: fi=0; break; ! 2118: case 2: fi=1; break; ! 2119: case 4: fi=2; break; ! 2120: case 8: fi=3; break; ! 2121: default: abort(); ! 2122: } 1.1 root 2123: 1.1.1.2 ! root 2124: emit_byte(0x88); ! 2125: emit_byte(0x84+8*s); ! 2126: emit_byte(baser+8*index+0x40*fi); ! 2127: emit_long(base); ! 2128: } 1.1 root 2129: LENDFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) 2130: 2131: LOWFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) 2132: { 1.1.1.2 ! root 2133: int fi; 1.1 root 2134: 1.1.1.2 ! root 2135: switch(factor) { ! 2136: case 1: fi=0; break; ! 2137: case 2: fi=1; break; ! 2138: case 4: fi=2; break; ! 2139: case 8: fi=3; break; ! 2140: default: abort(); ! 2141: } 1.1 root 2142: 1.1.1.2 ! root 2143: emit_byte(0x8b); ! 2144: emit_byte(0x84+8*d); ! 2145: emit_byte(baser+8*index+0x40*fi); ! 2146: emit_long(base); 1.1 root 2147: } 2148: LENDFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) 2149: 2150: LOWFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) 2151: { 1.1.1.2 ! root 2152: int fi; 1.1 root 2153: 1.1.1.2 ! root 2154: switch(factor) { ! 2155: case 1: fi=0; break; ! 2156: case 2: fi=1; break; ! 2157: case 4: fi=2; break; ! 2158: case 8: fi=3; break; ! 2159: default: abort(); ! 2160: } 1.1 root 2161: 1.1.1.2 ! root 2162: emit_byte(0x66); ! 2163: emit_byte(0x8b); ! 2164: emit_byte(0x84+8*d); ! 2165: emit_byte(baser+8*index+0x40*fi); ! 2166: emit_long(base); 1.1 root 2167: } 2168: LENDFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) 2169: 2170: LOWFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) 2171: { 1.1.1.2 ! root 2172: int fi; 1.1 root 2173: 1.1.1.2 ! root 2174: switch(factor) { ! 2175: case 1: fi=0; break; ! 2176: case 2: fi=1; break; ! 2177: case 4: fi=2; break; ! 2178: case 8: fi=3; break; ! 2179: default: abort(); ! 2180: } 1.1 root 2181: 1.1.1.2 ! root 2182: emit_byte(0x8a); ! 2183: emit_byte(0x84+8*d); ! 2184: emit_byte(baser+8*index+0x40*fi); ! 2185: emit_long(base); 1.1 root 2186: } 2187: LENDFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) 2188: 2189: LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) 2190: { 1.1.1.2 ! root 2191: int fi; ! 2192: switch(factor) { ! 2193: case 1: fi=0; break; ! 2194: case 2: fi=1; break; ! 2195: case 4: fi=2; break; ! 2196: case 8: fi=3; break; ! 2197: default: ! 2198: fprintf(stderr,"Bad factor %d in mov_l_rm_indexed!\n",factor); ! 2199: abort(); ! 2200: } ! 2201: emit_byte(0x8b); ! 2202: emit_byte(0x04+8*d); ! 2203: emit_byte(0x05+8*index+64*fi); ! 2204: emit_long(base); 1.1 root 2205: } 2206: LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) 2207: 2208: LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) 2209: { 1.1.1.2 ! root 2210: int fi; ! 2211: switch(factor) { ! 2212: case 1: fi=0; break; ! 2213: case 2: fi=1; break; ! 2214: case 4: fi=2; break; ! 2215: case 8: fi=3; break; ! 2216: default: ! 2217: fprintf(stderr,"Bad factor %d in mov_l_rm_indexed!\n",factor); ! 2218: abort(); ! 2219: } ! 2220: if (have_cmov) { ! 2221: emit_byte(0x0f); ! 2222: emit_byte(0x40+cond); ! 2223: emit_byte(0x04+8*d); ! 2224: emit_byte(0x05+8*index+64*fi); ! 2225: emit_long(base); ! 2226: } ! 2227: else { /* replacement using branch and mov */ ! 2228: int uncc=(cond^1); ! 2229: emit_byte(0x70+uncc); ! 2230: emit_byte(7); /* skip next 7 bytes if not cc=true */ ! 2231: emit_byte(0x8b); ! 2232: emit_byte(0x04+8*d); ! 2233: emit_byte(0x05+8*index+64*fi); ! 2234: emit_long(base); ! 2235: } 1.1 root 2236: } 2237: LENDFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) 2238: 2239: LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) 2240: { 1.1.1.2 ! root 2241: if (have_cmov) { ! 2242: emit_byte(0x0f); ! 2243: emit_byte(0x40+cond); ! 2244: emit_byte(0x05+8*d); ! 2245: emit_long(mem); ! 2246: } ! 2247: else { /* replacement using branch and mov */ ! 2248: int uncc=(cond^1); ! 2249: emit_byte(0x70+uncc); ! 2250: emit_byte(6); /* skip next 6 bytes if not cc=true */ ! 2251: emit_byte(0x8b); ! 2252: emit_byte(0x05+8*d); ! 2253: emit_long(mem); ! 2254: } 1.1 root 2255: } 2256: LENDFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) 2257: 2258: LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) 2259: { 2260: Dif(!isbyte(offset)) abort(); 1.1.1.2 ! root 2261: emit_byte(0x8b); ! 2262: emit_byte(0x40+8*d+s); ! 2263: emit_byte(offset); 1.1 root 2264: } 2265: LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) 2266: 2267: LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) 2268: { 2269: Dif(!isbyte(offset)) abort(); 1.1.1.2 ! root 2270: emit_byte(0x66); ! 2271: emit_byte(0x8b); ! 2272: emit_byte(0x40+8*d+s); ! 2273: emit_byte(offset); 1.1 root 2274: } 2275: LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) 2276: 2277: LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) 2278: { 2279: Dif(!isbyte(offset)) abort(); 1.1.1.2 ! root 2280: emit_byte(0x8a); ! 2281: emit_byte(0x40+8*d+s); ! 2282: emit_byte(offset); 1.1 root 2283: } 2284: LENDFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) 2285: 2286: LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) 2287: { 1.1.1.2 ! root 2288: emit_byte(0x8b); ! 2289: emit_byte(0x80+8*d+s); ! 2290: emit_long(offset); 1.1 root 2291: } 2292: LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) 2293: 2294: LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) 2295: { 1.1.1.2 ! root 2296: emit_byte(0x66); ! 2297: emit_byte(0x8b); ! 2298: emit_byte(0x80+8*d+s); ! 2299: emit_long(offset); 1.1 root 2300: } 2301: LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) 2302: 2303: LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) 2304: { 1.1.1.2 ! root 2305: emit_byte(0x8a); ! 2306: emit_byte(0x80+8*d+s); ! 2307: emit_long(offset); 1.1 root 2308: } 2309: LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) 2310: 2311: LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) 2312: { 2313: Dif(!isbyte(offset)) abort(); 1.1.1.2 ! root 2314: emit_byte(0xc7); ! 2315: emit_byte(0x40+d); ! 2316: emit_byte(offset); ! 2317: emit_long(i); 1.1 root 2318: } 2319: LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) 2320: 2321: LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) 2322: { 2323: Dif(!isbyte(offset)) abort(); 1.1.1.2 ! root 2324: emit_byte(0x66); ! 2325: emit_byte(0xc7); ! 2326: emit_byte(0x40+d); ! 2327: emit_byte(offset); ! 2328: emit_word(i); 1.1 root 2329: } 2330: LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) 2331: 2332: LOWFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) 2333: { 2334: Dif(!isbyte(offset)) abort(); 1.1.1.2 ! root 2335: emit_byte(0xc6); ! 2336: emit_byte(0x40+d); ! 2337: emit_byte(offset); ! 2338: emit_byte(i); 1.1 root 2339: } 2340: LENDFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) 2341: 2342: LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) 2343: { 2344: Dif(!isbyte(offset)) abort(); 1.1.1.2 ! root 2345: emit_byte(0x89); ! 2346: emit_byte(0x40+8*s+d); ! 2347: emit_byte(offset); 1.1 root 2348: } 2349: LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) 2350: 2351: LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) 2352: { 2353: Dif(!isbyte(offset)) abort(); 1.1.1.2 ! root 2354: emit_byte(0x66); ! 2355: emit_byte(0x89); ! 2356: emit_byte(0x40+8*s+d); ! 2357: emit_byte(offset); 1.1 root 2358: } 2359: LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) 2360: 2361: LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) 2362: { 2363: Dif(!isbyte(offset)) abort(); 1.1.1.2 ! root 2364: emit_byte(0x88); ! 2365: emit_byte(0x40+8*s+d); ! 2366: emit_byte(offset); 1.1 root 2367: } 2368: LENDFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) 2369: 2370: LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) 2371: { 2372: if (optimize_imm8 && isbyte(offset)) { 1.1.1.2 ! root 2373: emit_byte(0x8d); ! 2374: emit_byte(0x40+8*d+s); ! 2375: emit_byte(offset); 1.1 root 2376: } 2377: else { 1.1.1.2 ! root 2378: emit_byte(0x8d); ! 2379: emit_byte(0x80+8*d+s); ! 2380: emit_long(offset); 1.1 root 2381: } 2382: } 2383: LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) 2384: 2385: LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) 2386: { 1.1.1.2 ! root 2387: int fi; 1.1 root 2388: 1.1.1.2 ! root 2389: switch(factor) { ! 2390: case 1: fi=0; break; ! 2391: case 2: fi=1; break; ! 2392: case 4: fi=2; break; ! 2393: case 8: fi=3; break; ! 2394: default: abort(); ! 2395: } 1.1 root 2396: 2397: if (optimize_imm8 && isbyte(offset)) { 1.1.1.2 ! root 2398: emit_byte(0x8d); ! 2399: emit_byte(0x44+8*d); ! 2400: emit_byte(0x40*fi+8*index+s); ! 2401: emit_byte(offset); 1.1 root 2402: } 2403: else { 1.1.1.2 ! root 2404: emit_byte(0x8d); ! 2405: emit_byte(0x84+8*d); ! 2406: emit_byte(0x40*fi+8*index+s); ! 2407: emit_long(offset); 1.1 root 2408: } 2409: } 2410: LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) 2411: 2412: LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) 2413: { 1.1.1.2 ! root 2414: int isebp=(s==5)?0x40:0; ! 2415: int fi; 1.1 root 2416: 1.1.1.2 ! root 2417: switch(factor) { ! 2418: case 1: fi=0; break; ! 2419: case 2: fi=1; break; ! 2420: case 4: fi=2; break; ! 2421: case 8: fi=3; break; ! 2422: default: abort(); ! 2423: } 1.1 root 2424: 1.1.1.2 ! root 2425: emit_byte(0x8d); ! 2426: emit_byte(0x04+8*d+isebp); ! 2427: emit_byte(0x40*fi+8*index+s); ! 2428: if (isebp) ! 2429: emit_byte(0); 1.1 root 2430: } 2431: LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) 2432: 2433: LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) 2434: { 2435: if (optimize_imm8 && isbyte(offset)) { 1.1.1.2 ! root 2436: emit_byte(0x89); ! 2437: emit_byte(0x40+8*s+d); ! 2438: emit_byte(offset); 1.1 root 2439: } 2440: else { 1.1.1.2 ! root 2441: emit_byte(0x89); ! 2442: emit_byte(0x80+8*s+d); ! 2443: emit_long(offset); 1.1 root 2444: } 2445: } 2446: LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) 2447: 2448: LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) 2449: { 1.1.1.2 ! root 2450: emit_byte(0x66); ! 2451: emit_byte(0x89); ! 2452: emit_byte(0x80+8*s+d); ! 2453: emit_long(offset); 1.1 root 2454: } 2455: LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) 2456: 2457: LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) 2458: { 2459: if (optimize_imm8 && isbyte(offset)) { 1.1.1.2 ! root 2460: emit_byte(0x88); ! 2461: emit_byte(0x40+8*s+d); ! 2462: emit_byte(offset); 1.1 root 2463: } 2464: else { 1.1.1.2 ! root 2465: emit_byte(0x88); ! 2466: emit_byte(0x80+8*s+d); ! 2467: emit_long(offset); 1.1 root 2468: } 2469: } 2470: LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) 2471: 2472: LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) 2473: { 1.1.1.2 ! root 2474: emit_byte(0x0f); ! 2475: emit_byte(0xc8+r); 1.1 root 2476: } 2477: LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) 2478: 2479: LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) 2480: { 1.1.1.2 ! root 2481: emit_byte(0x66); ! 2482: emit_byte(0xc1); ! 2483: emit_byte(0xc0+r); ! 2484: emit_byte(0x08); 1.1 root 2485: } 2486: LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) 2487: 2488: LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) 2489: { 1.1.1.2 ! root 2490: emit_byte(0x89); ! 2491: emit_byte(0xc0+8*s+d); 1.1 root 2492: } 2493: LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) 2494: 2495: LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) 2496: { 1.1.1.2 ! root 2497: emit_byte(0x89); ! 2498: emit_byte(0x05+8*s); ! 2499: emit_long(d); 1.1 root 2500: } 2501: LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) 2502: 2503: LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) 2504: { 1.1.1.2 ! root 2505: emit_byte(0x66); ! 2506: emit_byte(0x89); ! 2507: emit_byte(0x05+8*s); ! 2508: emit_long(d); 1.1 root 2509: } 2510: LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) 2511: 2512: LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) 2513: { 1.1.1.2 ! root 2514: emit_byte(0x66); ! 2515: emit_byte(0x8b); ! 2516: emit_byte(0x05+8*d); ! 2517: emit_long(s); 1.1 root 2518: } 2519: LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) 2520: 2521: LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) 2522: { 1.1.1.2 ! root 2523: emit_byte(0x88); ! 2524: emit_byte(0x05+8*(s&0xf)); /* XXX this handles %ah case (defined as 0x10+4) and others */ ! 2525: emit_long(d); 1.1 root 2526: } 2527: LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) 2528: 2529: LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) 2530: { 1.1.1.2 ! root 2531: emit_byte(0x8a); ! 2532: emit_byte(0x05+8*d); ! 2533: emit_long(s); 1.1 root 2534: } 2535: LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) 2536: 2537: LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) 2538: { 1.1.1.2 ! root 2539: emit_byte(0xb8+d); ! 2540: emit_long(s); 1.1 root 2541: } 2542: LENDFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) 2543: 2544: LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) 2545: { 1.1.1.2 ! root 2546: emit_byte(0x66); ! 2547: emit_byte(0xb8+d); ! 2548: emit_word(s); 1.1 root 2549: } 2550: LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) 2551: 2552: LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) 2553: { 1.1.1.2 ! root 2554: emit_byte(0xb0+d); ! 2555: emit_byte(s); 1.1 root 2556: } 2557: LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) 2558: 2559: LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) 2560: { 1.1.1.2 ! root 2561: emit_byte(0x81); ! 2562: emit_byte(0x15); ! 2563: emit_long(d); ! 2564: emit_long(s); 1.1 root 2565: } 2566: LENDFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) 2567: 1.1.1.2 ! root 2568: LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) 1.1 root 2569: { 2570: if (optimize_imm8 && isbyte(s)) { 1.1.1.2 ! root 2571: emit_byte(0x83); ! 2572: emit_byte(0x05); ! 2573: emit_long(d); ! 2574: emit_byte(s); 1.1 root 2575: } 2576: else { 1.1.1.2 ! root 2577: emit_byte(0x81); ! 2578: emit_byte(0x05); ! 2579: emit_long(d); ! 2580: emit_long(s); 1.1 root 2581: } 2582: } 1.1.1.2 ! root 2583: LENDFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) 1.1 root 2584: 1.1.1.2 ! root 2585: LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) 1.1 root 2586: { 1.1.1.2 ! root 2587: emit_byte(0x66); ! 2588: emit_byte(0x81); ! 2589: emit_byte(0x05); ! 2590: emit_long(d); ! 2591: emit_word(s); 1.1 root 2592: } 1.1.1.2 ! root 2593: LENDFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) 1.1 root 2594: 1.1.1.2 ! root 2595: LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) 1.1 root 2596: { 1.1.1.2 ! root 2597: emit_byte(0x80); ! 2598: emit_byte(0x05); ! 2599: emit_long(d); ! 2600: emit_byte(s); 1.1 root 2601: } 1.1.1.2 ! root 2602: LENDFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) 1.1 root 2603: 2604: LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) 2605: { 2606: if (optimize_accum && isaccum(d)) 1.1.1.2 ! root 2607: emit_byte(0xa9); 1.1 root 2608: else { 1.1.1.2 ! root 2609: emit_byte(0xf7); ! 2610: emit_byte(0xc0+d); 1.1 root 2611: } 1.1.1.2 ! root 2612: emit_long(i); 1.1 root 2613: } 2614: LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) 2615: 2616: LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) 2617: { 1.1.1.2 ! root 2618: emit_byte(0x85); ! 2619: emit_byte(0xc0+8*s+d); 1.1 root 2620: } 2621: LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) 2622: 2623: LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) 2624: { 1.1.1.2 ! root 2625: emit_byte(0x66); ! 2626: emit_byte(0x85); ! 2627: emit_byte(0xc0+8*s+d); 1.1 root 2628: } 2629: LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) 2630: 2631: LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) 2632: { 1.1.1.2 ! root 2633: emit_byte(0x84); ! 2634: emit_byte(0xc0+8*s+d); 1.1 root 2635: } 2636: LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) 2637: 2638: LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) 2639: { 2640: emit_byte(0x81); 2641: emit_byte(0xf0+d); 2642: emit_long(i); 2643: } 2644: LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) 2645: 2646: LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) 2647: { 2648: if (optimize_imm8 && isbyte(i)) { 1.1.1.2 ! root 2649: emit_byte(0x83); ! 2650: emit_byte(0xe0+d); ! 2651: emit_byte(i); 1.1 root 2652: } 2653: else { 1.1.1.2 ! root 2654: if (optimize_accum && isaccum(d)) ! 2655: emit_byte(0x25); ! 2656: else { ! 2657: emit_byte(0x81); ! 2658: emit_byte(0xe0+d); ! 2659: } ! 2660: emit_long(i); 1.1 root 2661: } 2662: } 2663: LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) 2664: 2665: LOWFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) 2666: { 2667: emit_byte(0x66); 2668: if (optimize_imm8 && isbyte(i)) { 1.1.1.2 ! root 2669: emit_byte(0x83); ! 2670: emit_byte(0xe0+d); ! 2671: emit_byte(i); 1.1 root 2672: } 2673: else { 1.1.1.2 ! root 2674: if (optimize_accum && isaccum(d)) ! 2675: emit_byte(0x25); ! 2676: else { ! 2677: emit_byte(0x81); ! 2678: emit_byte(0xe0+d); ! 2679: } ! 2680: emit_word(i); 1.1 root 2681: } 2682: } 2683: LENDFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) 2684: 2685: LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) 2686: { 1.1.1.2 ! root 2687: emit_byte(0x21); ! 2688: emit_byte(0xc0+8*s+d); 1.1 root 2689: } 2690: LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) 2691: 2692: LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) 2693: { 1.1.1.2 ! root 2694: emit_byte(0x66); ! 2695: emit_byte(0x21); ! 2696: emit_byte(0xc0+8*s+d); 1.1 root 2697: } 2698: LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) 2699: 2700: LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) 2701: { 1.1.1.2 ! root 2702: emit_byte(0x20); ! 2703: emit_byte(0xc0+8*s+d); 1.1 root 2704: } 2705: LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) 2706: 2707: LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) 2708: { 2709: if (optimize_imm8 && isbyte(i)) { 1.1.1.2 ! root 2710: emit_byte(0x83); ! 2711: emit_byte(0xc8+d); ! 2712: emit_byte(i); 1.1 root 2713: } 2714: else { 1.1.1.2 ! root 2715: if (optimize_accum && isaccum(d)) ! 2716: emit_byte(0x0d); ! 2717: else { ! 2718: emit_byte(0x81); ! 2719: emit_byte(0xc8+d); 1.1 root 2720: } 1.1.1.2 ! root 2721: emit_long(i); 1.1 root 2722: } 2723: } 2724: LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) 2725: 2726: LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) 2727: { 1.1.1.2 ! root 2728: emit_byte(0x09); ! 2729: emit_byte(0xc0+8*s+d); 1.1 root 2730: } 2731: LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) 2732: 2733: LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) 2734: { 1.1.1.2 ! root 2735: emit_byte(0x66); ! 2736: emit_byte(0x09); ! 2737: emit_byte(0xc0+8*s+d); 1.1 root 2738: } 2739: LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) 2740: 2741: LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) 2742: { 1.1.1.2 ! root 2743: emit_byte(0x08); ! 2744: emit_byte(0xc0+8*s+d); 1.1 root 2745: } 2746: LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) 2747: 2748: LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) 2749: { 1.1.1.2 ! root 2750: emit_byte(0x11); ! 2751: emit_byte(0xc0+8*s+d); 1.1 root 2752: } 2753: LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) 2754: 2755: LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) 2756: { 1.1.1.2 ! root 2757: emit_byte(0x66); ! 2758: emit_byte(0x11); ! 2759: emit_byte(0xc0+8*s+d); 1.1 root 2760: } 2761: LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) 2762: 2763: LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) 2764: { 1.1.1.2 ! root 2765: emit_byte(0x10); ! 2766: emit_byte(0xc0+8*s+d); 1.1 root 2767: } 2768: LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) 2769: 2770: LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) 2771: { 1.1.1.2 ! root 2772: emit_byte(0x01); ! 2773: emit_byte(0xc0+8*s+d); 1.1 root 2774: } 2775: LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) 2776: 2777: LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) 2778: { 1.1.1.2 ! root 2779: emit_byte(0x66); ! 2780: emit_byte(0x01); ! 2781: emit_byte(0xc0+8*s+d); 1.1 root 2782: } 2783: LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) 2784: 2785: LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) 2786: { 1.1.1.2 ! root 2787: emit_byte(0x00); ! 2788: emit_byte(0xc0+8*s+d); 1.1 root 2789: } 2790: LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) 2791: 2792: LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) 2793: { 1.1.1.2 ! root 2794: if (isbyte(i)) { ! 2795: emit_byte(0x83); ! 2796: emit_byte(0xe8+d); ! 2797: emit_byte(i); ! 2798: } ! 2799: else { ! 2800: if (optimize_accum && isaccum(d)) ! 2801: emit_byte(0x2d); ! 2802: else { ! 2803: emit_byte(0x81); ! 2804: emit_byte(0xe8+d); ! 2805: } ! 2806: emit_long(i); ! 2807: } 1.1 root 2808: } 2809: LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) 2810: 2811: LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) 2812: { 2813: if (optimize_accum && isaccum(d)) 1.1.1.2 ! root 2814: emit_byte(0x2c); 1.1 root 2815: else { 1.1.1.2 ! root 2816: emit_byte(0x80); ! 2817: emit_byte(0xe8+d); 1.1 root 2818: } 1.1.1.2 ! root 2819: emit_byte(i); 1.1 root 2820: } 2821: LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) 2822: 2823: LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) 2824: { 1.1.1.2 ! root 2825: if (isbyte(i)) { ! 2826: emit_byte(0x83); ! 2827: emit_byte(0xc0+d); ! 2828: emit_byte(i); ! 2829: } 1.1 root 2830: else { 1.1.1.2 ! root 2831: if (optimize_accum && isaccum(d)) ! 2832: emit_byte(0x05); ! 2833: else { ! 2834: emit_byte(0x81); ! 2835: emit_byte(0xc0+d); ! 2836: } ! 2837: emit_long(i); 1.1 root 2838: } 2839: } 2840: LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) 2841: 2842: LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) 2843: { 2844: emit_byte(0x66); 1.1.1.2 ! root 2845: if (isbyte(i)) { ! 2846: emit_byte(0x83); ! 2847: emit_byte(0xc0+d); ! 2848: emit_byte(i); ! 2849: } 1.1 root 2850: else { 1.1.1.2 ! root 2851: if (optimize_accum && isaccum(d)) ! 2852: emit_byte(0x05); ! 2853: else { ! 2854: emit_byte(0x81); ! 2855: emit_byte(0xc0+d); ! 2856: } ! 2857: emit_word(i); 1.1 root 2858: } 2859: } 2860: LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) 2861: 2862: LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) 2863: { 2864: if (optimize_accum && isaccum(d)) 1.1.1.2 ! root 2865: emit_byte(0x04); 1.1 root 2866: else { 1.1.1.2 ! root 2867: emit_byte(0x80); ! 2868: emit_byte(0xc0+d); 1.1 root 2869: } 1.1.1.2 ! root 2870: emit_byte(i); 1.1 root 2871: } 2872: LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) 2873: 2874: LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) 2875: { 1.1.1.2 ! root 2876: emit_byte(0x19); ! 2877: emit_byte(0xc0+8*s+d); 1.1 root 2878: } 2879: LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) 2880: 2881: LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) 2882: { 1.1.1.2 ! root 2883: emit_byte(0x66); ! 2884: emit_byte(0x19); ! 2885: emit_byte(0xc0+8*s+d); 1.1 root 2886: } 2887: LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) 2888: 2889: LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) 2890: { 1.1.1.2 ! root 2891: emit_byte(0x18); ! 2892: emit_byte(0xc0+8*s+d); 1.1 root 2893: } 2894: LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) 2895: 2896: LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) 2897: { 1.1.1.2 ! root 2898: emit_byte(0x29); ! 2899: emit_byte(0xc0+8*s+d); 1.1 root 2900: } 2901: LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) 2902: 2903: LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) 2904: { 1.1.1.2 ! root 2905: emit_byte(0x66); ! 2906: emit_byte(0x29); ! 2907: emit_byte(0xc0+8*s+d); 1.1 root 2908: } 2909: LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) 2910: 2911: LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) 2912: { 1.1.1.2 ! root 2913: emit_byte(0x28); ! 2914: emit_byte(0xc0+8*s+d); 1.1 root 2915: } 2916: LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) 2917: 2918: LOWFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) 2919: { 1.1.1.2 ! root 2920: emit_byte(0x39); ! 2921: emit_byte(0xc0+8*s+d); 1.1 root 2922: } 2923: LENDFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) 2924: 2925: LOWFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) 2926: { 2927: if (optimize_imm8 && isbyte(i)) { 1.1.1.2 ! root 2928: emit_byte(0x83); ! 2929: emit_byte(0xf8+r); ! 2930: emit_byte(i); 1.1 root 2931: } 2932: else { 1.1.1.2 ! root 2933: if (optimize_accum && isaccum(r)) ! 2934: emit_byte(0x3d); ! 2935: else { ! 2936: emit_byte(0x81); ! 2937: emit_byte(0xf8+r); ! 2938: } ! 2939: emit_long(i); 1.1 root 2940: } 2941: } 2942: LENDFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) 2943: 2944: LOWFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) 2945: { 1.1.1.2 ! root 2946: emit_byte(0x66); ! 2947: emit_byte(0x39); ! 2948: emit_byte(0xc0+8*s+d); 1.1 root 2949: } 2950: LENDFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) 2951: 2952: LOWFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) 2953: { 2954: emit_byte(0x80); 2955: emit_byte(0x3d); 2956: emit_long(d); 2957: emit_byte(s); 2958: } 2959: LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) 2960: 2961: LOWFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) 2962: { 1.1.1.2 ! root 2963: if (optimize_accum && isaccum(d)) ! 2964: emit_byte(0x3c); ! 2965: else { ! 2966: emit_byte(0x80); ! 2967: emit_byte(0xf8+d); ! 2968: } ! 2969: emit_byte(i); 1.1 root 2970: } 2971: LENDFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) 2972: 2973: LOWFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) 2974: { 1.1.1.2 ! root 2975: emit_byte(0x38); ! 2976: emit_byte(0xc0+8*s+d); 1.1 root 2977: } 2978: LENDFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) 2979: 2980: LOWFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) 2981: { 2982: int fi; 2983: 2984: switch(factor) { 2985: case 1: fi=0; break; 2986: case 2: fi=1; break; 2987: case 4: fi=2; break; 2988: case 8: fi=3; break; 2989: default: abort(); 2990: } 2991: emit_byte(0x39); 2992: emit_byte(0x04+8*d); 2993: emit_byte(5+8*index+0x40*fi); 2994: emit_long(offset); 2995: } 2996: LENDFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) 2997: 2998: LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) 2999: { 1.1.1.2 ! root 3000: emit_byte(0x31); ! 3001: emit_byte(0xc0+8*s+d); 1.1 root 3002: } 3003: LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) 3004: 3005: LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) 3006: { 1.1.1.2 ! root 3007: emit_byte(0x66); ! 3008: emit_byte(0x31); ! 3009: emit_byte(0xc0+8*s+d); 1.1 root 3010: } 3011: LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) 3012: 3013: LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) 3014: { 1.1.1.2 ! root 3015: emit_byte(0x30); ! 3016: emit_byte(0xc0+8*s+d); 1.1 root 3017: } 3018: LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) 3019: 3020: LOWFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) 3021: { 3022: if (optimize_imm8 && isbyte(s)) { 1.1.1.2 ! root 3023: emit_byte(0x83); ! 3024: emit_byte(0x2d); ! 3025: emit_long(d); ! 3026: emit_byte(s); 1.1 root 3027: } 3028: else { 1.1.1.2 ! root 3029: emit_byte(0x81); ! 3030: emit_byte(0x2d); ! 3031: emit_long(d); ! 3032: emit_long(s); 1.1 root 3033: } 3034: } 3035: LENDFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) 3036: 3037: LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) 3038: { 3039: if (optimize_imm8 && isbyte(s)) { 1.1.1.2 ! root 3040: emit_byte(0x83); ! 3041: emit_byte(0x3d); ! 3042: emit_long(d); ! 3043: emit_byte(s); 1.1 root 3044: } 3045: else { 1.1.1.2 ! root 3046: emit_byte(0x81); ! 3047: emit_byte(0x3d); ! 3048: emit_long(d); ! 3049: emit_long(s); 1.1 root 3050: } 3051: } 3052: LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) 3053: 3054: LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) 3055: { 1.1.1.2 ! root 3056: emit_byte(0x87); ! 3057: emit_byte(0xc0+8*r1+r2); 1.1 root 3058: } 3059: LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) 3060: 3061: LOWFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) 3062: { 3063: emit_byte(0x86); 3064: emit_byte(0xc0+8*(r1&0xf)+(r2&0xf)); /* XXX this handles upper-halves registers (e.g. %ah defined as 0x10+4) */ 3065: } 3066: LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) 3067: 3068: /************************************************************************* 3069: * FIXME: mem access modes probably wrong * 3070: *************************************************************************/ 3071: 3072: LOWFUNC(READ,WRITE,0,raw_pushfl,(void)) 3073: { 3074: emit_byte(0x9c); 3075: } 3076: LENDFUNC(READ,WRITE,0,raw_pushfl,(void)) 3077: 3078: LOWFUNC(WRITE,READ,0,raw_popfl,(void)) 3079: { 3080: emit_byte(0x9d); 3081: } 3082: LENDFUNC(WRITE,READ,0,raw_popfl,(void)) 3083: 3084: /* Generate floating-point instructions */ 3085: static inline void x86_fadd_m(MEMR s) 3086: { 3087: emit_byte(0xdc); 3088: emit_byte(0x05); 3089: emit_long(s); 3090: } 3091: 3092: #endif 3093: 3094: /************************************************************************* 3095: * Unoptimizable stuff --- jump * 3096: *************************************************************************/ 3097: 1.1.1.2 ! root 3098: static inline void raw_call_r(R4 r) 1.1 root 3099: { 3100: #if USE_NEW_RTASM 3101: CALLsr(r); 3102: #else 1.1.1.2 ! root 3103: emit_byte(0xff); ! 3104: emit_byte(0xd0+r); 1.1 root 3105: #endif 3106: } 3107: 1.1.1.2 ! root 3108: static inline void raw_call_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) 1.1 root 3109: { 3110: #if USE_NEW_RTASM 1.1.1.2 ! root 3111: ADDR32 CALLsm(base, X86_NOREG, r, m); 1.1 root 3112: #else 1.1.1.2 ! root 3113: int mu; ! 3114: switch(m) { ! 3115: case 1: mu=0; break; ! 3116: case 2: mu=1; break; ! 3117: case 4: mu=2; break; ! 3118: case 8: mu=3; break; ! 3119: default: abort(); ! 3120: } ! 3121: emit_byte(0xff); ! 3122: emit_byte(0x14); ! 3123: emit_byte(0x05+8*r+0x40*mu); ! 3124: emit_long(base); 1.1 root 3125: #endif 3126: } 3127: 1.1.1.2 ! root 3128: static inline void raw_jmp_r(R4 r) 1.1 root 3129: { 3130: #if USE_NEW_RTASM 1.1.1.2 ! root 3131: JMPsr(r); 1.1 root 3132: #else 1.1.1.2 ! root 3133: emit_byte(0xff); ! 3134: emit_byte(0xe0+r); 1.1 root 3135: #endif 3136: } 3137: 1.1.1.2 ! root 3138: static inline void raw_jmp_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) 1.1 root 3139: { 3140: #if USE_NEW_RTASM 1.1.1.2 ! root 3141: ADDR32 JMPsm(base, X86_NOREG, r, m); 1.1 root 3142: #else 1.1.1.2 ! root 3143: int mu; ! 3144: switch (m) { ! 3145: case 1: mu=0; break; ! 3146: case 2: mu=1; break; ! 3147: case 4: mu=2; break; ! 3148: case 8: mu=3; break; ! 3149: default: abort(); ! 3150: } ! 3151: emit_byte(0xff); ! 3152: emit_byte(0x24); ! 3153: emit_byte(0x05+8*r+0x40*mu); ! 3154: emit_long(base); 1.1 root 3155: #endif 3156: } 3157: 1.1.1.2 ! root 3158: static inline void raw_jmp_m(uae_u32 base) 1.1 root 3159: { 1.1.1.2 ! root 3160: emit_byte(0xff); ! 3161: emit_byte(0x25); ! 3162: emit_long(base); 1.1 root 3163: } 3164: 3165: 1.1.1.2 ! root 3166: static inline void raw_call(uae_u32 t) 1.1 root 3167: { 3168: #if USE_NEW_RTASM 1.1.1.2 ! root 3169: ADDR32 CALLm(t); 1.1 root 3170: #else 1.1.1.2 ! root 3171: emit_byte(0xe8); ! 3172: emit_long(t-(uintptr)target-4); 1.1 root 3173: #endif 3174: } 3175: 1.1.1.2 ! root 3176: static inline void raw_jmp(uae_u32 t) 1.1 root 3177: { 3178: #if USE_NEW_RTASM 1.1.1.2 ! root 3179: ADDR32 JMPm(t); 1.1 root 3180: #else 1.1.1.2 ! root 3181: emit_byte(0xe9); ! 3182: emit_long(t-(uintptr)target-4); 1.1 root 3183: #endif 3184: } 3185: 1.1.1.2 ! root 3186: static inline void raw_jl(uae_u32 t) 1.1 root 3187: { 1.1.1.2 ! root 3188: emit_byte(0x0f); ! 3189: emit_byte(0x8c); ! 3190: emit_long(t-(uintptr)target-4); 1.1 root 3191: } 3192: 1.1.1.2 ! root 3193: static inline void raw_jz(uae_u32 t) 1.1 root 3194: { 1.1.1.2 ! root 3195: emit_byte(0x0f); ! 3196: emit_byte(0x84); ! 3197: emit_long(t-(uintptr)target-4); 1.1 root 3198: } 3199: 1.1.1.2 ! root 3200: static inline void raw_jnz(uae_u32 t) 1.1 root 3201: { 1.1.1.2 ! root 3202: emit_byte(0x0f); ! 3203: emit_byte(0x85); ! 3204: emit_long(t-(uintptr)target-4); 1.1 root 3205: } 3206: 1.1.1.2 ! root 3207: static inline void raw_jnz_l_oponly(void) 1.1 root 3208: { 1.1.1.2 ! root 3209: emit_byte(0x0f); ! 3210: emit_byte(0x85); 1.1 root 3211: } 3212: 1.1.1.2 ! root 3213: static inline void raw_jcc_l_oponly(int cc) 1.1 root 3214: { 1.1.1.2 ! root 3215: emit_byte(0x0f); ! 3216: emit_byte(0x80+cc); 1.1 root 3217: } 3218: 1.1.1.2 ! root 3219: static inline void raw_jnz_b_oponly(void) 1.1 root 3220: { 1.1.1.2 ! root 3221: emit_byte(0x75); 1.1 root 3222: } 3223: 1.1.1.2 ! root 3224: static inline void raw_jz_b_oponly(void) 1.1 root 3225: { 1.1.1.2 ! root 3226: emit_byte(0x74); 1.1 root 3227: } 3228: 1.1.1.2 ! root 3229: static inline void raw_jcc_b_oponly(int cc) 1.1 root 3230: { 3231: emit_byte(0x70+cc); 3232: } 3233: 1.1.1.2 ! root 3234: static inline void raw_jmp_l_oponly(void) 1.1 root 3235: { 1.1.1.2 ! root 3236: emit_byte(0xe9); 1.1 root 3237: } 3238: 1.1.1.2 ! root 3239: static inline void raw_jmp_b_oponly(void) 1.1 root 3240: { 1.1.1.2 ! root 3241: emit_byte(0xeb); 1.1 root 3242: } 3243: 1.1.1.2 ! root 3244: static inline void raw_ret(void) 1.1 root 3245: { 1.1.1.2 ! root 3246: emit_byte(0xc3); 1.1 root 3247: } 3248: 1.1.1.2 ! root 3249: static inline void raw_nop(void) 1.1 root 3250: { 1.1.1.2 ! root 3251: emit_byte(0x90); 1.1 root 3252: } 3253: 1.1.1.2 ! root 3254: static inline void raw_emit_nop_filler(int nbytes) 1.1 root 3255: { 1.1.1.2 ! root 3256: ! 3257: #if defined(CPU_x86_64) ! 3258: /* The recommended way to pad 64bit code is to use NOPs preceded by ! 3259: maximally four 0x66 prefixes. Balance the size of nops. */ ! 3260: static const uae_u8 prefixes[4] = { 0x66, 0x66, 0x66, 0x66 }; ! 3261: if (nbytes == 0) ! 3262: return; ! 3263: ! 3264: int i; ! 3265: int nnops = (nbytes + 3) / 4; ! 3266: int len = nbytes / nnops; ! 3267: int remains = nbytes - nnops * len; ! 3268: ! 3269: for (i = 0; i < remains; i++) { ! 3270: emit_block(prefixes, len); ! 3271: raw_nop(); ! 3272: } ! 3273: for (; i < nnops; i++) { ! 3274: emit_block(prefixes, len - 1); ! 3275: raw_nop(); ! 3276: } ! 3277: #else 1.1 root 3278: /* Source: GNU Binutils 2.12.90.0.15 */ 3279: /* Various efficient no-op patterns for aligning code labels. 3280: Note: Don't try to assemble the instructions in the comments. 3281: 0L and 0w are not legal. */ 3282: static const uae_u8 f32_1[] = 3283: {0x90}; /* nop */ 3284: static const uae_u8 f32_2[] = 3285: {0x89,0xf6}; /* movl %esi,%esi */ 3286: static const uae_u8 f32_3[] = 3287: {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ 3288: static const uae_u8 f32_4[] = 3289: {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ 3290: static const uae_u8 f32_5[] = 3291: {0x90, /* nop */ 3292: 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ 3293: static const uae_u8 f32_6[] = 3294: {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ 3295: static const uae_u8 f32_7[] = 3296: {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ 3297: static const uae_u8 f32_8[] = 3298: {0x90, /* nop */ 3299: 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ 3300: static const uae_u8 f32_9[] = 3301: {0x89,0xf6, /* movl %esi,%esi */ 3302: 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 3303: static const uae_u8 f32_10[] = 3304: {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ 3305: 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 3306: static const uae_u8 f32_11[] = 3307: {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ 3308: 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 3309: static const uae_u8 f32_12[] = 3310: {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ 3311: 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ 3312: static const uae_u8 f32_13[] = 3313: {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ 3314: 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 3315: static const uae_u8 f32_14[] = 3316: {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ 3317: 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 3318: static const uae_u8 f32_15[] = 3319: {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ 3320: 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; 3321: static const uae_u8 f32_16[] = 3322: {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ 3323: 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; 3324: static const uae_u8 *const f32_patt[] = { 3325: f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, 3326: f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15 3327: }; 3328: 3329: int nloops = nbytes / 16; 3330: while (nloops-- > 0) 3331: emit_block(f32_16, sizeof(f32_16)); 3332: 3333: nbytes %= 16; 3334: if (nbytes) 3335: emit_block(f32_patt[nbytes - 1], nbytes); 3336: #endif 3337: } 3338: 3339: 3340: /************************************************************************* 1.1.1.2 ! root 3341: * Flag handling, to and fro UAE flag register * ! 3342: *************************************************************************/ 1.1 root 3343: 1.1.1.2 ! root 3344: static inline void raw_flags_evicted(int r) 1.1 root 3345: { 1.1.1.2 ! root 3346: //live.state[FLAGTMP].status=CLEAN; ! 3347: live.state[FLAGTMP].status=INMEM; ! 3348: live.state[FLAGTMP].realreg=-1; ! 3349: /* We just "evicted" FLAGTMP. */ ! 3350: if (live.nat[r].nholds!=1) { ! 3351: /* Huh? */ ! 3352: abort(); ! 3353: } ! 3354: live.nat[r].nholds=0; 1.1 root 3355: } 3356: 3357: #define FLAG_NREG1_FLAGREG 0 /* Set to -1 if any register will do */ 1.1.1.2 ! root 3358: static inline void raw_flags_to_reg_FLAGREG(int r) 1.1 root 3359: { 1.1.1.2 ! root 3360: raw_lahf(0); /* Most flags in AH */ ! 3361: //raw_setcc(r,0); /* V flag in AL */ ! 3362: raw_setcc_m((uintptr)live.state[FLAGTMP].mem,0); ! 3363: 1.1 root 3364: #if 1 /* Let's avoid those nasty partial register stalls */ 1.1.1.2 ! root 3365: //raw_mov_b_mr((uintptr)live.state[FLAGTMP].mem,r); ! 3366: raw_mov_b_mr(((uintptr)live.state[FLAGTMP].mem)+1,AH_INDEX); ! 3367: raw_flags_evicted(r); 1.1 root 3368: #endif 3369: } 3370: 3371: #define FLAG_NREG2_FLAGREG 0 /* Set to -1 if any register will do */ 1.1.1.2 ! root 3372: static inline void raw_reg_to_flags_FLAGREG(int r) 1.1 root 3373: { 1.1.1.2 ! root 3374: raw_cmp_b_ri(r,-127); /* set V */ ! 3375: raw_sahf(0); 1.1 root 3376: } 3377: 3378: #define FLAG_NREG3_FLAGREG 0 /* Set to -1 if any register will do */ 3379: static __inline__ void raw_flags_set_zero_FLAGREG(int s, int tmp) 3380: { 3381: raw_mov_l_rr(tmp,s); 3382: raw_lahf(s); /* flags into ah */ 3383: raw_and_l_ri(s,0xffffbfff); 3384: raw_and_l_ri(tmp,0x00004000); 3385: raw_xor_l_ri(tmp,0x00004000); 3386: raw_or_l(s,tmp); 3387: raw_sahf(s); 3388: } 3389: 1.1.1.2 ! root 3390: static inline void raw_flags_init_FLAGREG(void) { } 1.1 root 3391: 3392: #define FLAG_NREG1_FLAGSTK -1 /* Set to -1 if any register will do */ 1.1.1.2 ! root 3393: static inline void raw_flags_to_reg_FLAGSTK(int r) 1.1 root 3394: { 3395: raw_pushfl(); 3396: raw_pop_l_r(r); 3397: raw_mov_l_mr((uintptr)live.state[FLAGTMP].mem,r); 3398: raw_flags_evicted(r); 3399: } 3400: 3401: #define FLAG_NREG2_FLAGSTK -1 /* Set to -1 if any register will do */ 1.1.1.2 ! root 3402: static inline void raw_reg_to_flags_FLAGSTK(int r) 1.1 root 3403: { 3404: raw_push_l_r(r); 3405: raw_popfl(); 3406: } 3407: 3408: #define FLAG_NREG3_FLAGSTK -1 /* Set to -1 if any register will do */ 1.1.1.2 ! root 3409: static inline void raw_flags_set_zero_FLAGSTK(int s, int tmp) 1.1 root 3410: { 3411: raw_mov_l_rr(tmp,s); 3412: raw_pushfl(); 3413: raw_pop_l_r(s); 3414: raw_and_l_ri(s,0xffffffbf); 3415: raw_and_l_ri(tmp,0x00000040); 3416: raw_xor_l_ri(tmp,0x00000040); 3417: raw_or_l(s,tmp); 3418: raw_push_l_r(s); 3419: raw_popfl(); 3420: } 3421: 1.1.1.2 ! root 3422: static inline void raw_flags_init_FLAGSTK(void) { } 1.1 root 3423: 1.1.1.2 ! root 3424: #if defined(CPU_x86_64) 1.1 root 3425: /* Try to use the LAHF/SETO method on x86_64 since it is faster. 3426: This can't be the default because some older CPUs don't support 3427: LAHF/SAHF in long mode. */ 3428: static int FLAG_NREG1_FLAGGEN = 0; 1.1.1.2 ! root 3429: static inline void raw_flags_to_reg_FLAGGEN(int r) 1.1 root 3430: { 3431: if (have_lahf_lm) { 3432: // NOTE: the interpreter uses the normal EFLAGS layout 3433: // pushf/popf CF(0) ZF( 6) SF( 7) OF(11) 3434: // sahf/lahf CF(8) ZF(14) SF(15) OF( 0) 3435: assert(r == 0); 3436: raw_setcc(r,0); /* V flag in AL */ 3437: raw_lea_l_r_scaled(0,0,8); /* move it to its EFLAGS location */ 3438: raw_mov_b_mr(((uintptr)live.state[FLAGTMP].mem)+1,0); 3439: raw_lahf(0); /* most flags in AH */ 3440: raw_mov_b_mr((uintptr)live.state[FLAGTMP].mem,AH_INDEX); 3441: raw_flags_evicted(r); 3442: } 3443: else 3444: raw_flags_to_reg_FLAGSTK(r); 3445: } 3446: 3447: static int FLAG_NREG2_FLAGGEN = 0; 1.1.1.2 ! root 3448: static inline void raw_reg_to_flags_FLAGGEN(int r) 1.1 root 3449: { 3450: if (have_lahf_lm) { 3451: raw_xchg_b_rr(0,AH_INDEX); 3452: raw_cmp_b_ri(r,-120); /* set V */ 3453: raw_sahf(0); 3454: } 3455: else 3456: raw_reg_to_flags_FLAGSTK(r); 3457: } 3458: 3459: static int FLAG_NREG3_FLAGGEN = 0; 1.1.1.2 ! root 3460: static inline void raw_flags_set_zero_FLAGGEN(int s, int tmp) 1.1 root 3461: { 3462: if (have_lahf_lm) 3463: raw_flags_set_zero_FLAGREG(s, tmp); 3464: else 3465: raw_flags_set_zero_FLAGSTK(s, tmp); 3466: } 3467: 1.1.1.2 ! root 3468: static inline void raw_flags_init_FLAGGEN(void) 1.1 root 3469: { 3470: if (have_lahf_lm) { 3471: FLAG_NREG1_FLAGGEN = FLAG_NREG1_FLAGREG; 3472: FLAG_NREG2_FLAGGEN = FLAG_NREG2_FLAGREG; 3473: FLAG_NREG1_FLAGGEN = FLAG_NREG3_FLAGREG; 3474: } 3475: else { 3476: FLAG_NREG1_FLAGGEN = FLAG_NREG1_FLAGSTK; 3477: FLAG_NREG2_FLAGGEN = FLAG_NREG2_FLAGSTK; 3478: FLAG_NREG1_FLAGGEN = FLAG_NREG3_FLAGSTK; 3479: } 3480: } 3481: #endif 3482: 3483: #ifdef SAHF_SETO_PROFITABLE 3484: #define FLAG_SUFFIX FLAGREG 1.1.1.2 ! root 3485: #elif defined CPU_x86_64 1.1 root 3486: #define FLAG_SUFFIX FLAGGEN 3487: #else 3488: #define FLAG_SUFFIX FLAGSTK 3489: #endif 3490: 3491: #define FLAG_GLUE_2(x, y) x ## _ ## y 3492: #define FLAG_GLUE_1(x, y) FLAG_GLUE_2(x, y) 3493: #define FLAG_GLUE(x) FLAG_GLUE_1(x, FLAG_SUFFIX) 3494: 3495: #define raw_flags_init FLAG_GLUE(raw_flags_init) 3496: #define FLAG_NREG1 FLAG_GLUE(FLAG_NREG1) 3497: #define raw_flags_to_reg FLAG_GLUE(raw_flags_to_reg) 3498: #define FLAG_NREG2 FLAG_GLUE(FLAG_NREG2) 3499: #define raw_reg_to_flags FLAG_GLUE(raw_reg_to_flags) 3500: #define FLAG_NREG3 FLAG_GLUE(FLAG_NREG3) 3501: #define raw_flags_set_zero FLAG_GLUE(raw_flags_set_zero) 3502: 3503: /* Apparently, there are enough instructions between flag store and 1.1.1.2 ! root 3504: flag reload to avoid the partial memory stall */ ! 3505: static inline void raw_load_flagreg(uae_u32 target, uae_u32 r) 1.1 root 3506: { 3507: #if 1 1.1.1.2 ! root 3508: raw_mov_l_rm(target,(uintptr)live.state[r].mem); 1.1 root 3509: #else 1.1.1.2 ! root 3510: raw_mov_b_rm(target,(uintptr)live.state[r].mem); ! 3511: raw_mov_b_rm(target+4,((uintptr)live.state[r].mem)+1); 1.1 root 3512: #endif 3513: } 3514: 1.1.1.2 ! root 3515: #ifdef UAE ! 3516: /* FLAGX is word-sized */ ! 3517: #else 1.1 root 3518: /* FLAGX is byte sized, and we *do* write it at that size */ 1.1.1.2 ! root 3519: #endif ! 3520: static inline void raw_load_flagx(uae_u32 target, uae_u32 r) 1.1 root 3521: { 1.1.1.2 ! root 3522: #ifdef UAE ! 3523: if (live.nat[target].canword) ! 3524: #else ! 3525: if (live.nat[target].canbyte) ! 3526: raw_mov_b_rm(target,(uintptr)live.state[r].mem); ! 3527: else if (live.nat[target].canword) ! 3528: #endif ! 3529: raw_mov_w_rm(target,(uintptr)live.state[r].mem); ! 3530: else ! 3531: raw_mov_l_rm(target,(uintptr)live.state[r].mem); 1.1 root 3532: } 3533: 1.1.1.2 ! root 3534: static inline void raw_dec_sp(int off) 1.1 root 3535: { 1.1.1.2 ! root 3536: if (off) { ! 3537: #ifdef CPU_x86_64 ! 3538: emit_byte(0x48); /* REX prefix */ ! 3539: #endif ! 3540: raw_sub_l_ri(ESP_INDEX,off); ! 3541: } 1.1 root 3542: } 3543: 1.1.1.2 ! root 3544: static inline void raw_inc_sp(int off) 1.1 root 3545: { 1.1.1.2 ! root 3546: if (off) { ! 3547: #ifdef CPU_x86_64 ! 3548: emit_byte(0x48); /* REX prefix */ ! 3549: #endif ! 3550: raw_add_l_ri(ESP_INDEX,off); ! 3551: } 1.1 root 3552: } 3553: 1.1.1.2 ! root 3554: static inline void raw_push_regs_to_preserve(void) { ! 3555: for (int i=N_REGS;i--;) { ! 3556: if (need_to_preserve[i]) ! 3557: raw_push_l_r(i); ! 3558: } ! 3559: } 1.1 root 3560: 1.1.1.2 ! root 3561: static inline void raw_pop_preserved_regs(void) { ! 3562: for (int i=0;i<N_REGS;i++) { ! 3563: if (need_to_preserve[i]) ! 3564: raw_pop_l_r(i); 1.1 root 3565: } 3566: } 1.1.1.2 ! root 3567: ! 3568: /************************************************************************* ! 3569: * Handling mistaken direct memory access (removed from ARAnyM sources) * ! 3570: *************************************************************************/ ! 3571: ! 3572: #ifdef UAE ! 3573: #include "exception_handler.cpp" 1.1 root 3574: #endif 3575: 1.1.1.2 ! root 3576: static ! 3577: void compiler_status() { ! 3578: jit_log("compiled code starts at %p, current at %p (size 0x%x)", compiled_code, current_compile_p, (unsigned int)(current_compile_p - compiled_code)); ! 3579: } 1.1 root 3580: 3581: /************************************************************************* 1.1.1.2 ! root 3582: * Checking for CPU features * ! 3583: *************************************************************************/ 1.1 root 3584: 3585: struct cpuinfo_x86 { 1.1.1.2 ! root 3586: uae_u8 x86; // CPU family ! 3587: uae_u8 x86_vendor; // CPU vendor ! 3588: uae_u8 x86_processor; // CPU canonical processor type ! 3589: uae_u8 x86_brand_id; // CPU BrandID if supported, yield 0 otherwise ! 3590: uae_u32 x86_hwcap; ! 3591: uae_u8 x86_model; ! 3592: uae_u8 x86_mask; ! 3593: bool x86_has_xmm2; ! 3594: int cpuid_level; // Maximum supported CPUID level, -1=no CPUID ! 3595: char x86_vendor_id[16]; ! 3596: uintptr x86_clflush_size; 1.1 root 3597: }; 3598: struct cpuinfo_x86 cpuinfo; 3599: 3600: enum { 1.1.1.2 ! root 3601: X86_VENDOR_INTEL = 0, ! 3602: X86_VENDOR_CYRIX = 1, ! 3603: X86_VENDOR_AMD = 2, ! 3604: X86_VENDOR_UMC = 3, ! 3605: X86_VENDOR_NEXGEN = 4, ! 3606: X86_VENDOR_CENTAUR = 5, ! 3607: X86_VENDOR_RISE = 6, ! 3608: X86_VENDOR_TRANSMETA = 7, ! 3609: X86_VENDOR_NSC = 8, ! 3610: X86_VENDOR_UNKNOWN = 0xff 1.1 root 3611: }; 3612: 3613: enum { 1.1.1.2 ! root 3614: X86_PROCESSOR_I386, /* 80386 */ ! 3615: X86_PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */ ! 3616: X86_PROCESSOR_PENTIUM, ! 3617: X86_PROCESSOR_PENTIUMPRO, ! 3618: X86_PROCESSOR_K6, ! 3619: X86_PROCESSOR_ATHLON, ! 3620: X86_PROCESSOR_PENTIUM4, ! 3621: X86_PROCESSOR_X86_64, ! 3622: X86_PROCESSOR_max 1.1 root 3623: }; 3624: 3625: static const char * x86_processor_string_table[X86_PROCESSOR_max] = { 1.1.1.2 ! root 3626: "80386", ! 3627: "80486", ! 3628: "Pentium", ! 3629: "PentiumPro", ! 3630: "K6", ! 3631: "Athlon", ! 3632: "Pentium4", ! 3633: "x86-64" 1.1 root 3634: }; 3635: 3636: static struct ptt { 1.1.1.2 ! root 3637: const int align_loop; ! 3638: const int align_loop_max_skip; ! 3639: const int align_jump; ! 3640: const int align_jump_max_skip; ! 3641: const int align_func; 1.1 root 3642: } 3643: x86_alignments[X86_PROCESSOR_max] = { 1.1.1.2 ! root 3644: { 4, 3, 4, 3, 4 }, ! 3645: { 16, 15, 16, 15, 16 }, ! 3646: { 16, 7, 16, 7, 16 }, ! 3647: { 16, 15, 16, 7, 16 }, ! 3648: { 32, 7, 32, 7, 32 }, ! 3649: { 16, 7, 16, 7, 16 }, ! 3650: { 0, 0, 0, 0, 0 }, ! 3651: { 16, 7, 16, 7, 16 } 1.1 root 3652: }; 3653: 3654: static void 1.1.1.2 ! root 3655: x86_get_cpu_vendor(struct cpuinfo_x86 *c) 1.1 root 3656: { 3657: char *v = c->x86_vendor_id; 3658: 3659: if (!strcmp(v, "GenuineIntel")) 3660: c->x86_vendor = X86_VENDOR_INTEL; 3661: else if (!strcmp(v, "AuthenticAMD")) 3662: c->x86_vendor = X86_VENDOR_AMD; 3663: else if (!strcmp(v, "CyrixInstead")) 3664: c->x86_vendor = X86_VENDOR_CYRIX; 3665: else if (!strcmp(v, "Geode by NSC")) 3666: c->x86_vendor = X86_VENDOR_NSC; 3667: else if (!strcmp(v, "UMC UMC UMC ")) 3668: c->x86_vendor = X86_VENDOR_UMC; 3669: else if (!strcmp(v, "CentaurHauls")) 3670: c->x86_vendor = X86_VENDOR_CENTAUR; 3671: else if (!strcmp(v, "NexGenDriven")) 3672: c->x86_vendor = X86_VENDOR_NEXGEN; 3673: else if (!strcmp(v, "RiseRiseRise")) 3674: c->x86_vendor = X86_VENDOR_RISE; 3675: else if (!strcmp(v, "GenuineTMx86") || 1.1.1.2 ! root 3676: !strcmp(v, "TransmetaCPU")) 1.1 root 3677: c->x86_vendor = X86_VENDOR_TRANSMETA; 3678: else 3679: c->x86_vendor = X86_VENDOR_UNKNOWN; 3680: } 3681: 1.1.1.2 ! root 3682: /* ! 3683: * Generic CPUID function ! 3684: * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx ! 3685: * resulting in stale register contents being returned. ! 3686: */ ! 3687: /* Some CPUID calls want 'count' to be placed in ecx */ ! 3688: #ifdef __GNUC__ ! 3689: static void cpuid_count(uae_u32 op, uae_u32 count, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 *edx) ! 3690: { ! 3691: uae_u32 _eax, _ebx, _ecx, _edx; ! 3692: _eax = op; ! 3693: _ecx = count; ! 3694: __asm__ __volatile__( ! 3695: " movl %0,%%eax \n" ! 3696: " movl %2,%%ecx \n" ! 3697: " cpuid \n" ! 3698: " movl %%eax,%0 \n" ! 3699: " movl %%ebx,%1 \n" ! 3700: " movl %%ecx,%2 \n" ! 3701: " movl %%edx,%3 \n" ! 3702: : "+m" (_eax), ! 3703: "=m" (_ebx), ! 3704: "+m" (_ecx), ! 3705: "=m" (_edx) ! 3706: : ! 3707: : "eax", "ebx", "ecx", "edx"); ! 3708: *eax = _eax; ! 3709: *ebx = _ebx; ! 3710: *ecx = _ecx; ! 3711: *edx = _edx; ! 3712: } ! 3713: #endif ! 3714: ! 3715: #ifdef _MSC_VER ! 3716: static void cpuid_count(uae_u32 op, uae_u32 count, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 *edx) ! 3717: { ! 3718: int cpuinfo[4]; ! 3719: cpuinfo[0] = op; ! 3720: cpuinfo[1] = 0; ! 3721: cpuinfo[2] = count; ! 3722: cpuinfo[3] = 0; ! 3723: __cpuidex(cpuinfo, op, count); ! 3724: *eax = cpuinfo[0]; ! 3725: *ebx = cpuinfo[1]; ! 3726: *ecx = cpuinfo[2]; ! 3727: *edx = cpuinfo[3]; ! 3728: } ! 3729: #endif ! 3730: 1.1 root 3731: static void 3732: cpuid(uae_u32 op, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 *edx) 3733: { 1.1.1.2 ! root 3734: cpuid_count(op, 0, eax, ebx, ecx, edx); 1.1 root 3735: } 3736: 3737: static void 3738: raw_init_cpu(void) 3739: { 1.1.1.2 ! root 3740: struct cpuinfo_x86 *c = &cpuinfo; ! 3741: uae_u32 dummy; 1.1 root 3742: 1.1.1.2 ! root 3743: /* Defaults */ ! 3744: c->x86_processor = X86_PROCESSOR_max; ! 3745: c->x86_vendor = X86_VENDOR_UNKNOWN; ! 3746: c->cpuid_level = -1; /* CPUID not detected */ ! 3747: c->x86_model = c->x86_mask = 0; /* So far unknown... */ ! 3748: c->x86_vendor_id[0] = '\0'; /* Unset */ ! 3749: c->x86_hwcap = 0; ! 3750: #ifdef CPU_x86_64 ! 3751: c->x86_clflush_size = 64; ! 3752: #else ! 3753: c->x86_clflush_size = 32; ! 3754: #endif ! 3755: ! 3756: /* Get vendor name */ ! 3757: c->x86_vendor_id[12] = '\0'; ! 3758: cpuid(0x00000000, 1.1 root 3759: (uae_u32 *)&c->cpuid_level, 3760: (uae_u32 *)&c->x86_vendor_id[0], 3761: (uae_u32 *)&c->x86_vendor_id[8], 3762: (uae_u32 *)&c->x86_vendor_id[4]); 1.1.1.2 ! root 3763: x86_get_cpu_vendor(c); 1.1 root 3764: 1.1.1.2 ! root 3765: /* Intel-defined flags: level 0x00000001 */ ! 3766: c->x86_brand_id = 0; ! 3767: if ( c->cpuid_level >= 0x00000001 ) { ! 3768: uae_u32 tfms, brand_id; ! 3769: cpuid(0x00000001, &tfms, &brand_id, &dummy, &c->x86_hwcap); ! 3770: c->x86 = (tfms >> 8) & 15; ! 3771: if (c->x86 == 0xf) ! 3772: c->x86 += (tfms >> 20) & 0xff; /* extended family */ ! 3773: c->x86_model = (tfms >> 4) & 15; ! 3774: if (c->x86_model == 0xf) ! 3775: c->x86_model |= (tfms >> 12) & 0xf0; /* extended model */ ! 3776: c->x86_brand_id = brand_id & 0xff; ! 3777: c->x86_mask = tfms & 15; ! 3778: if (c->x86_hwcap & (1 << 19)) ! 3779: { ! 3780: c->x86_clflush_size = ((brand_id >> 8) & 0xff) * 8; ! 3781: } ! 3782: } else { ! 3783: /* Have CPUID level 0 only - unheard of */ ! 3784: c->x86 = 4; ! 3785: } ! 3786: ! 3787: /* AMD-defined flags: level 0x80000001 */ ! 3788: uae_u32 xlvl; ! 3789: cpuid(0x80000000, &xlvl, &dummy, &dummy, &dummy); ! 3790: if ( (xlvl & 0xffff0000) == 0x80000000 ) { ! 3791: if ( xlvl >= 0x80000001 ) { ! 3792: uae_u32 features, extra_features; ! 3793: cpuid(0x80000001, &dummy, &dummy, &extra_features, &features); ! 3794: if (features & (1 << 29)) { ! 3795: /* Assume x86-64 if long mode is supported */ ! 3796: c->x86_processor = X86_PROCESSOR_X86_64; ! 3797: } ! 3798: if (extra_features & (1 << 0)) ! 3799: have_lahf_lm = true; ! 3800: } 1.1 root 3801: } 3802: 1.1.1.2 ! root 3803: /* Canonicalize processor ID */ ! 3804: switch (c->x86) { ! 3805: case 3: ! 3806: c->x86_processor = X86_PROCESSOR_I386; ! 3807: break; ! 3808: case 4: ! 3809: c->x86_processor = X86_PROCESSOR_I486; ! 3810: break; ! 3811: case 5: ! 3812: if (c->x86_vendor == X86_VENDOR_AMD) ! 3813: c->x86_processor = X86_PROCESSOR_K6; ! 3814: else ! 3815: c->x86_processor = X86_PROCESSOR_PENTIUM; ! 3816: break; ! 3817: case 6: ! 3818: if (c->x86_vendor == X86_VENDOR_AMD) ! 3819: c->x86_processor = X86_PROCESSOR_ATHLON; ! 3820: else ! 3821: c->x86_processor = X86_PROCESSOR_PENTIUMPRO; ! 3822: break; ! 3823: case 15: ! 3824: if (c->x86_processor == X86_PROCESSOR_max) { ! 3825: switch (c->x86_vendor) { ! 3826: case X86_VENDOR_INTEL: ! 3827: c->x86_processor = X86_PROCESSOR_PENTIUM4; ! 3828: break; ! 3829: case X86_VENDOR_AMD: ! 3830: /* Assume a 32-bit Athlon processor if not in long mode */ ! 3831: c->x86_processor = X86_PROCESSOR_ATHLON; ! 3832: break; ! 3833: } ! 3834: } ! 3835: break; ! 3836: } ! 3837: if (c->x86_processor == X86_PROCESSOR_max) { ! 3838: c->x86_processor = X86_PROCESSOR_I386; ! 3839: jit_log("Error: unknown processor type"); ! 3840: jit_log(" Family : %d", c->x86); ! 3841: jit_log(" Model : %d", c->x86_model); ! 3842: jit_log(" Mask : %d", c->x86_mask); ! 3843: jit_log(" Vendor : %s [%d]", c->x86_vendor_id, c->x86_vendor); ! 3844: if (c->x86_brand_id) ! 3845: jit_log(" BrandID : %02x", c->x86_brand_id); ! 3846: } ! 3847: ! 3848: /* Have CMOV support? */ ! 3849: have_cmov = (c->x86_hwcap & (1 << 15)) != 0; ! 3850: #if defined(CPU_x86_64) ! 3851: if (!have_cmov) { ! 3852: jit_abort("x86-64 implementations are bound to have CMOV!"); ! 3853: } 1.1 root 3854: #endif 3855: 1.1.1.2 ! root 3856: c->x86_has_xmm2 = (c->x86_hwcap & (1 << 26)) != 0; ! 3857: ! 3858: /* Can the host CPU suffer from partial register stalls? */ ! 3859: // non-RAT_STALL mode is currently broken ! 3860: have_rat_stall = true; //(c->x86_vendor == X86_VENDOR_INTEL); ! 3861: #if 0 ! 3862: /* It appears that partial register writes are a bad idea even on ! 3863: AMD K7 cores, even though they are not supposed to have the ! 3864: dreaded rat stall. Why? Anyway, that's why we lie about it ;-) */ ! 3865: if (c->x86_processor == X86_PROCESSOR_ATHLON) ! 3866: have_rat_stall = true; 1.1 root 3867: #endif 3868: 1.1.1.2 ! root 3869: /* Alignments */ ! 3870: if (tune_alignment) { ! 3871: align_loops = x86_alignments[c->x86_processor].align_loop; ! 3872: align_jumps = x86_alignments[c->x86_processor].align_jump; ! 3873: } 1.1 root 3874: 1.1.1.2 ! root 3875: jit_log("Max CPUID level=%d Processor is %s [%s]", 1.1 root 3876: c->cpuid_level, c->x86_vendor_id, 3877: x86_processor_string_table[c->x86_processor]); 3878: 1.1.1.2 ! root 3879: raw_flags_init(); 1.1 root 3880: } 3881: 1.1.1.2 ! root 3882: #if 0 ! 3883: static void __attribute_noinline__ prevent_redzone_use(void) {} ! 3884: 1.1 root 3885: static bool target_check_bsf(void) 3886: { 3887: bool mismatch = false; 3888: for (int g_ZF = 0; g_ZF <= 1; g_ZF++) { 1.1.1.2 ! root 3889: for (int g_CF = 0; g_CF <= 1; g_CF++) { ! 3890: for (int g_OF = 0; g_OF <= 1; g_OF++) { ! 3891: for (int g_SF = 0; g_SF <= 1; g_SF++) { ! 3892: for (int value = -1; value <= 1; value++) { ! 3893: uintptr flags = (g_SF << 7) | (g_OF << 11) | (g_ZF << 6) | g_CF; ! 3894: intptr tmp = value; ! 3895: prevent_redzone_use(); ! 3896: __asm__ __volatile__ ("push %0; popf; bsf %1,%1; pushf; pop %0" ! 3897: : "+r" (flags), "+r" (tmp) : : "cc"); ! 3898: int OF = (flags >> 11) & 1; ! 3899: int SF = (flags >> 7) & 1; ! 3900: int ZF = (flags >> 6) & 1; ! 3901: int CF = flags & 1; ! 3902: tmp = (value == 0); ! 3903: if (ZF != tmp || SF != g_SF || OF != g_OF || CF != g_CF) ! 3904: mismatch = true; ! 3905: } ! 3906: }}}} 1.1 root 3907: if (mismatch) 1.1.1.2 ! root 3908: { ! 3909: jit_log("Target CPU defines all flags on BSF instruction"); ! 3910: } 1.1 root 3911: return !mismatch; 3912: } 1.1.1.2 ! root 3913: #endif 1.1 root 3914: 3915: /************************************************************************* 1.1.1.2 ! root 3916: * FPU stuff * ! 3917: *************************************************************************/ 1.1 root 3918: 3919: 1.1.1.2 ! root 3920: static inline void raw_fp_init(void) 1.1 root 3921: { 1.1.1.2 ! root 3922: int i; ! 3923: ! 3924: for (i=0;i<N_FREGS;i++) ! 3925: live.spos[i]=-2; ! 3926: live.tos=-1; /* Stack is empty */ 1.1 root 3927: } 3928: 1.1.1.2 ! root 3929: static inline void raw_fp_cleanup_drop(void) 1.1 root 3930: { 3931: #if 0 1.1.1.2 ! root 3932: /* using FINIT instead of popping all the entries. ! 3933: Seems to have side effects --- there is display corruption in ! 3934: Quake when this is used */ ! 3935: if (live.tos>1) { ! 3936: emit_byte(0x9b); ! 3937: emit_byte(0xdb); ! 3938: emit_byte(0xe3); ! 3939: live.tos=-1; ! 3940: } 1.1 root 3941: #endif 1.1.1.2 ! root 3942: while (live.tos>=1) { ! 3943: emit_byte(0xde); ! 3944: emit_byte(0xd9); ! 3945: live.tos-=2; ! 3946: } ! 3947: while (live.tos>=0) { ! 3948: emit_byte(0xdd); ! 3949: emit_byte(0xd8); ! 3950: live.tos--; ! 3951: } ! 3952: raw_fp_init(); 1.1 root 3953: } 3954: 1.1.1.2 ! root 3955: static inline void make_tos(int r) 1.1 root 3956: { 1.1.1.2 ! root 3957: int p,q; ! 3958: ! 3959: if (live.spos[r]<0) { /* Register not yet on stack */ ! 3960: emit_byte(0xd9); ! 3961: emit_byte(0xe8); /* Push '1' on the stack, just to grow it */ ! 3962: live.tos++; ! 3963: live.spos[r]=live.tos; ! 3964: live.onstack[live.tos]=r; ! 3965: return; ! 3966: } ! 3967: /* Register is on stack */ ! 3968: if (live.tos==live.spos[r]) ! 3969: return; ! 3970: p=live.spos[r]; ! 3971: q=live.onstack[live.tos]; 1.1 root 3972: 3973: emit_byte(0xd9); 1.1.1.2 ! root 3974: emit_byte(0xc8+live.tos-live.spos[r]); /* exchange it with top of stack */ 1.1 root 3975: live.onstack[live.tos]=r; 1.1.1.2 ! root 3976: live.spos[r]=live.tos; ! 3977: live.onstack[p]=q; ! 3978: live.spos[q]=p; 1.1 root 3979: } 3980: 1.1.1.2 ! root 3981: static inline void make_tos2(int r, int r2) 1.1 root 3982: { 3983: int q; 3984: 3985: make_tos(r2); /* Put the reg that's supposed to end up in position2 3986: on top */ 3987: 3988: if (live.spos[r]<0) { /* Register not yet on stack */ 3989: make_tos(r); /* This will extend the stack */ 3990: return; 3991: } 3992: /* Register is on stack */ 3993: emit_byte(0xd9); 3994: emit_byte(0xc9); /* Move r2 into position 2 */ 3995: 3996: q=live.onstack[live.tos-1]; 3997: live.onstack[live.tos]=q; 3998: live.spos[q]=live.tos; 3999: live.onstack[live.tos-1]=r2; 4000: live.spos[r2]=live.tos-1; 4001: 4002: make_tos(r); /* And r into 1 */ 4003: } 4004: 1.1.1.2 ! root 4005: static inline int stackpos(int r) 1.1 root 4006: { 1.1.1.2 ! root 4007: if (live.spos[r]<0) ! 4008: abort(); ! 4009: if (live.tos<live.spos[r]) { ! 4010: jit_abort("Looking for spos for fnreg %d",r); ! 4011: } ! 4012: return live.tos-live.spos[r]; 1.1 root 4013: } 4014: 1.1.1.2 ! root 4015: /* IMO, calling usereg(r) makes no sense, if the register r should supply our function with ! 4016: an argument, because I would expect all arguments to be on the stack already, won't they? ! 4017: Thus, usereg(s) is always useless and also for every FRW d it's too late here now. PeterK ! 4018: */ ! 4019: static inline void usereg(int r) 1.1 root 4020: { 1.1.1.2 ! root 4021: if (live.spos[r]<0) ! 4022: make_tos(r); 1.1 root 4023: } 4024: 4025: /* This is called with one FP value in a reg *above* tos, which it will 4026: pop off the stack if necessary */ 1.1.1.2 ! root 4027: static inline void tos_make(int r) 1.1 root 4028: { 1.1.1.2 ! root 4029: if (live.spos[r]<0) { ! 4030: live.tos++; ! 4031: live.spos[r]=live.tos; ! 4032: live.onstack[live.tos]=r; ! 4033: return; ! 4034: } ! 4035: emit_byte(0xdd); ! 4036: emit_byte(0xd8+(live.tos+1)-live.spos[r]); /* store top of stack in reg, ! 4037: and pop it*/ 1.1 root 4038: } 4039: 4040: /* FP helper functions */ 4041: #if USE_NEW_RTASM 4042: #define DEFINE_OP(NAME, GEN) \ 4043: static inline void raw_##NAME(uint32 m) \ 4044: { \ 4045: GEN(m, X86_NOREG, X86_NOREG, 1); \ 4046: } 4047: DEFINE_OP(fstl, FSTLm); 4048: DEFINE_OP(fstpl, FSTPLm); 4049: DEFINE_OP(fldl, FLDLm); 4050: DEFINE_OP(fildl, FILDLm); 4051: DEFINE_OP(fistl, FISTLm); 4052: DEFINE_OP(flds, FLDSm); 4053: DEFINE_OP(fsts, FSTSm); 4054: DEFINE_OP(fstpt, FSTPTm); 4055: DEFINE_OP(fldt, FLDTm); 1.1.1.2 ! root 4056: DEFINE_OP(fistpl, FISTPLm); 1.1 root 4057: #else 4058: #define DEFINE_OP(NAME, OP1, OP2) \ 4059: static inline void raw_##NAME(uint32 m) \ 4060: { \ 4061: emit_byte(OP1); \ 4062: emit_byte(OP2); \ 4063: emit_long(m); \ 4064: } 4065: DEFINE_OP(fstl, 0xdd, 0x15); 4066: DEFINE_OP(fstpl, 0xdd, 0x1d); 4067: DEFINE_OP(fldl, 0xdd, 0x05); 4068: DEFINE_OP(fildl, 0xdb, 0x05); 4069: DEFINE_OP(fistl, 0xdb, 0x15); 4070: DEFINE_OP(flds, 0xd9, 0x05); 4071: DEFINE_OP(fsts, 0xd9, 0x15); 4072: DEFINE_OP(fstpt, 0xdb, 0x3d); 4073: DEFINE_OP(fldt, 0xdb, 0x2d); 1.1.1.2 ! root 4074: DEFINE_OP(fistpl, 0xdb, 0x1d); 1.1 root 4075: #endif 4076: #undef DEFINE_OP 4077: 4078: LOWFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) 4079: { 1.1.1.2 ! root 4080: make_tos(r); ! 4081: raw_fstl(m); 1.1 root 4082: } 4083: LENDFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) 4084: 4085: LOWFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMW m, FR r)) 4086: { 1.1.1.2 ! root 4087: make_tos(r); ! 4088: raw_fstpl(m); ! 4089: live.onstack[live.tos]=-1; ! 4090: live.tos--; ! 4091: live.spos[r]=-2; 1.1 root 4092: } 4093: LENDFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) 4094: 4095: LOWFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) 4096: { 1.1.1.2 ! root 4097: raw_fldl(m); ! 4098: tos_make(r); 1.1 root 4099: } 4100: LENDFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) 4101: 4102: LOWFUNC(NONE,READ,2,raw_fmovi_rm,(FW r, MEMR m)) 4103: { 1.1.1.2 ! root 4104: raw_fildl(m); ! 4105: tos_make(r); 1.1 root 4106: } 4107: LENDFUNC(NONE,READ,2,raw_fmovi_rm,(FW r, MEMR m)) 4108: 4109: LOWFUNC(NONE,WRITE,2,raw_fmovi_mr,(MEMW m, FR r)) 4110: { 1.1.1.2 ! root 4111: make_tos(r); ! 4112: raw_fistl(m); 1.1 root 4113: } 4114: LENDFUNC(NONE,WRITE,2,raw_fmovi_mr,(MEMW m, FR r)) 4115: 1.1.1.2 ! root 4116: LOWFUNC(NONE,WRITE,3,raw_fmovi_mrb,(MEMW m, FR r, double *bounds)) ! 4117: { ! 4118: /* Clamp value to the given range and convert to integer. */ ! 4119: ! 4120: int rs; ! 4121: usereg(r); ! 4122: rs = stackpos(r)+1; ! 4123: ! 4124: /* Lower bound onto stack */ ! 4125: raw_fldl((uintptr) &bounds[0]); /* fld double from lower */ ! 4126: ! 4127: /* Clamp to lower */ ! 4128: emit_byte(0xdb); ! 4129: emit_byte(0xf0+rs); /* fcomi lower,r */ ! 4130: emit_byte(0x73); ! 4131: emit_byte(12); /* jae to writeback */ ! 4132: ! 4133: /* Upper bound onto stack */ ! 4134: emit_byte(0xdd); ! 4135: emit_byte(0xd8); /* fstp st(0) */ ! 4136: raw_fldl((uintptr) &bounds[1]); /* fld double from upper */ ! 4137: ! 4138: /* Clamp to upper */ ! 4139: emit_byte(0xdb); ! 4140: emit_byte(0xf0+rs); /* fcomi upper,r */ ! 4141: emit_byte(0xdb); ! 4142: emit_byte(0xd0+rs); /* fcmovnbe upper,r */ ! 4143: ! 4144: /* Store to destination */ ! 4145: raw_fistpl(m); ! 4146: } ! 4147: LENDFUNC(NONE,WRITE,3,raw_fmovi_mrb,(MEMW m, FR r, double *bounds)) ! 4148: 1.1 root 4149: LOWFUNC(NONE,READ,2,raw_fmovs_rm,(FW r, MEMR m)) 4150: { 1.1.1.2 ! root 4151: raw_flds(m); ! 4152: tos_make(r); 1.1 root 4153: } 4154: LENDFUNC(NONE,READ,2,raw_fmovs_rm,(FW r, MEMR m)) 4155: 4156: LOWFUNC(NONE,WRITE,2,raw_fmovs_mr,(MEMW m, FR r)) 4157: { 1.1.1.2 ! root 4158: make_tos(r); ! 4159: raw_fsts(m); 1.1 root 4160: } 4161: LENDFUNC(NONE,WRITE,2,raw_fmovs_mr,(MEMW m, FR r)) 4162: 4163: LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) 4164: { 1.1.1.2 ! root 4165: int rs; 1.1 root 4166: 1.1.1.2 ! root 4167: /* Stupid x87 can't write a long double to mem without popping the ! 4168: stack! */ ! 4169: usereg(r); ! 4170: rs=stackpos(r); ! 4171: emit_byte(0xd9); /* Get a copy to the top of stack */ ! 4172: emit_byte(0xc0+rs); 1.1 root 4173: 1.1.1.2 ! root 4174: raw_fstpt(m); /* store and pop it */ 1.1 root 4175: } 4176: LENDFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) 4177: 4178: LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr_drop,(MEMW m, FR r)) 4179: { 1.1.1.2 ! root 4180: make_tos(r); ! 4181: raw_fstpt(m); /* store and pop it */ ! 4182: live.onstack[live.tos]=-1; ! 4183: live.tos--; ! 4184: live.spos[r]=-2; 1.1 root 4185: } 4186: LENDFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) 4187: 4188: LOWFUNC(NONE,READ,2,raw_fmov_ext_rm,(FW r, MEMR m)) 4189: { 1.1.1.2 ! root 4190: raw_fldt(m); ! 4191: tos_make(r); 1.1 root 4192: } 4193: LENDFUNC(NONE,READ,2,raw_fmov_ext_rm,(FW r, MEMR m)) 4194: 4195: LOWFUNC(NONE,NONE,1,raw_fmov_pi,(FW r)) 4196: { 1.1.1.2 ! root 4197: emit_byte(0xd9); ! 4198: emit_byte(0xeb); ! 4199: tos_make(r); 1.1 root 4200: } 4201: LENDFUNC(NONE,NONE,1,raw_fmov_pi,(FW r)) 4202: 4203: LOWFUNC(NONE,NONE,1,raw_fmov_log10_2,(FW r)) 4204: { 1.1.1.2 ! root 4205: emit_byte(0xd9); ! 4206: emit_byte(0xec); ! 4207: tos_make(r); 1.1 root 4208: } 4209: LENDFUNC(NONE,NONE,1,raw_fmov_log10_2,(FW r)) 4210: 4211: LOWFUNC(NONE,NONE,1,raw_fmov_log2_e,(FW r)) 4212: { 1.1.1.2 ! root 4213: emit_byte(0xd9); ! 4214: emit_byte(0xea); ! 4215: tos_make(r); 1.1 root 4216: } 4217: LENDFUNC(NONE,NONE,1,raw_fmov_log2_e,(FW r)) 4218: 4219: LOWFUNC(NONE,NONE,1,raw_fmov_loge_2,(FW r)) 4220: { 1.1.1.2 ! root 4221: emit_byte(0xd9); ! 4222: emit_byte(0xed); ! 4223: tos_make(r); 1.1 root 4224: } 4225: LENDFUNC(NONE,NONE,1,raw_fmov_loge_2,(FW r)) 4226: 4227: LOWFUNC(NONE,NONE,1,raw_fmov_1,(FW r)) 4228: { 1.1.1.2 ! root 4229: emit_byte(0xd9); ! 4230: emit_byte(0xe8); ! 4231: tos_make(r); 1.1 root 4232: } 4233: LENDFUNC(NONE,NONE,1,raw_fmov_1,(FW r)) 4234: 4235: LOWFUNC(NONE,NONE,1,raw_fmov_0,(FW r)) 4236: { 1.1.1.2 ! root 4237: emit_byte(0xd9); ! 4238: emit_byte(0xee); ! 4239: tos_make(r); 1.1 root 4240: } 4241: LENDFUNC(NONE,NONE,1,raw_fmov_0,(FW r)) 4242: 4243: LOWFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) 4244: { 1.1.1.2 ! root 4245: int ds; 1.1 root 4246: 1.1.1.2 ! root 4247: usereg(s); ! 4248: ds=stackpos(s); ! 4249: if (ds==0 && live.spos[d]>=0) { ! 4250: /* source is on top of stack, and we already have the dest */ ! 4251: int dd=stackpos(d); ! 4252: emit_byte(0xdd); ! 4253: emit_byte(0xd0+dd); ! 4254: } ! 4255: else { ! 4256: emit_byte(0xd9); ! 4257: emit_byte(0xc0+ds); /* duplicate source on tos */ ! 4258: tos_make(d); /* store to destination, pop if necessary */ ! 4259: } 1.1 root 4260: } 4261: LENDFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) 4262: 1.1.1.2 ! root 4263: LOWFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base)) 1.1 root 4264: { 1.1.1.2 ! root 4265: x86_64_prefix(true, false, NULL, NULL, &index); ! 4266: emit_byte(0xd9); ! 4267: emit_byte(0xa8 + index); ! 4268: emit_long(base); 1.1 root 4269: } 1.1.1.2 ! root 4270: LENDFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base)) 1.1 root 4271: 4272: LOWFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) 4273: { 1.1.1.2 ! root 4274: int ds; 1.1 root 4275: 1.1.1.2 ! root 4276: if (d!=s) { ! 4277: usereg(s); ! 4278: ds=stackpos(s); ! 4279: emit_byte(0xd9); ! 4280: emit_byte(0xc0+ds); /* duplicate source */ ! 4281: emit_byte(0xd9); ! 4282: emit_byte(0xfa); /* take square root */ ! 4283: tos_make(d); /* store to destination */ ! 4284: } ! 4285: else { ! 4286: make_tos(d); ! 4287: emit_byte(0xd9); ! 4288: emit_byte(0xfa); /* take square root */ ! 4289: } 1.1 root 4290: } 4291: LENDFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) 4292: 4293: LOWFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) 4294: { 1.1.1.2 ! root 4295: int ds; 1.1 root 4296: 1.1.1.2 ! root 4297: if (d!=s) { ! 4298: usereg(s); ! 4299: ds=stackpos(s); ! 4300: emit_byte(0xd9); ! 4301: emit_byte(0xc0+ds); /* duplicate source */ ! 4302: emit_byte(0xd9); ! 4303: emit_byte(0xe1); /* take fabs */ ! 4304: tos_make(d); /* store to destination */ ! 4305: } ! 4306: else { ! 4307: make_tos(d); ! 4308: emit_byte(0xd9); ! 4309: emit_byte(0xe1); /* take fabs */ ! 4310: } 1.1 root 4311: } 4312: LENDFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) 4313: 4314: LOWFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) 4315: { 1.1.1.2 ! root 4316: int ds; 1.1 root 4317: 1.1.1.2 ! root 4318: if (d!=s) { ! 4319: usereg(s); ! 4320: ds=stackpos(s); ! 4321: emit_byte(0xd9); ! 4322: emit_byte(0xc0+ds); /* duplicate source */ ! 4323: emit_byte(0xd9); ! 4324: emit_byte(0xfc); /* take frndint */ ! 4325: tos_make(d); /* store to destination */ ! 4326: } ! 4327: else { ! 4328: make_tos(d); ! 4329: emit_byte(0xd9); ! 4330: emit_byte(0xfc); /* take frndint */ ! 4331: } 1.1 root 4332: } 4333: LENDFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) 4334: 4335: LOWFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) 4336: { 1.1.1.2 ! root 4337: int ds; 1.1 root 4338: 1.1.1.2 ! root 4339: if (d!=s) { ! 4340: usereg(s); ! 4341: ds=stackpos(s); ! 4342: emit_byte(0xd9); ! 4343: emit_byte(0xc0+ds); /* duplicate source */ ! 4344: emit_byte(0xd9); ! 4345: emit_byte(0xff); /* take cos */ ! 4346: tos_make(d); /* store to destination */ ! 4347: } ! 4348: else { ! 4349: make_tos(d); ! 4350: emit_byte(0xd9); ! 4351: emit_byte(0xff); /* take cos */ ! 4352: } 1.1 root 4353: } 4354: LENDFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) 4355: 4356: LOWFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) 4357: { 1.1.1.2 ! root 4358: int ds; 1.1 root 4359: 1.1.1.2 ! root 4360: if (d!=s) { ! 4361: ds=stackpos(s); ! 4362: emit_byte(0xd9); ! 4363: emit_byte(0xc0+ds); /* fld x */ ! 4364: emit_byte(0xd9); ! 4365: emit_byte(0xfe); /* fsin sin(x) */ ! 4366: tos_make(d); /* store to destination */ ! 4367: } ! 4368: else { ! 4369: make_tos(d); ! 4370: emit_byte(0xd9); ! 4371: emit_byte(0xfe); /* fsin y=sin(x) */ ! 4372: } 1.1 root 4373: } 4374: LENDFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) 4375: 1.1.1.2 ! root 4376: static const double one = 1; ! 4377: 1.1 root 4378: LOWFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) 4379: { 1.1.1.2 ! root 4380: int ds; 1.1 root 4381: 1.1.1.2 ! root 4382: ds=stackpos(s); ! 4383: emit_byte(0xd9); ! 4384: emit_byte(0xc0+ds); /* fld x */ ! 4385: emit_byte(0xd9); ! 4386: emit_byte(0xfc); /* frndint int(x) */ ! 4387: emit_byte(0xd9); ! 4388: emit_byte(0xc1+ds); /* fld x again */ ! 4389: emit_byte(0xd8); ! 4390: emit_byte(0xe1); /* fsub frac(x) = x - int(x) */ ! 4391: emit_byte(0xd9); ! 4392: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 4393: x86_fadd_m((uintptr) &one); /* Add '1' without using extra stack space */ ! 4394: emit_byte(0xd9); ! 4395: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x) */ ! 4396: emit_byte(0xdd); ! 4397: emit_byte(0xd9); /* fstp copy & pop */ ! 4398: tos_make(d); /* store y=2^x */ 1.1 root 4399: } 4400: LENDFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) 4401: 4402: LOWFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) 4403: { 1.1.1.2 ! root 4404: int ds; 1.1 root 4405: 1.1.1.2 ! root 4406: if (s==d) ! 4407: make_tos(s); ! 4408: else { ! 4409: ds=stackpos(s); ! 4410: emit_byte(0xd9); ! 4411: emit_byte(0xc0+ds); /* duplicate source */ ! 4412: } ! 4413: emit_byte(0xd9); ! 4414: emit_byte(0xea); /* fldl2e log2(e) */ ! 4415: emit_byte(0xd8); ! 4416: emit_byte(0xc9); /* fmul x*log2(e) */ ! 4417: emit_byte(0xdd); ! 4418: emit_byte(0xd1); /* fst copy up */ ! 4419: emit_byte(0xd9); ! 4420: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 4421: emit_byte(0xd9); ! 4422: emit_byte(0xc9); /* fxch swap top two elements */ ! 4423: emit_byte(0xd8); ! 4424: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 4425: emit_byte(0xd9); ! 4426: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 4427: x86_fadd_m((uintptr) &one); /* Add '1' without using extra stack space */ ! 4428: emit_byte(0xd9); ! 4429: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 4430: emit_byte(0xdd); ! 4431: emit_byte(0xd9); /* fstp copy & pop */ ! 4432: if (s!=d) ! 4433: tos_make(d); /* store y=e^x */ 1.1 root 4434: } 4435: LENDFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) 1.1.1.2 ! root 4436: 1.1 root 4437: LOWFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) 4438: { 1.1.1.2 ! root 4439: int ds; 1.1 root 4440: 1.1.1.2 ! root 4441: if (s==d) ! 4442: make_tos(s); ! 4443: else { ! 4444: ds=stackpos(s); ! 4445: emit_byte(0xd9); ! 4446: emit_byte(0xc0+ds); /* duplicate source */ ! 4447: } ! 4448: emit_byte(0xd9); ! 4449: emit_byte(0xe8); /* push '1' */ ! 4450: emit_byte(0xd9); ! 4451: emit_byte(0xc9); /* swap top two */ ! 4452: emit_byte(0xd9); ! 4453: emit_byte(0xf1); /* take 1*log2(x) */ ! 4454: if (s!=d) ! 4455: tos_make(d); /* store to destination */ 1.1 root 4456: } 4457: LENDFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) 4458: 4459: 4460: LOWFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) 4461: { 1.1.1.2 ! root 4462: int ds; 1.1 root 4463: 1.1.1.2 ! root 4464: if (d!=s) { ! 4465: usereg(s); ! 4466: ds=stackpos(s); ! 4467: emit_byte(0xd9); ! 4468: emit_byte(0xc0+ds); /* duplicate source */ ! 4469: emit_byte(0xd9); ! 4470: emit_byte(0xe0); /* take fchs */ ! 4471: tos_make(d); /* store to destination */ ! 4472: } ! 4473: else { ! 4474: make_tos(d); ! 4475: emit_byte(0xd9); ! 4476: emit_byte(0xe0); /* take fchs */ ! 4477: } 1.1 root 4478: } 4479: LENDFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) 4480: 4481: LOWFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) 4482: { 1.1.1.2 ! root 4483: int ds; 1.1 root 4484: 1.1.1.2 ! root 4485: usereg(s); ! 4486: usereg(d); ! 4487: ! 4488: if (live.spos[s]==live.tos) { ! 4489: /* Source is on top of stack */ ! 4490: ds=stackpos(d); ! 4491: emit_byte(0xdc); ! 4492: emit_byte(0xc0+ds); /* add source to dest*/ ! 4493: } ! 4494: else { ! 4495: make_tos(d); ! 4496: ds=stackpos(s); ! 4497: ! 4498: emit_byte(0xd8); ! 4499: emit_byte(0xc0+ds); /* add source to dest*/ ! 4500: } 1.1 root 4501: } 4502: LENDFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) 4503: 4504: LOWFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) 4505: { 1.1.1.2 ! root 4506: int ds; 1.1 root 4507: 1.1.1.2 ! root 4508: usereg(s); ! 4509: usereg(d); ! 4510: ! 4511: if (live.spos[s]==live.tos) { ! 4512: /* Source is on top of stack */ ! 4513: ds=stackpos(d); ! 4514: emit_byte(0xdc); ! 4515: emit_byte(0xe8+ds); /* sub source from dest*/ ! 4516: } ! 4517: else { ! 4518: make_tos(d); ! 4519: ds=stackpos(s); ! 4520: ! 4521: emit_byte(0xd8); ! 4522: emit_byte(0xe0+ds); /* sub src from dest */ ! 4523: } 1.1 root 4524: } 4525: LENDFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) 4526: 4527: LOWFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) 4528: { 1.1.1.2 ! root 4529: int ds; 1.1 root 4530: 1.1.1.2 ! root 4531: usereg(s); ! 4532: usereg(d); ! 4533: ! 4534: make_tos(d); ! 4535: ds=stackpos(s); 1.1 root 4536: 1.1.1.2 ! root 4537: emit_byte(0xdd); ! 4538: emit_byte(0xe0+ds); /* cmp dest with source*/ 1.1 root 4539: } 4540: LENDFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) 4541: 4542: LOWFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) 4543: { 1.1.1.2 ! root 4544: int ds; 1.1 root 4545: 1.1.1.2 ! root 4546: usereg(s); ! 4547: usereg(d); ! 4548: ! 4549: if (live.spos[s]==live.tos) { ! 4550: /* Source is on top of stack */ ! 4551: ds=stackpos(d); ! 4552: emit_byte(0xdc); ! 4553: emit_byte(0xc8+ds); /* mul dest by source*/ ! 4554: } ! 4555: else { ! 4556: make_tos(d); ! 4557: ds=stackpos(s); ! 4558: ! 4559: emit_byte(0xd8); ! 4560: emit_byte(0xc8+ds); /* mul dest by source*/ ! 4561: } 1.1 root 4562: } 4563: LENDFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) 4564: 4565: LOWFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) 4566: { 1.1.1.2 ! root 4567: int ds; 1.1 root 4568: 1.1.1.2 ! root 4569: usereg(s); ! 4570: usereg(d); ! 4571: ! 4572: if (live.spos[s]==live.tos) { ! 4573: /* Source is on top of stack */ ! 4574: ds=stackpos(d); ! 4575: emit_byte(0xdc); ! 4576: emit_byte(0xf8+ds); /* div dest by source */ ! 4577: } ! 4578: else { ! 4579: make_tos(d); ! 4580: ds=stackpos(s); ! 4581: ! 4582: emit_byte(0xd8); ! 4583: emit_byte(0xf0+ds); /* div dest by source*/ ! 4584: } 1.1 root 4585: } 4586: LENDFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) 4587: 4588: LOWFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) 4589: { 1.1.1.2 ! root 4590: int ds; 1.1 root 4591: 1.1.1.2 ! root 4592: usereg(s); ! 4593: usereg(d); 1.1 root 4594: 1.1.1.2 ! root 4595: make_tos2(d,s); ! 4596: ds=stackpos(s); ! 4597: ! 4598: if (ds!=1) { ! 4599: printf("Failed horribly in raw_frem_rr! ds is %d\n",ds); ! 4600: abort(); ! 4601: } ! 4602: emit_byte(0xd9); ! 4603: emit_byte(0xf8); /* take rem from dest by source */ 1.1 root 4604: } 4605: LENDFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) 4606: 4607: LOWFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) 4608: { 1.1.1.2 ! root 4609: int ds; 1.1 root 4610: 1.1.1.2 ! root 4611: usereg(s); ! 4612: usereg(d); 1.1 root 4613: 1.1.1.2 ! root 4614: make_tos2(d,s); ! 4615: ds=stackpos(s); ! 4616: ! 4617: if (ds!=1) { ! 4618: printf("Failed horribly in raw_frem1_rr! ds is %d\n",ds); ! 4619: abort(); ! 4620: } ! 4621: emit_byte(0xd9); ! 4622: emit_byte(0xf5); /* take rem1 from dest by source */ 1.1 root 4623: } 4624: LENDFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) 4625: 4626: 4627: LOWFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) 4628: { 1.1.1.2 ! root 4629: make_tos(r); ! 4630: emit_byte(0xd9); /* ftst */ ! 4631: emit_byte(0xe4); 1.1 root 4632: } 4633: LENDFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) 4634: 1.1.1.2 ! root 4635: LOWFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s)) ! 4636: { ! 4637: int ds; ! 4638: ! 4639: if (s==d) ! 4640: make_tos(s); ! 4641: else { ! 4642: ds=stackpos(s); ! 4643: emit_byte(0xd9); ! 4644: emit_byte(0xc0+ds); /* fld x */ ! 4645: } ! 4646: emit_byte(0xd9); ! 4647: emit_byte(0xea); /* fldl2e log2(e) */ ! 4648: emit_byte(0xd8); ! 4649: emit_byte(0xc9); /* fmul x*log2(e) */ ! 4650: emit_byte(0xdd); ! 4651: emit_byte(0xd1); /* fst copy up */ ! 4652: emit_byte(0xd9); ! 4653: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 4654: emit_byte(0xd9); ! 4655: emit_byte(0xc9); /* fxch swap top two elements */ ! 4656: emit_byte(0xd8); ! 4657: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 4658: emit_byte(0xd9); ! 4659: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 4660: emit_byte(0xd9); ! 4661: emit_byte(0xfd); /* fscale ((2^frac(x))-1)*2^int(x*log2(e)) */ ! 4662: emit_byte(0xdd); ! 4663: emit_byte(0xd9); /* fstp copy & pop */ ! 4664: if (s!=d) ! 4665: tos_make(d); /* store y=(e^x)-1 */ ! 4666: } ! 4667: LENDFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s)) ! 4668: ! 4669: LOWFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s)) ! 4670: { ! 4671: int ds; ! 4672: ! 4673: if (s==d) ! 4674: make_tos(s); ! 4675: else { ! 4676: ds=stackpos(s); ! 4677: emit_byte(0xd9); ! 4678: emit_byte(0xc0+ds); /* fld x */ ! 4679: } ! 4680: emit_byte(0xd9); ! 4681: emit_byte(0xe9); /* fldl2t log2(10) */ ! 4682: emit_byte(0xd8); ! 4683: emit_byte(0xc9); /* fmul x*log2(10) */ ! 4684: emit_byte(0xdd); ! 4685: emit_byte(0xd1); /* fst copy up */ ! 4686: emit_byte(0xd9); ! 4687: emit_byte(0xfc); /* frndint int(x*log2(10)) */ ! 4688: emit_byte(0xd9); ! 4689: emit_byte(0xc9); /* fxch swap top two elements */ ! 4690: emit_byte(0xd8); ! 4691: emit_byte(0xe1); /* fsub x*log2(10) - int(x*log2(10)) */ ! 4692: emit_byte(0xd9); ! 4693: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 4694: x86_fadd_m((uintptr) &one); ! 4695: emit_byte(0xd9); ! 4696: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(10)) */ ! 4697: emit_byte(0xdd); ! 4698: emit_byte(0xd9); /* fstp copy & pop */ ! 4699: if (s!=d) ! 4700: tos_make(d); /* store y=10^x */ ! 4701: } ! 4702: LENDFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s)) ! 4703: ! 4704: LOWFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s)) ! 4705: { ! 4706: int ds; ! 4707: ! 4708: if (s==d) { ! 4709: //write_log (_T("FSINCOS src = dest\n")); ! 4710: make_tos(s); ! 4711: emit_byte(0xd9); ! 4712: emit_byte(0xfb); /* fsincos sin(x) push cos(x) */ ! 4713: tos_make(c); /* store cos(x) to c */ ! 4714: return; ! 4715: } ! 4716: ! 4717: ds=stackpos(s); ! 4718: emit_byte(0xd9); ! 4719: emit_byte(0xc0+ds); /* fld x */ ! 4720: emit_byte(0xd9); ! 4721: emit_byte(0xfb); /* fsincos sin(x) push cos(x) */ ! 4722: if (live.spos[c]<0) { ! 4723: if (live.spos[d]<0) { /* occupy both regs directly */ ! 4724: live.tos++; ! 4725: live.spos[d]=live.tos; ! 4726: live.onstack[live.tos]=d; /* sin(x) comes first */ ! 4727: live.tos++; ! 4728: live.spos[c]=live.tos; ! 4729: live.onstack[live.tos]=c; ! 4730: } ! 4731: else { ! 4732: emit_byte(0xd9); ! 4733: emit_byte(0xc9); /* fxch swap cos(x) with sin(x) */ ! 4734: emit_byte(0xdd); /* store sin(x) to d & pop */ ! 4735: emit_byte(0xd8+(live.tos+2)-live.spos[d]); ! 4736: live.tos++; /* occupy a reg for cos(x) here */ ! 4737: live.spos[c]=live.tos; ! 4738: live.onstack[live.tos]=c; ! 4739: } ! 4740: } ! 4741: else { ! 4742: emit_byte(0xdd); /* store cos(x) to c & pop */ ! 4743: emit_byte(0xd8+(live.tos+2)-live.spos[c]); ! 4744: tos_make(d); /* store sin(x) to destination */ ! 4745: } ! 4746: } ! 4747: LENDFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s)) ! 4748: ! 4749: LOWFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s)) ! 4750: { ! 4751: int ds; ! 4752: ! 4753: if (live.spos[d]==live.tos && live.spos[s]==live.tos-1) { ! 4754: //write_log (_T("fscale found x in TOS-1 and y in TOS\n")); ! 4755: emit_byte(0xd9); ! 4756: emit_byte(0xfd); /* fscale y*(2^x) */ ! 4757: } ! 4758: else { ! 4759: make_tos(s); /* tos=x */ ! 4760: ds=stackpos(d); ! 4761: emit_byte(0xd9); ! 4762: emit_byte(0xc0+ds); /* fld y */ ! 4763: emit_byte(0xd9); ! 4764: emit_byte(0xfd); /* fscale y*(2^x) */ ! 4765: tos_make(d); /* store y=y*(2^x) */ ! 4766: } ! 4767: } ! 4768: LENDFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s)) ! 4769: ! 4770: LOWFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s)) ! 4771: { ! 4772: int ds; ! 4773: ! 4774: if (d!=s) { ! 4775: ds=stackpos(s); ! 4776: emit_byte(0xd9); ! 4777: emit_byte(0xc0+ds); /* fld x */ ! 4778: emit_byte(0xd9); ! 4779: emit_byte(0xf2); /* fptan tan(x)=y/1.0 */ ! 4780: emit_byte(0xdd); ! 4781: emit_byte(0xd8); /* fstp pop 1.0 */ ! 4782: tos_make(d); /* store to destination */ ! 4783: } ! 4784: else { ! 4785: make_tos(d); ! 4786: emit_byte(0xd9); ! 4787: emit_byte(0xf2); /* fptan tan(x)=y/1.0 */ ! 4788: emit_byte(0xdd); ! 4789: emit_byte(0xd8); /* fstp pop 1.0 */ ! 4790: } ! 4791: } ! 4792: LENDFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s)) ! 4793: ! 4794: #ifdef CPU_x86_64 ! 4795: #define REX64() emit_byte(0x48) ! 4796: #else ! 4797: #define REX64() ! 4798: #endif ! 4799: ! 4800: LOWFUNC(NONE,NONE,1,raw_fcuts_r,(FRW r)) ! 4801: { ! 4802: make_tos(r); /* TOS = r */ ! 4803: REX64(); ! 4804: emit_byte(0x83); ! 4805: emit_byte(0xc4); ! 4806: emit_byte(0xfc); /* add -4 to esp */ ! 4807: emit_byte(0xd9); ! 4808: emit_byte(0x1c); ! 4809: emit_byte(0x24); /* fstp store r as SINGLE to [esp] and pop */ ! 4810: emit_byte(0xd9); ! 4811: emit_byte(0x04); ! 4812: emit_byte(0x24); /* fld load r as SINGLE from [esp] */ ! 4813: emit_byte(0x9b); /* let the CPU wait on FPU exceptions */ ! 4814: REX64(); ! 4815: emit_byte(0x83); ! 4816: emit_byte(0xc4); ! 4817: emit_byte(0x04); /* add +4 to esp */ ! 4818: } ! 4819: LENDFUNC(NONE,NONE,1,raw_fcuts_r,(FRW r)) ! 4820: ! 4821: LOWFUNC(NONE,NONE,1,raw_fcut_r,(FRW r)) ! 4822: { ! 4823: make_tos(r); /* TOS = r */ ! 4824: REX64(); ! 4825: emit_byte(0x83); ! 4826: emit_byte(0xc4); ! 4827: emit_byte(0xf8); /* add -8 to esp */ ! 4828: emit_byte(0xdd); ! 4829: emit_byte(0x1c); ! 4830: emit_byte(0x24); /* fstp store r as DOUBLE to [esp] and pop */ ! 4831: emit_byte(0xdd); ! 4832: emit_byte(0x04); ! 4833: emit_byte(0x24); /* fld load r as DOUBLE from [esp] */ ! 4834: emit_byte(0x9b); /* let the CPU wait on FPU exceptions */ ! 4835: REX64(); ! 4836: emit_byte(0x83); ! 4837: emit_byte(0xc4); ! 4838: emit_byte(0x08); /* add +8 to esp */ ! 4839: } ! 4840: LENDFUNC(NONE,NONE,1,raw_fcut_r,(FRW r)) ! 4841: ! 4842: LOWFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s)) ! 4843: { ! 4844: int ds; ! 4845: ! 4846: if (d!=s) { ! 4847: ds=stackpos(s); ! 4848: emit_byte(0xd9); ! 4849: emit_byte(0xc0+ds); /* fld x */ ! 4850: emit_byte(0xd9); ! 4851: emit_byte(0xf4); /* fxtract exp push man */ ! 4852: emit_byte(0xdd); ! 4853: emit_byte(0xd8); /* fstp just pop man */ ! 4854: tos_make(d); /* store exp to destination */ ! 4855: } ! 4856: else { ! 4857: make_tos(d); /* tos=x=y */ ! 4858: emit_byte(0xd9); ! 4859: emit_byte(0xf4); /* fxtract exp push man */ ! 4860: emit_byte(0xdd); ! 4861: emit_byte(0xd8); /* fstp just pop man */ ! 4862: } ! 4863: } ! 4864: LENDFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s)) ! 4865: ! 4866: LOWFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s)) ! 4867: { ! 4868: int ds; ! 4869: ! 4870: if (d!=s) { ! 4871: ds=stackpos(s); ! 4872: emit_byte(0xd9); ! 4873: emit_byte(0xc0+ds); /* fld x */ ! 4874: emit_byte(0xd9); ! 4875: emit_byte(0xf4); /* fxtract exp push man */ ! 4876: emit_byte(0xdd); ! 4877: emit_byte(0xd9); /* fstp copy man up & pop */ ! 4878: tos_make(d); /* store man to destination */ ! 4879: } ! 4880: else { ! 4881: make_tos(d); /* tos=x=y */ ! 4882: emit_byte(0xd9); ! 4883: emit_byte(0xf4); /* fxtract exp push man */ ! 4884: emit_byte(0xdd); ! 4885: emit_byte(0xd9); /* fstp copy man up & pop */ ! 4886: } ! 4887: } ! 4888: LENDFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s)) ! 4889: ! 4890: LOWFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s)) ! 4891: { ! 4892: int ds; ! 4893: ! 4894: if (s==d) ! 4895: make_tos(s); ! 4896: else { ! 4897: ds=stackpos(s); ! 4898: emit_byte(0xd9); ! 4899: emit_byte(0xc0+ds); /* fld x */ ! 4900: } ! 4901: emit_byte(0xd9); ! 4902: emit_byte(0xed); /* fldln2 logN(2) */ ! 4903: emit_byte(0xd9); ! 4904: emit_byte(0xc9); /* fxch swap logN(2) with x */ ! 4905: emit_byte(0xd9); ! 4906: emit_byte(0xf1); /* fyl2x logN(2)*log2(x) */ ! 4907: if (s!=d) ! 4908: tos_make(d); /* store y=logN(x) */ ! 4909: } ! 4910: LENDFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s)) ! 4911: ! 4912: LOWFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s)) ! 4913: { ! 4914: int ds; ! 4915: ! 4916: if (s==d) ! 4917: make_tos(s); ! 4918: else { ! 4919: ds=stackpos(s); ! 4920: emit_byte(0xd9); ! 4921: emit_byte(0xc0+ds); /* fld x */ ! 4922: } ! 4923: emit_byte(0xd9); ! 4924: emit_byte(0xed); /* fldln2 logN(2) */ ! 4925: emit_byte(0xd9); ! 4926: emit_byte(0xc9); /* fxch swap logN(2) with x */ ! 4927: emit_byte(0xd9); ! 4928: emit_byte(0xf9); /* fyl2xp1 logN(2)*log2(x+1) */ ! 4929: if (s!=d) ! 4930: tos_make(d); /* store y=logN(x+1) */ ! 4931: } ! 4932: LENDFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s)) ! 4933: ! 4934: LOWFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s)) ! 4935: { ! 4936: int ds; ! 4937: ! 4938: if (s==d) ! 4939: make_tos(s); ! 4940: else { ! 4941: ds=stackpos(s); ! 4942: emit_byte(0xd9); ! 4943: emit_byte(0xc0+ds); /* fld x */ ! 4944: } ! 4945: emit_byte(0xd9); ! 4946: emit_byte(0xec); /* fldlg2 log10(2) */ ! 4947: emit_byte(0xd9); ! 4948: emit_byte(0xc9); /* fxch swap log10(2) with x */ ! 4949: emit_byte(0xd9); ! 4950: emit_byte(0xf1); /* fyl2x log10(2)*log2(x) */ ! 4951: if (s!=d) ! 4952: tos_make(d); /* store y=log10(x) */ ! 4953: } ! 4954: LENDFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s)) ! 4955: ! 4956: LOWFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s)) ! 4957: { ! 4958: int ds; ! 4959: ! 4960: ds=stackpos(s); ! 4961: emit_byte(0xd9); ! 4962: emit_byte(0xc0+ds); /* fld x */ ! 4963: emit_byte(0xd8); ! 4964: emit_byte(0xc8); /* fmul x*x */ ! 4965: emit_byte(0xd9); ! 4966: emit_byte(0xe8); /* fld 1.0 */ ! 4967: emit_byte(0xde); ! 4968: emit_byte(0xe1); /* fsubrp 1 - (x^2) */ ! 4969: emit_byte(0xd9); ! 4970: emit_byte(0xfa); /* fsqrt sqrt(1-(x^2)) */ ! 4971: emit_byte(0xd9); ! 4972: emit_byte(0xc1+ds); /* fld x again */ ! 4973: emit_byte(0xd9); ! 4974: emit_byte(0xc9); /* fxch swap x with sqrt(1-(x^2)) */ ! 4975: emit_byte(0xd9); ! 4976: emit_byte(0xf3); /* fpatan atan(x/sqrt(1-(x^2))) & pop */ ! 4977: tos_make(d); /* store y=asin(x) */ ! 4978: } ! 4979: LENDFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s)) ! 4980: ! 4981: static uae_u32 pihalf[] = {0x2168c234, 0xc90fdaa2, 0x3fff}; // LSB=0 to get acos(1)=0 ! 4982: ! 4983: LOWFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s)) ! 4984: { ! 4985: int ds; ! 4986: ! 4987: ds=stackpos(s); ! 4988: emit_byte(0xd9); ! 4989: emit_byte(0xc0+ds); /* fld x */ ! 4990: emit_byte(0xd8); ! 4991: emit_byte(0xc8); /* fmul x*x */ ! 4992: emit_byte(0xd9); ! 4993: emit_byte(0xe8); /* fld 1.0 */ ! 4994: emit_byte(0xde); ! 4995: emit_byte(0xe1); /* fsubrp 1 - (x^2) */ ! 4996: emit_byte(0xd9); ! 4997: emit_byte(0xfa); /* fsqrt sqrt(1-(x^2)) */ ! 4998: emit_byte(0xd9); ! 4999: emit_byte(0xc1+ds); /* fld x again */ ! 5000: emit_byte(0xd9); ! 5001: emit_byte(0xc9); /* fxch swap x with sqrt(1-(x^2)) */ ! 5002: emit_byte(0xd9); ! 5003: emit_byte(0xf3); /* fpatan atan(x/sqrt(1-(x^2))) & pop */ ! 5004: raw_fldt((uintptr) &pihalf); /* fld load pi/2 from pihalf */ ! 5005: emit_byte(0xde); ! 5006: emit_byte(0xe1); /* fsubrp pi/2 - asin(x) & pop */ ! 5007: tos_make(d); /* store y=acos(x) */ ! 5008: } ! 5009: LENDFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s)) ! 5010: ! 5011: LOWFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s)) ! 5012: { ! 5013: int ds; ! 5014: ! 5015: if (s==d) ! 5016: make_tos(s); ! 5017: else { ! 5018: ds=stackpos(s); ! 5019: emit_byte(0xd9); ! 5020: emit_byte(0xc0+ds); /* fld x */ ! 5021: } ! 5022: emit_byte(0xd9); ! 5023: emit_byte(0xe8); /* fld 1.0 */ ! 5024: emit_byte(0xd9); ! 5025: emit_byte(0xf3); /* fpatan atan(x)/1 & pop*/ ! 5026: if (s!=d) ! 5027: tos_make(d); /* store y=atan(x) */ ! 5028: } ! 5029: LENDFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s)) ! 5030: ! 5031: LOWFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s)) ! 5032: { ! 5033: int ds; ! 5034: ! 5035: ds=stackpos(s); ! 5036: emit_byte(0xd9); ! 5037: emit_byte(0xc0+ds); /* fld x */ ! 5038: emit_byte(0xd9); ! 5039: emit_byte(0xe8); /* fld 1.0 */ ! 5040: emit_byte(0xdc); ! 5041: emit_byte(0xc1); /* fadd 1 + x */ ! 5042: emit_byte(0xd8); ! 5043: emit_byte(0xe2+ds); /* fsub 1 - x */ ! 5044: emit_byte(0xde); ! 5045: emit_byte(0xf9); /* fdivp (1+x)/(1-x) */ ! 5046: emit_byte(0xd9); ! 5047: emit_byte(0xed); /* fldl2e logN(2) */ ! 5048: emit_byte(0xd9); ! 5049: emit_byte(0xc9); /* fxch swap logN(2) with (1+x)/(1-x) */ ! 5050: emit_byte(0xd9); ! 5051: emit_byte(0xf1); /* fyl2x logN(2)*log2((1+x)/(1-x)) pop */ ! 5052: emit_byte(0xd9); ! 5053: emit_byte(0xe8); /* fld 1.0 */ ! 5054: emit_byte(0xd9); ! 5055: emit_byte(0xe0); /* fchs -1.0 */ ! 5056: emit_byte(0xd9); ! 5057: emit_byte(0xc9); /* fxch swap */ ! 5058: emit_byte(0xd9); ! 5059: emit_byte(0xfd); /* fscale logN((1+x)/(1-x)) * 2^(-1) */ ! 5060: emit_byte(0xdd); ! 5061: emit_byte(0xd9); /* fstp copy & pop */ ! 5062: tos_make(d); /* store y=atanh(x) */ ! 5063: } ! 5064: LENDFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s)) ! 5065: ! 5066: LOWFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s)) ! 5067: { ! 5068: int ds,tr; ! 5069: ! 5070: tr=live.onstack[live.tos+3]; ! 5071: if (s==d) ! 5072: make_tos(s); ! 5073: else { ! 5074: ds=stackpos(s); ! 5075: emit_byte(0xd9); ! 5076: emit_byte(0xc0+ds); /* fld x */ ! 5077: } ! 5078: emit_byte(0xd9); ! 5079: emit_byte(0xea); /* fldl2e log2(e) */ ! 5080: emit_byte(0xd8); ! 5081: emit_byte(0xc9); /* fmul x*log2(e) */ ! 5082: emit_byte(0xdd); ! 5083: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 5084: if (tr>=0) { ! 5085: emit_byte(0xd9); ! 5086: emit_byte(0xca); /* fxch swap with temp-reg */ ! 5087: REX64(); ! 5088: emit_byte(0x83); ! 5089: emit_byte(0xc4); ! 5090: emit_byte(0xf4); /* add -12 to esp */ ! 5091: emit_byte(0xdb); ! 5092: emit_byte(0x3c); ! 5093: emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */ ! 5094: } ! 5095: emit_byte(0xd9); ! 5096: emit_byte(0xe0); /* fchs -x*log2(e) */ ! 5097: emit_byte(0xd9); ! 5098: emit_byte(0xc0); /* fld -x*log2(e) again */ ! 5099: emit_byte(0xd9); ! 5100: emit_byte(0xfc); /* frndint int(-x*log2(e)) */ ! 5101: emit_byte(0xd9); ! 5102: emit_byte(0xc9); /* fxch swap */ ! 5103: emit_byte(0xd8); ! 5104: emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */ ! 5105: emit_byte(0xd9); ! 5106: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 5107: x86_fadd_m((uintptr) &one); ! 5108: emit_byte(0xd9); ! 5109: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 5110: emit_byte(0xd9); ! 5111: emit_byte(0xca); /* fxch swap e^-x with x*log2(e) in tr */ ! 5112: emit_byte(0xdd); ! 5113: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 5114: emit_byte(0xd9); ! 5115: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 5116: emit_byte(0xd9); ! 5117: emit_byte(0xc9); /* fxch swap */ ! 5118: emit_byte(0xd8); ! 5119: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 5120: emit_byte(0xd9); ! 5121: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 5122: x86_fadd_m((uintptr) &one); ! 5123: emit_byte(0xd9); ! 5124: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 5125: emit_byte(0xdd); ! 5126: emit_byte(0xd9); /* fstp copy e^x & pop */ ! 5127: if (tr>=0) { ! 5128: emit_byte(0xdb); ! 5129: emit_byte(0x2c); ! 5130: emit_byte(0x24); /* fld load temp-reg from [esp] */ ! 5131: emit_byte(0xd9); ! 5132: emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */ ! 5133: emit_byte(0xde); ! 5134: emit_byte(0xe9); /* fsubp (e^x)-(e^-x) */ ! 5135: REX64(); ! 5136: emit_byte(0x83); ! 5137: emit_byte(0xc4); ! 5138: emit_byte(0x0c); /* delayed add +12 to esp */ ! 5139: } ! 5140: else { ! 5141: emit_byte(0xde); ! 5142: emit_byte(0xe1); /* fsubrp (e^x)-(e^-x) */ ! 5143: } ! 5144: emit_byte(0xd9); ! 5145: emit_byte(0xe8); /* fld 1.0 */ ! 5146: emit_byte(0xd9); ! 5147: emit_byte(0xe0); /* fchs -1.0 */ ! 5148: emit_byte(0xd9); ! 5149: emit_byte(0xc9); /* fxch swap */ ! 5150: emit_byte(0xd9); ! 5151: emit_byte(0xfd); /* fscale ((e^x)-(e^-x))/2 */ ! 5152: emit_byte(0xdd); ! 5153: emit_byte(0xd9); /* fstp copy & pop */ ! 5154: if (s!=d) ! 5155: tos_make(d); /* store y=sinh(x) */ ! 5156: } ! 5157: LENDFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s)) ! 5158: ! 5159: LOWFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s)) ! 5160: { ! 5161: int ds,tr; ! 5162: ! 5163: tr=live.onstack[live.tos+3]; ! 5164: if (s==d) ! 5165: make_tos(s); ! 5166: else { ! 5167: ds=stackpos(s); ! 5168: emit_byte(0xd9); ! 5169: emit_byte(0xc0+ds); /* fld x */ ! 5170: } ! 5171: emit_byte(0xd9); ! 5172: emit_byte(0xea); /* fldl2e log2(e) */ ! 5173: emit_byte(0xd8); ! 5174: emit_byte(0xc9); /* fmul x*log2(e) */ ! 5175: emit_byte(0xdd); ! 5176: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 5177: if (tr>=0) { ! 5178: emit_byte(0xd9); ! 5179: emit_byte(0xca); /* fxch swap with temp-reg */ ! 5180: REX64(); ! 5181: emit_byte(0x83); ! 5182: emit_byte(0xc4); ! 5183: emit_byte(0xf4); /* add -12 to esp */ ! 5184: emit_byte(0xdb); ! 5185: emit_byte(0x3c); ! 5186: emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */ ! 5187: } ! 5188: emit_byte(0xd9); ! 5189: emit_byte(0xe0); /* fchs -x*log2(e) */ ! 5190: emit_byte(0xd9); ! 5191: emit_byte(0xc0); /* fld -x*log2(e) again */ ! 5192: emit_byte(0xd9); ! 5193: emit_byte(0xfc); /* frndint int(-x*log2(e)) */ ! 5194: emit_byte(0xd9); ! 5195: emit_byte(0xc9); /* fxch swap */ ! 5196: emit_byte(0xd8); ! 5197: emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */ ! 5198: emit_byte(0xd9); ! 5199: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 5200: x86_fadd_m((uintptr) &one); ! 5201: emit_byte(0xd9); ! 5202: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 5203: emit_byte(0xd9); ! 5204: emit_byte(0xca); /* fxch swap e^-x with x*log2(e) in tr */ ! 5205: emit_byte(0xdd); ! 5206: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 5207: emit_byte(0xd9); ! 5208: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 5209: emit_byte(0xd9); ! 5210: emit_byte(0xc9); /* fxch swap */ ! 5211: emit_byte(0xd8); ! 5212: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 5213: emit_byte(0xd9); ! 5214: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 5215: x86_fadd_m((uintptr) &one); ! 5216: emit_byte(0xd9); ! 5217: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 5218: emit_byte(0xdd); ! 5219: emit_byte(0xd9); /* fstp copy e^x & pop */ ! 5220: if (tr>=0) { ! 5221: emit_byte(0xdb); ! 5222: emit_byte(0x2c); ! 5223: emit_byte(0x24); /* fld load temp-reg from [esp] */ ! 5224: emit_byte(0xd9); ! 5225: emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */ ! 5226: REX64(); ! 5227: emit_byte(0x83); ! 5228: emit_byte(0xc4); ! 5229: emit_byte(0x0c); /* delayed add +12 to esp */ ! 5230: } ! 5231: emit_byte(0xde); ! 5232: emit_byte(0xc1); /* faddp (e^x)+(e^-x) */ ! 5233: emit_byte(0xd9); ! 5234: emit_byte(0xe8); /* fld 1.0 */ ! 5235: emit_byte(0xd9); ! 5236: emit_byte(0xe0); /* fchs -1.0 */ ! 5237: emit_byte(0xd9); ! 5238: emit_byte(0xc9); /* fxch swap */ ! 5239: emit_byte(0xd9); ! 5240: emit_byte(0xfd); /* fscale ((e^x)+(e^-x))/2 */ ! 5241: emit_byte(0xdd); ! 5242: emit_byte(0xd9); /* fstp copy & pop */ ! 5243: if (s!=d) ! 5244: tos_make(d); /* store y=cosh(x) */ ! 5245: } ! 5246: LENDFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s)) ! 5247: ! 5248: LOWFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s)) ! 5249: { ! 5250: int ds,tr; ! 5251: ! 5252: tr=live.onstack[live.tos+3]; ! 5253: if (s==d) ! 5254: make_tos(s); ! 5255: else { ! 5256: ds=stackpos(s); ! 5257: emit_byte(0xd9); ! 5258: emit_byte(0xc0+ds); /* fld x */ ! 5259: } ! 5260: emit_byte(0xd9); ! 5261: emit_byte(0xea); /* fldl2e log2(e) */ ! 5262: emit_byte(0xd8); ! 5263: emit_byte(0xc9); /* fmul x*log2(e) */ ! 5264: emit_byte(0xdd); ! 5265: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 5266: if (tr>=0) { ! 5267: emit_byte(0xd9); ! 5268: emit_byte(0xca); /* fxch swap with temp-reg */ ! 5269: REX64(); ! 5270: emit_byte(0x83); ! 5271: emit_byte(0xc4); ! 5272: emit_byte(0xf4); /* add -12 to esp */ ! 5273: emit_byte(0xdb); ! 5274: emit_byte(0x3c); ! 5275: emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */ ! 5276: } ! 5277: emit_byte(0xd9); ! 5278: emit_byte(0xe0); /* fchs -x*log2(e) */ ! 5279: emit_byte(0xd9); ! 5280: emit_byte(0xc0); /* fld -x*log2(e) again */ ! 5281: emit_byte(0xd9); ! 5282: emit_byte(0xfc); /* frndint int(-x*log2(e)) */ ! 5283: emit_byte(0xd9); ! 5284: emit_byte(0xc9); /* fxch swap */ ! 5285: emit_byte(0xd8); ! 5286: emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */ ! 5287: emit_byte(0xd9); ! 5288: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 5289: x86_fadd_m((uintptr) &one); ! 5290: emit_byte(0xd9); ! 5291: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 5292: emit_byte(0xd9); ! 5293: emit_byte(0xca); /* fxch swap e^-x with x*log2(e) */ ! 5294: emit_byte(0xdd); ! 5295: emit_byte(0xd1); /* fst copy x*log2(e) */ ! 5296: emit_byte(0xd9); ! 5297: emit_byte(0xfc); /* frndint int(x*log2(e)) */ ! 5298: emit_byte(0xd9); ! 5299: emit_byte(0xc9); /* fxch swap */ ! 5300: emit_byte(0xd8); ! 5301: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ ! 5302: emit_byte(0xd9); ! 5303: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ ! 5304: x86_fadd_m((uintptr) &one); ! 5305: emit_byte(0xd9); ! 5306: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ ! 5307: emit_byte(0xdd); ! 5308: emit_byte(0xd1); /* fst copy e^x */ ! 5309: emit_byte(0xd8); ! 5310: emit_byte(0xc2); /* fadd (e^x)+(e^-x) */ ! 5311: emit_byte(0xd9); ! 5312: emit_byte(0xca); /* fxch swap with e^-x */ ! 5313: emit_byte(0xde); ! 5314: emit_byte(0xe9); /* fsubp (e^x)-(e^-x) */ ! 5315: if (tr>=0) { ! 5316: emit_byte(0xdb); ! 5317: emit_byte(0x2c); ! 5318: emit_byte(0x24); /* fld load temp-reg from [esp] */ ! 5319: emit_byte(0xd9); ! 5320: emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */ ! 5321: emit_byte(0xde); ! 5322: emit_byte(0xf9); /* fdivp ((e^x)-(e^-x))/((e^x)+(e^-x)) */ ! 5323: REX64(); ! 5324: emit_byte(0x83); ! 5325: emit_byte(0xc4); ! 5326: emit_byte(0x0c); /* delayed add +12 to esp */ ! 5327: } ! 5328: else { ! 5329: emit_byte(0xde); ! 5330: emit_byte(0xf1); /* fdivrp ((e^x)-(e^-x))/((e^x)+(e^-x)) */ ! 5331: } ! 5332: if (s!=d) ! 5333: tos_make(d); /* store y=tanh(x) */ ! 5334: } ! 5335: LENDFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s)) ! 5336: 1.1 root 5337: /* %eax register is clobbered if target processor doesn't support fucomi */ 5338: #define FFLAG_NREG_CLOBBER_CONDITION !have_cmov 5339: #define FFLAG_NREG EAX_INDEX 5340: 1.1.1.2 ! root 5341: static inline void raw_fflags_into_flags(int r) 1.1 root 5342: { 1.1.1.2 ! root 5343: int p; 1.1 root 5344: 1.1.1.2 ! root 5345: usereg(r); ! 5346: p=stackpos(r); 1.1 root 5347: 1.1.1.2 ! root 5348: emit_byte(0xd9); ! 5349: emit_byte(0xee); /* Push 0 */ ! 5350: emit_byte(0xd9); ! 5351: emit_byte(0xc9+p); /* swap top two around */ 1.1 root 5352: if (have_cmov) { 5353: // gb-- fucomi is for P6 cores only, not K6-2 then... 1.1.1.2 ! root 5354: emit_byte(0xdb); ! 5355: emit_byte(0xe9+p); /* fucomi them */ 1.1 root 5356: } 5357: else { 5358: emit_byte(0xdd); 5359: emit_byte(0xe1+p); /* fucom them */ 5360: emit_byte(0x9b); 5361: emit_byte(0xdf); 5362: emit_byte(0xe0); /* fstsw ax */ 5363: raw_sahf(0); /* sahf */ 5364: } 1.1.1.2 ! root 5365: emit_byte(0xdd); ! 5366: emit_byte(0xd9+p); /* store value back, and get rid of 0 */ 1.1 root 5367: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.