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