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