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