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