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