|
|
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) {
1.1.1.2 ! root 644: write_log (_T("JIT: Bad register in IMUL: d=%d, s=%d\n"),d,s);
1.1 root 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) {
1.1.1.2 ! root 657: write_log (_T("JIT: Bad register in MUL: d=%d, s=%d\n"),d,s);
1.1 root 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
1.1.1.2 ! root 1723: write_log (_T("JIT: fault address is 0x%x at 0x%x\n"),addr,i);
1.1 root 1724: #endif
1725: if (!canbang || !currprefs.cachesize)
1726: return EXCEPTION_CONTINUE_SEARCH;
1727:
1728: if (in_handler)
1.1.1.2 ! root 1729: write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n"));
1.1 root 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
1.1.1.2 ! root 1803: write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size);
1.1 root 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)) {
1.1.1.2 ! root 1849: write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr);
1.1 root 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
1.1.1.2 ! root 1869: write_log (_T("JIT: Handled one access!\n"));
1.1 root 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)) {
1.1.1.2 ! root 1885: write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr);
1.1 root 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:
1.1.1.2 ! root 1896: write_log (_T("JIT: Create jump to %p\n"),veccode);
! 1897: write_log (_T("JIT: Handled one access!\n"));
1.1 root 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
1.1.1.2 ! root 1933: write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"),
1.1 root 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
1.1.1.2 ! root 1954: write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"),
1.1 root 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
1.1.1.2 ! root 1968: write_log (_T("JIT: Huh? Could not find trigger!\n"));
1.1 root 1969: #endif
1970: return EXCEPTION_CONTINUE_EXECUTION;
1971: }
1972: }
1.1.1.2 ! root 1973: write_log (_T("JIT: Can't handle access %08X!\n"), i);
1.1 root 1974: #if 0
1975: if (i)
1976: {
1977: int j;
1978:
1979: for (j=0;j<10;j++) {
1.1.1.2 ! root 1980: write_log (_T("JIT: instruction byte %2d is 0x%02x\n"),j,i[j]);
1.1 root 1981: }
1982: }
1.1.1.2 ! root 1983: write_log (_T("Please send the above info (starting at \"fault address\") to\n")
! 1984: _T("[email protected]\n")
! 1985: _T("This shouldn't happen ;-)\n"));
1.1 root 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:
1.1.1.2 ! root 2000: write_log (_T("JIT: fault address is %08x at %08x\n"),sc.cr2,sc.eip);
1.1 root 2001: if (!canbang)
1.1.1.2 ! root 2002: write_log (_T("JIT: Not happy! Canbang is 0 in SIGSEGV handler!\n"));
1.1 root 2003: if (in_handler)
1.1.1.2 ! root 2004: write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n"));
1.1 root 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;
1.1.1.2 ! root 2079: write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size);
1.1 root 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)) {
1.1.1.2 ! root 2106: write_log (_T("JIT: Suspicious address in %x SEGV handler.\n"),addr);
1.1 root 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: }
1.1.1.2 ! root 2124: write_log (_T("JIT: Handled one access!\n"));
1.1 root 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)) {
1.1.1.2 ! root 2138: write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr);
1.1 root 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);
1.1.1.2 ! root 2146: write_log (_T("JIT: Create jump to %p\n"),veccode);
1.1 root 2147:
1.1.1.2 ! root 2148: write_log (_T("JIT: Handled one access!\n"));
1.1 root 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) {
1.1.1.2 ! root 2182: write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"),
1.1 root 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) {
1.1.1.2 ! root 2201: write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"),
1.1 root 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: }
1.1.1.2 ! root 2213: write_log (_T("JIT: Huh? Could not find trigger!\n"));
1.1 root 2214: return;
2215: }
2216: }
1.1.1.2 ! root 2217: write_log (_T("JIT: Can't handle access!\n"));
1.1 root 2218: for (j=0;j<10;j++) {
1.1.1.2 ! root 2219: write_log (_T("JIT: instruction byte %2d is %02x\n"),j,i[j]);
1.1 root 2220: }
2221: #if 0
1.1.1.2 ! root 2222: write_log (_T("Please send the above info (starting at \"fault address\") to\n")
1.1 root 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);
1.1.1.2 ! root 2467: write_log (_T("CPUID level=%d, Family=%d, Model=%d, Mask=%d, Vendor=%s [%d]\n"),
1.1 root 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)
1.1.1.2 ! root 2496: write_log (_T("Target CPU defines all flags on BSF instruction\n"));
1.1 root 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;
1.1.1.2 ! root 2564: write_log (_T("Max CPUID level=%d Processor is %c%c%c%c%c%c%c%c%c%c%c%c\n"),
1.1 root 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
1.1.1.2 ! root 2592: write_log (_T("have_cmov=%d, avoid_cmov=%d, have_rat_stall=%d\n"),
1.1 root 2593: have_cmov,currprefs.avoid_cmov,have_rat_stall);
2594: if (currprefs.avoid_cmov) {
1.1.1.2 ! root 2595: write_log (_T("Disabling cmov use despite processor claiming to support it!\n"));
1.1 root 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? */
1.1.1.2 ! root 2601: write_log (_T("have_cmov=%d, have_rat_stall=%d\n"), have_cmov, have_rat_stall);
1.1 root 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]) {
1.1.1.2 ! root 2686: write_log (_T("JIT: Looking for spos for fnreg %d\n"),r);
1.1 root 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) {
1.1.1.2 ! root 2700: // write_log (_T("usereg wants to push reg %d onto the x87 stack calling make_tos\n"), r);
1.1 root 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] */
1.1.1.2 ! root 2834: emit_byte(0x9b); /* let the CPU wait on FPU exceptions */
1.1 root 2835: emit_byte(0x83);
2836: emit_byte(0xc4);
2837: emit_byte(0x04); /* add +4 to esp */
2838: }
2839: LENDFUNC(NONE,NONE,1,raw_fcuts_r,(FRW r))
2840:
2841: LOWFUNC(NONE,NONE,1,raw_fcut_r,(FRW r))
2842: {
2843: make_tos(r); /* TOS = r */
2844: emit_byte(0x83);
2845: emit_byte(0xc4);
2846: emit_byte(0xf8); /* add -8 to esp */
2847: emit_byte(0xdd);
2848: emit_byte(0x1c);
2849: emit_byte(0x24); /* fstp store r as DOUBLE to [esp] and pop */
2850: emit_byte(0xdd);
2851: emit_byte(0x04);
2852: emit_byte(0x24); /* fld load r as DOUBLE from [esp] */
1.1.1.2 ! root 2853: emit_byte(0x9b); /* let the CPU wait on FPU exceptions */
1.1 root 2854: emit_byte(0x83);
2855: emit_byte(0xc4);
2856: emit_byte(0x08); /* add +8 to esp */
2857: }
2858: LENDFUNC(NONE,NONE,1,raw_fcut_r,(FRW r))
2859:
2860: LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r))
2861: {
2862: int rs;
2863:
2864: /* Stupid x87 can't write a long double to mem without popping the
2865: stack! */
2866: usereg(r);
2867: rs=stackpos(r);
2868: emit_byte(0xd9); /* Get a copy to the top of stack */
2869: emit_byte(0xc0+rs);
2870:
2871: emit_byte(0xdb); /* store and pop it */
2872: emit_byte(0x3d);
2873: emit_long(m);
2874: }
2875: LENDFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r))
2876:
2877: LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr_drop,(MEMW m, FR r))
2878: {
2879: make_tos(r);
2880: emit_byte(0xdb); /* store and pop it */
2881: emit_byte(0x3d);
2882: emit_long(m);
2883: live.onstack[live.tos]=-1;
2884: live.tos--;
2885: live.spos[r]=-2;
2886: }
2887: LENDFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r))
2888:
2889: LOWFUNC(NONE,READ,2,raw_fmov_ext_rm,(FW r, MEMR m))
2890: {
2891: emit_byte(0xdb);
2892: emit_byte(0x2d);
2893: emit_long(m);
2894: tos_make(r);
2895: }
2896: LENDFUNC(NONE,READ,2,raw_fmov_ext_rm,(FW r, MEMR m))
2897:
2898: LOWFUNC(NONE,NONE,1,raw_fmov_pi,(FW r))
2899: {
2900: emit_byte(0xd9);
2901: emit_byte(0xeb);
2902: tos_make(r);
2903: }
2904: LENDFUNC(NONE,NONE,1,raw_fmov_pi,(FW r))
2905:
2906: LOWFUNC(NONE,NONE,1,raw_fmov_log10_2,(FW r))
2907: {
2908: emit_byte(0xd9);
2909: emit_byte(0xec);
2910: tos_make(r);
2911: }
2912: LENDFUNC(NONE,NONE,1,raw_fmov_log10_2,(FW r))
2913:
2914: LOWFUNC(NONE,NONE,1,raw_fmov_log2_e,(FW r))
2915: {
2916: emit_byte(0xd9);
2917: emit_byte(0xea);
2918: tos_make(r);
2919: }
2920: LENDFUNC(NONE,NONE,1,raw_fmov_log2_e,(FW r))
2921:
2922: LOWFUNC(NONE,NONE,1,raw_fmov_loge_2,(FW r))
2923: {
2924: emit_byte(0xd9);
2925: emit_byte(0xed);
2926: tos_make(r);
2927: }
2928: LENDFUNC(NONE,NONE,1,raw_fmov_loge_2,(FW r))
2929:
2930: LOWFUNC(NONE,NONE,1,raw_fmov_1,(FW r))
2931: {
2932: emit_byte(0xd9);
2933: emit_byte(0xe8);
2934: tos_make(r);
2935: }
2936: LENDFUNC(NONE,NONE,1,raw_fmov_1,(FW r))
2937:
2938: LOWFUNC(NONE,NONE,1,raw_fmov_0,(FW r))
2939: {
2940: emit_byte(0xd9);
2941: emit_byte(0xee);
2942: tos_make(r);
2943: }
2944: LENDFUNC(NONE,NONE,1,raw_fmov_0,(FW r))
2945:
2946: LOWFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s))
2947: {
2948: int ds;
2949:
2950: ds=stackpos(s);
2951: if (ds==0 && live.spos[d]>=0) {
2952: /* source is on top of stack, and we already have the dest */
2953: int dd=stackpos(d);
2954: emit_byte(0xdd);
2955: emit_byte(0xd0+dd);
2956: }
2957: else {
2958: emit_byte(0xd9);
2959: emit_byte(0xc0+ds); /* duplicate source on tos */
2960: tos_make(d); /* store to destination, pop if necessary */
2961: }
2962: }
2963: LENDFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s))
2964:
2965: LOWFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base))
2966: {
2967: emit_byte(0xd9);
2968: emit_byte(0xa8+index);
2969: emit_long(base);
2970: }
2971: LENDFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base))
2972:
2973: LOWFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s))
2974: {
2975: int ds;
2976:
2977: if (d!=s) {
2978: ds=stackpos(s);
2979: emit_byte(0xd9);
2980: emit_byte(0xc0+ds); /* fld x */
2981: emit_byte(0xd9);
2982: emit_byte(0xfa); /* fsqrt sqrt(x) */
2983: tos_make(d); /* store to destination */
2984: }
2985: else {
2986: make_tos(d);
2987: emit_byte(0xd9);
2988: emit_byte(0xfa); /* fsqrt y=sqrt(x) */
2989: }
2990: }
2991: LENDFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s))
2992:
2993: LOWFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s))
2994: {
2995: int ds;
2996:
2997: if (d!=s) {
2998: ds=stackpos(s);
2999: emit_byte(0xd9);
3000: emit_byte(0xc0+ds); /* fld x */
3001: emit_byte(0xd9);
3002: emit_byte(0xe1); /* fabs abs(x) */
3003: tos_make(d); /* store to destination */
3004: }
3005: else {
3006: make_tos(d);
3007: emit_byte(0xd9);
3008: emit_byte(0xe1); /* fabs y=abs(x) */
3009: }
3010: }
3011: LENDFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s))
3012:
3013: LOWFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s))
3014: {
3015: int ds;
3016:
3017: if (d!=s) {
3018: ds=stackpos(s);
3019: emit_byte(0xd9);
3020: emit_byte(0xc0+ds); /* fld x */
3021: emit_byte(0xd9);
3022: emit_byte(0xfc); /* frndint int(x) */
3023: tos_make(d); /* store to destination */
3024: }
3025: else {
3026: make_tos(d);
3027: emit_byte(0xd9);
3028: emit_byte(0xfc); /* frndint y=int(x) */
3029: }
3030: }
3031: LENDFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s))
3032:
3033: LOWFUNC(NONE,NONE,2,raw_fgetexp_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(0xf4); /* fxtract exp push man */
3043: emit_byte(0xdd);
3044: emit_byte(0xd8); /* fstp just pop man */
3045: tos_make(d); /* store exp to destination */
3046: }
3047: else {
3048: make_tos(d); /* tos=x=y */
3049: emit_byte(0xd9);
3050: emit_byte(0xf4); /* fxtract exp push man */
3051: emit_byte(0xdd);
3052: emit_byte(0xd8); /* fstp just pop man */
3053: }
3054: }
3055: LENDFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s))
3056:
3057: LOWFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s))
3058: {
3059: int ds;
3060:
3061: if (d!=s) {
3062: ds=stackpos(s);
3063: emit_byte(0xd9);
3064: emit_byte(0xc0+ds); /* fld x */
3065: emit_byte(0xd9);
3066: emit_byte(0xf4); /* fxtract exp push man */
3067: emit_byte(0xdd);
3068: emit_byte(0xd9); /* fstp copy man up & pop */
3069: tos_make(d); /* store man to destination */
3070: }
3071: else {
3072: make_tos(d); /* tos=x=y */
3073: emit_byte(0xd9);
3074: emit_byte(0xf4); /* fxtract exp push man */
3075: emit_byte(0xdd);
3076: emit_byte(0xd9); /* fstp copy man up & pop */
3077: }
3078: }
3079: LENDFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s))
3080:
3081: LOWFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s))
3082: {
3083: int ds;
3084:
3085: if (d!=s) {
3086: ds=stackpos(s);
3087: emit_byte(0xd9);
3088: emit_byte(0xc0+ds); /* fld x */
3089: emit_byte(0xd9);
3090: emit_byte(0xfe); /* fsin sin(x) */
3091: tos_make(d); /* store to destination */
3092: }
3093: else {
3094: make_tos(d);
3095: emit_byte(0xd9);
3096: emit_byte(0xfe); /* fsin y=sin(x) */
3097: }
3098: }
3099: LENDFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s))
3100:
3101: LOWFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s))
3102: {
3103: int ds;
3104:
3105: if (d!=s) {
3106: ds=stackpos(s);
3107: emit_byte(0xd9);
3108: emit_byte(0xc0+ds); /* fld x */
3109: emit_byte(0xd9);
3110: emit_byte(0xff); /* fcos cos(x) */
3111: tos_make(d); /* store to destination */
3112: }
3113: else {
3114: make_tos(d);
3115: emit_byte(0xd9);
3116: emit_byte(0xff); /* fcos y=cos(x) */
3117: }
3118: }
3119: LENDFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s))
3120:
3121: LOWFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s))
3122: {
3123: int ds;
3124:
3125: if (d!=s) {
3126: ds=stackpos(s);
3127: emit_byte(0xd9);
3128: emit_byte(0xc0+ds); /* fld x */
3129: emit_byte(0xd9);
3130: emit_byte(0xf2); /* fptan tan(x)=y/1.0 */
3131: emit_byte(0xdd);
3132: emit_byte(0xd8); /* fstp pop 1.0 */
3133: tos_make(d); /* store to destination */
3134: }
3135: else {
3136: make_tos(d);
3137: emit_byte(0xd9);
3138: emit_byte(0xf2); /* fptan tan(x)=y/1.0 */
3139: emit_byte(0xdd);
3140: emit_byte(0xd8); /* fstp pop 1.0 */
3141: }
3142: }
3143: LENDFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s))
3144:
3145: LOWFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s))
3146: {
3147: int ds;
3148:
3149: if (s==d) {
1.1.1.2 ! root 3150: //write_log (_T("FSINCOS src = dest\n"));
1.1 root 3151: make_tos(s);
3152: emit_byte(0xd9);
3153: emit_byte(0xfb); /* fsincos sin(x) push cos(x) */
3154: tos_make(c); /* store cos(x) to c */
3155: return;
3156: }
3157:
3158: ds=stackpos(s);
3159: emit_byte(0xd9);
3160: emit_byte(0xc0+ds); /* fld x */
3161: emit_byte(0xd9);
3162: emit_byte(0xfb); /* fsincos sin(x) push cos(x) */
3163: if (live.spos[c]<0) {
3164: if (live.spos[d]<0) { /* occupy both regs directly */
3165: live.tos++;
3166: live.spos[d]=live.tos;
3167: live.onstack[live.tos]=d; /* sin(x) comes first */
3168: live.tos++;
3169: live.spos[c]=live.tos;
3170: live.onstack[live.tos]=c;
3171: }
3172: else {
3173: emit_byte(0xd9);
3174: emit_byte(0xc9); /* fxch swap cos(x) with sin(x) */
3175: emit_byte(0xdd); /* store sin(x) to d & pop */
3176: emit_byte(0xd8+(live.tos+2)-live.spos[d]);
3177: live.tos++; /* occupy a reg for cos(x) here */
3178: live.spos[c]=live.tos;
3179: live.onstack[live.tos]=c;
3180: }
3181: }
3182: else {
3183: emit_byte(0xdd); /* store cos(x) to c & pop */
3184: emit_byte(0xd8+(live.tos+2)-live.spos[c]);
3185: tos_make(d); /* store sin(x) to destination */
3186: }
3187: }
3188: LENDFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s))
3189:
3190: float one=1;
3191:
3192: LOWFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s))
3193: {
3194: int ds;
3195:
3196: if (live.spos[d]==live.tos && live.spos[s]==live.tos-1) {
1.1.1.2 ! root 3197: //write_log (_T("fscale found x in TOS-1 and y in TOS\n"));
1.1 root 3198: emit_byte(0xd9);
3199: emit_byte(0xfd); /* fscale y*(2^x) */
3200: }
3201: else {
3202: make_tos(s); /* tos=x */
3203: ds=stackpos(d);
3204: emit_byte(0xd9);
3205: emit_byte(0xc0+ds); /* fld y */
3206: emit_byte(0xd9);
3207: emit_byte(0xfd); /* fscale y*(2^x) */
3208: tos_make(d); /* store y=y*(2^x) */
3209: }
3210: }
3211: LENDFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s))
3212:
3213: LOWFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s))
3214: {
3215: int ds;
3216:
3217: ds=stackpos(s);
3218: emit_byte(0xd9);
3219: emit_byte(0xc0+ds); /* fld x */
3220: emit_byte(0xd9);
3221: emit_byte(0xfc); /* frndint int(x) */
3222: emit_byte(0xd9);
3223: emit_byte(0xc1+ds); /* fld x again */
3224: emit_byte(0xd8);
3225: emit_byte(0xe1); /* fsub frac(x) = x - int(x) */
3226: emit_byte(0xd9);
3227: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3228: emit_byte(0xd8);
3229: emit_byte(0x05);
3230: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */
3231: emit_byte(0xd9);
3232: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x) */
3233: emit_byte(0xdd);
3234: emit_byte(0xd9); /* fstp copy & pop */
3235: tos_make(d); /* store y=2^x */
3236: }
3237: LENDFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s))
3238:
3239: LOWFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s))
3240: {
3241: int ds;
3242:
3243: if (s==d)
3244: make_tos(s);
3245: else {
3246: ds=stackpos(s);
3247: emit_byte(0xd9);
3248: emit_byte(0xc0+ds); /* fld x */
3249: }
3250: emit_byte(0xd9);
3251: emit_byte(0xea); /* fldl2e log2(e) */
3252: emit_byte(0xd8);
3253: emit_byte(0xc9); /* fmul x*log2(e) */
3254: emit_byte(0xdd);
3255: emit_byte(0xd1); /* fst copy up */
3256: emit_byte(0xd9);
3257: emit_byte(0xfc); /* frndint int(x*log2(e)) */
3258: emit_byte(0xd9);
3259: emit_byte(0xc9); /* fxch swap top two elements */
3260: emit_byte(0xd8);
3261: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */
3262: emit_byte(0xd9);
3263: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3264: emit_byte(0xd8);
3265: emit_byte(0x05);
3266: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */
3267: emit_byte(0xd9);
3268: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */
3269: emit_byte(0xdd);
3270: emit_byte(0xd9); /* fstp copy & pop */
3271: if (s!=d)
3272: tos_make(d); /* store y=e^x */
3273: }
3274: LENDFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s))
3275:
3276: LOWFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s))
3277: {
3278: int ds;
3279:
3280: if (s==d)
3281: make_tos(s);
3282: else {
3283: ds=stackpos(s);
3284: emit_byte(0xd9);
3285: emit_byte(0xc0+ds); /* fld x */
3286: }
3287: emit_byte(0xd9);
3288: emit_byte(0xea); /* fldl2e log2(e) */
3289: emit_byte(0xd8);
3290: emit_byte(0xc9); /* fmul x*log2(e) */
3291: emit_byte(0xdd);
3292: emit_byte(0xd1); /* fst copy up */
3293: emit_byte(0xd9);
3294: emit_byte(0xfc); /* frndint int(x*log2(e)) */
3295: emit_byte(0xd9);
3296: emit_byte(0xc9); /* fxch swap top two elements */
3297: emit_byte(0xd8);
3298: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */
3299: emit_byte(0xd9);
3300: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3301: emit_byte(0xd9);
3302: emit_byte(0xfd); /* fscale ((2^frac(x))-1)*2^int(x*log2(e)) */
3303: emit_byte(0xdd);
3304: emit_byte(0xd9); /* fstp copy & pop */
3305: if (s!=d)
3306: tos_make(d); /* store y=(e^x)-1 */
3307: }
3308: LENDFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s))
3309:
3310: LOWFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s))
3311: {
3312: int ds;
3313:
3314: if (s==d)
3315: make_tos(s);
3316: else {
3317: ds=stackpos(s);
3318: emit_byte(0xd9);
3319: emit_byte(0xc0+ds); /* fld x */
3320: }
3321: emit_byte(0xd9);
3322: emit_byte(0xe9); /* fldl2t log2(10) */
3323: emit_byte(0xd8);
3324: emit_byte(0xc9); /* fmul x*log2(10) */
3325: emit_byte(0xdd);
3326: emit_byte(0xd1); /* fst copy up */
3327: emit_byte(0xd9);
3328: emit_byte(0xfc); /* frndint int(x*log2(10)) */
3329: emit_byte(0xd9);
3330: emit_byte(0xc9); /* fxch swap top two elements */
3331: emit_byte(0xd8);
3332: emit_byte(0xe1); /* fsub x*log2(10) - int(x*log2(10)) */
3333: emit_byte(0xd9);
3334: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3335: emit_byte(0xd8);
3336: emit_byte(0x05);
3337: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */
3338: emit_byte(0xd9);
3339: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(10)) */
3340: emit_byte(0xdd);
3341: emit_byte(0xd9); /* fstp copy & pop */
3342: if (s!=d)
3343: tos_make(d); /* store y=10^x */
3344: }
3345: LENDFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s))
3346:
3347: LOWFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s))
3348: {
3349: int ds;
3350:
3351: if (s==d)
3352: make_tos(s);
3353: else {
3354: ds=stackpos(s);
3355: emit_byte(0xd9);
3356: emit_byte(0xc0+ds); /* fld x */
3357: }
3358: emit_byte(0xd9);
3359: emit_byte(0xe8); /* fld1 1 */
3360: emit_byte(0xd9);
3361: emit_byte(0xc9); /* fxch swap 1 with x */
3362: emit_byte(0xd9);
3363: emit_byte(0xf1); /* fyl2x 1*log2(x) */
3364: if (s!=d)
3365: tos_make(d); /* store y=log2(x) */
3366: }
3367: LENDFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s))
3368:
3369: LOWFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s))
3370: {
3371: int ds;
3372:
3373: if (s==d)
3374: make_tos(s);
3375: else {
3376: ds=stackpos(s);
3377: emit_byte(0xd9);
3378: emit_byte(0xc0+ds); /* fld x */
3379: }
3380: emit_byte(0xd9);
3381: emit_byte(0xed); /* fldln2 logN(2) */
3382: emit_byte(0xd9);
3383: emit_byte(0xc9); /* fxch swap logN(2) with x */
3384: emit_byte(0xd9);
3385: emit_byte(0xf1); /* fyl2x logN(2)*log2(x) */
3386: if (s!=d)
3387: tos_make(d); /* store y=logN(x) */
3388: }
3389: LENDFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s))
3390:
3391: LOWFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s))
3392: {
3393: int ds;
3394:
3395: if (s==d)
3396: make_tos(s);
3397: else {
3398: ds=stackpos(s);
3399: emit_byte(0xd9);
3400: emit_byte(0xc0+ds); /* fld x */
3401: }
3402: emit_byte(0xd9);
3403: emit_byte(0xed); /* fldln2 logN(2) */
3404: emit_byte(0xd9);
3405: emit_byte(0xc9); /* fxch swap logN(2) with x */
3406: emit_byte(0xd9);
3407: emit_byte(0xf9); /* fyl2xp1 logN(2)*log2(x+1) */
3408: if (s!=d)
3409: tos_make(d); /* store y=logN(x+1) */
3410: }
3411: LENDFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s))
3412:
3413: LOWFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s))
3414: {
3415: int ds;
3416:
3417: if (s==d)
3418: make_tos(s);
3419: else {
3420: ds=stackpos(s);
3421: emit_byte(0xd9);
3422: emit_byte(0xc0+ds); /* fld x */
3423: }
3424: emit_byte(0xd9);
3425: emit_byte(0xec); /* fldlg2 log10(2) */
3426: emit_byte(0xd9);
3427: emit_byte(0xc9); /* fxch swap log10(2) with x */
3428: emit_byte(0xd9);
3429: emit_byte(0xf1); /* fyl2x log10(2)*log2(x) */
3430: if (s!=d)
3431: tos_make(d); /* store y=log10(x) */
3432: }
3433: LENDFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s))
3434:
3435: LOWFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s))
3436: {
3437: int ds;
3438:
3439: ds=stackpos(s);
3440: emit_byte(0xd9);
3441: emit_byte(0xc0+ds); /* fld x */
3442: emit_byte(0xd8);
3443: emit_byte(0xc8); /* fmul x*x */
3444: emit_byte(0xd9);
3445: emit_byte(0xe8); /* fld 1.0 */
3446: emit_byte(0xde);
3447: emit_byte(0xe1); /* fsubrp 1 - (x^2) */
3448: emit_byte(0xd9);
3449: emit_byte(0xfa); /* fsqrt sqrt(1-(x^2)) */
3450: emit_byte(0xd9);
3451: emit_byte(0xc1+ds); /* fld x again */
3452: emit_byte(0xd9);
3453: emit_byte(0xc9); /* fxch swap x with sqrt(1-(x^2)) */
3454: emit_byte(0xd9);
3455: emit_byte(0xf3); /* fpatan atan(x/sqrt(1-(x^2))) & pop */
3456: tos_make(d); /* store y=asin(x) */
3457: }
3458: LENDFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s))
3459:
3460: static uae_u32 pihalf[] = {0x2168c234, 0xc90fdaa2, 0x3fff}; // LSB=0 to get acos(1)=0
3461: LOWFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s))
3462: {
3463: int ds;
3464:
3465: ds=stackpos(s);
3466: emit_byte(0xd9);
3467: emit_byte(0xc0+ds); /* fld x */
3468: emit_byte(0xd8);
3469: emit_byte(0xc8); /* fmul x*x */
3470: emit_byte(0xd9);
3471: emit_byte(0xe8); /* fld 1.0 */
3472: emit_byte(0xde);
3473: emit_byte(0xe1); /* fsubrp 1 - (x^2) */
3474: emit_byte(0xd9);
3475: emit_byte(0xfa); /* fsqrt sqrt(1-(x^2)) */
3476: emit_byte(0xd9);
3477: emit_byte(0xc1+ds); /* fld x again */
3478: emit_byte(0xd9);
3479: emit_byte(0xc9); /* fxch swap x with sqrt(1-(x^2)) */
3480: emit_byte(0xd9);
3481: emit_byte(0xf3); /* fpatan atan(x/sqrt(1-(x^2))) & pop */
3482: emit_byte(0xdb);
3483: emit_byte(0x2d);
3484: emit_long((uae_u32)&pihalf); /* fld load pi/2 from pihalf */
3485: emit_byte(0xde);
3486: emit_byte(0xe1); /* fsubrp pi/2 - asin(x) & pop */
3487: tos_make(d); /* store y=acos(x) */
3488: }
3489: LENDFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s))
3490:
3491: LOWFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s))
3492: {
3493: int ds;
3494:
3495: if (s==d)
3496: make_tos(s);
3497: else {
3498: ds=stackpos(s);
3499: emit_byte(0xd9);
3500: emit_byte(0xc0+ds); /* fld x */
3501: }
3502: emit_byte(0xd9);
3503: emit_byte(0xe8); /* fld 1.0 */
3504: emit_byte(0xd9);
3505: emit_byte(0xf3); /* fpatan atan(x)/1 & pop*/
3506: if (s!=d)
3507: tos_make(d); /* store y=atan(x) */
3508: }
3509: LENDFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s))
3510:
3511: LOWFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s))
3512: {
3513: int ds;
3514:
3515: ds=stackpos(s);
3516: emit_byte(0xd9);
3517: emit_byte(0xc0+ds); /* fld x */
3518: emit_byte(0xd9);
3519: emit_byte(0xe8); /* fld 1.0 */
3520: emit_byte(0xdc);
3521: emit_byte(0xc1); /* fadd 1 + x */
3522: emit_byte(0xd8);
3523: emit_byte(0xe2+ds); /* fsub 1 - x */
3524: emit_byte(0xde);
3525: emit_byte(0xf9); /* fdivp (1+x)/(1-x) */
3526: emit_byte(0xd9);
3527: emit_byte(0xed); /* fldl2e logN(2) */
3528: emit_byte(0xd9);
3529: emit_byte(0xc9); /* fxch swap logN(2) with (1+x)/(1-x) */
3530: emit_byte(0xd9);
3531: emit_byte(0xf1); /* fyl2x logN(2)*log2((1+x)/(1-x)) pop */
3532: emit_byte(0xd9);
3533: emit_byte(0xe8); /* fld 1.0 */
3534: emit_byte(0xd9);
3535: emit_byte(0xe0); /* fchs -1.0 */
3536: emit_byte(0xd9);
3537: emit_byte(0xc9); /* fxch swap */
3538: emit_byte(0xd9);
3539: emit_byte(0xfd); /* fscale logN((1+x)/(1-x)) * 2^(-1) */
3540: emit_byte(0xdd);
3541: emit_byte(0xd9); /* fstp copy & pop */
3542: tos_make(d); /* store y=atanh(x) */
3543: }
3544: LENDFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s))
3545:
3546: LOWFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s))
3547: {
3548: int ds,tr;
3549:
3550: tr=live.onstack[live.tos+3];
3551: if (s==d)
3552: make_tos(s);
3553: else {
3554: ds=stackpos(s);
3555: emit_byte(0xd9);
3556: emit_byte(0xc0+ds); /* fld x */
3557: }
3558: emit_byte(0xd9);
3559: emit_byte(0xea); /* fldl2e log2(e) */
3560: emit_byte(0xd8);
3561: emit_byte(0xc9); /* fmul x*log2(e) */
3562: emit_byte(0xdd);
3563: emit_byte(0xd1); /* fst copy x*log2(e) */
3564: if (tr>=0) {
3565: emit_byte(0xd9);
3566: emit_byte(0xca); /* fxch swap with temp-reg */
3567: emit_byte(0x83);
3568: emit_byte(0xc4);
3569: emit_byte(0xf4); /* add -12 to esp */
3570: emit_byte(0xdb);
3571: emit_byte(0x3c);
3572: emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */
3573: }
3574: emit_byte(0xd9);
3575: emit_byte(0xe0); /* fchs -x*log2(e) */
3576: emit_byte(0xd9);
3577: emit_byte(0xc0); /* fld -x*log2(e) again */
3578: emit_byte(0xd9);
3579: emit_byte(0xfc); /* frndint int(-x*log2(e)) */
3580: emit_byte(0xd9);
3581: emit_byte(0xc9); /* fxch swap */
3582: emit_byte(0xd8);
3583: emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */
3584: emit_byte(0xd9);
3585: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3586: emit_byte(0xd8);
3587: emit_byte(0x05);
3588: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */
3589: emit_byte(0xd9);
3590: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */
3591: emit_byte(0xd9);
3592: emit_byte(0xca); /* fxch swap e^-x with x*log2(e) in tr */
3593: emit_byte(0xdd);
3594: emit_byte(0xd1); /* fst copy x*log2(e) */
3595: emit_byte(0xd9);
3596: emit_byte(0xfc); /* frndint int(x*log2(e)) */
3597: emit_byte(0xd9);
3598: emit_byte(0xc9); /* fxch swap */
3599: emit_byte(0xd8);
3600: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */
3601: emit_byte(0xd9);
3602: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3603: emit_byte(0xd8);
3604: emit_byte(0x05);
3605: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */
3606: emit_byte(0xd9);
3607: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */
3608: emit_byte(0xdd);
3609: emit_byte(0xd9); /* fstp copy e^x & pop */
3610: if (tr>=0) {
3611: emit_byte(0xdb);
3612: emit_byte(0x2c);
3613: emit_byte(0x24); /* fld load temp-reg from [esp] */
3614: emit_byte(0xd9);
3615: emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */
3616: emit_byte(0xde);
3617: emit_byte(0xe9); /* fsubp (e^x)-(e^-x) */
1.1.1.2 ! root 3618: emit_byte(0x83);
! 3619: emit_byte(0xc4);
! 3620: emit_byte(0x0c); /* delayed add +12 to esp */
1.1 root 3621: }
3622: else {
3623: emit_byte(0xde);
3624: emit_byte(0xe1); /* fsubrp (e^x)-(e^-x) */
3625: }
3626: emit_byte(0xd9);
3627: emit_byte(0xe8); /* fld 1.0 */
3628: emit_byte(0xd9);
3629: emit_byte(0xe0); /* fchs -1.0 */
3630: emit_byte(0xd9);
3631: emit_byte(0xc9); /* fxch swap */
3632: emit_byte(0xd9);
3633: emit_byte(0xfd); /* fscale ((e^x)-(e^-x))/2 */
3634: emit_byte(0xdd);
3635: emit_byte(0xd9); /* fstp copy & pop */
3636: if (s!=d)
3637: tos_make(d); /* store y=sinh(x) */
3638: }
3639: LENDFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s))
3640:
3641: LOWFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s))
3642: {
3643: int ds,tr;
3644:
3645: tr=live.onstack[live.tos+3];
3646: if (s==d)
3647: make_tos(s);
3648: else {
3649: ds=stackpos(s);
3650: emit_byte(0xd9);
3651: emit_byte(0xc0+ds); /* fld x */
3652: }
3653: emit_byte(0xd9);
3654: emit_byte(0xea); /* fldl2e log2(e) */
3655: emit_byte(0xd8);
3656: emit_byte(0xc9); /* fmul x*log2(e) */
3657: emit_byte(0xdd);
3658: emit_byte(0xd1); /* fst copy x*log2(e) */
3659: if (tr>=0) {
3660: emit_byte(0xd9);
3661: emit_byte(0xca); /* fxch swap with temp-reg */
3662: emit_byte(0x83);
3663: emit_byte(0xc4);
3664: emit_byte(0xf4); /* add -12 to esp */
3665: emit_byte(0xdb);
3666: emit_byte(0x3c);
3667: emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */
3668: }
3669: emit_byte(0xd9);
3670: emit_byte(0xe0); /* fchs -x*log2(e) */
3671: emit_byte(0xd9);
3672: emit_byte(0xc0); /* fld -x*log2(e) again */
3673: emit_byte(0xd9);
3674: emit_byte(0xfc); /* frndint int(-x*log2(e)) */
3675: emit_byte(0xd9);
3676: emit_byte(0xc9); /* fxch swap */
3677: emit_byte(0xd8);
3678: emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */
3679: emit_byte(0xd9);
3680: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3681: emit_byte(0xd8);
3682: emit_byte(0x05);
3683: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */
3684: emit_byte(0xd9);
3685: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */
3686: emit_byte(0xd9);
3687: emit_byte(0xca); /* fxch swap e^-x with x*log2(e) in tr */
3688: emit_byte(0xdd);
3689: emit_byte(0xd1); /* fst copy x*log2(e) */
3690: emit_byte(0xd9);
3691: emit_byte(0xfc); /* frndint int(x*log2(e)) */
3692: emit_byte(0xd9);
3693: emit_byte(0xc9); /* fxch swap */
3694: emit_byte(0xd8);
3695: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */
3696: emit_byte(0xd9);
3697: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3698: emit_byte(0xd8);
3699: emit_byte(0x05);
3700: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */
3701: emit_byte(0xd9);
3702: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */
3703: emit_byte(0xdd);
3704: emit_byte(0xd9); /* fstp copy e^x & pop */
3705: if (tr>=0) {
3706: emit_byte(0xdb);
3707: emit_byte(0x2c);
3708: emit_byte(0x24); /* fld load temp-reg from [esp] */
3709: emit_byte(0xd9);
3710: emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */
1.1.1.2 ! root 3711: emit_byte(0x83);
! 3712: emit_byte(0xc4);
! 3713: emit_byte(0x0c); /* delayed add +12 to esp */
1.1 root 3714: }
3715: emit_byte(0xde);
3716: emit_byte(0xc1); /* faddp (e^x)+(e^-x) */
3717: emit_byte(0xd9);
3718: emit_byte(0xe8); /* fld 1.0 */
3719: emit_byte(0xd9);
3720: emit_byte(0xe0); /* fchs -1.0 */
3721: emit_byte(0xd9);
3722: emit_byte(0xc9); /* fxch swap */
3723: emit_byte(0xd9);
3724: emit_byte(0xfd); /* fscale ((e^x)+(e^-x))/2 */
3725: emit_byte(0xdd);
3726: emit_byte(0xd9); /* fstp copy & pop */
3727: if (s!=d)
3728: tos_make(d); /* store y=cosh(x) */
3729: }
3730: LENDFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s))
3731:
3732: LOWFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s))
3733: {
3734: int ds,tr;
3735:
3736: tr=live.onstack[live.tos+3];
3737: if (s==d)
3738: make_tos(s);
3739: else {
3740: ds=stackpos(s);
3741: emit_byte(0xd9);
3742: emit_byte(0xc0+ds); /* fld x */
3743: }
3744: emit_byte(0xd9);
3745: emit_byte(0xea); /* fldl2e log2(e) */
3746: emit_byte(0xd8);
3747: emit_byte(0xc9); /* fmul x*log2(e) */
3748: emit_byte(0xdd);
3749: emit_byte(0xd1); /* fst copy x*log2(e) */
3750: if (tr>=0) {
3751: emit_byte(0xd9);
3752: emit_byte(0xca); /* fxch swap with temp-reg */
3753: emit_byte(0x83);
3754: emit_byte(0xc4);
3755: emit_byte(0xf4); /* add -12 to esp */
3756: emit_byte(0xdb);
3757: emit_byte(0x3c);
3758: emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */
3759: }
3760: emit_byte(0xd9);
3761: emit_byte(0xe0); /* fchs -x*log2(e) */
3762: emit_byte(0xd9);
3763: emit_byte(0xc0); /* fld -x*log2(e) again */
3764: emit_byte(0xd9);
3765: emit_byte(0xfc); /* frndint int(-x*log2(e)) */
3766: emit_byte(0xd9);
3767: emit_byte(0xc9); /* fxch swap */
3768: emit_byte(0xd8);
3769: emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */
3770: emit_byte(0xd9);
3771: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3772: emit_byte(0xd8);
3773: emit_byte(0x05);
3774: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */
3775: emit_byte(0xd9);
3776: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */
3777: emit_byte(0xd9);
3778: emit_byte(0xca); /* fxch swap e^-x with x*log2(e) */
3779: emit_byte(0xdd);
3780: emit_byte(0xd1); /* fst copy x*log2(e) */
3781: emit_byte(0xd9);
3782: emit_byte(0xfc); /* frndint int(x*log2(e)) */
3783: emit_byte(0xd9);
3784: emit_byte(0xc9); /* fxch swap */
3785: emit_byte(0xd8);
3786: emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */
3787: emit_byte(0xd9);
3788: emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */
3789: emit_byte(0xd8);
3790: emit_byte(0x05);
3791: emit_long((uae_u32)&one); /* fadd (2^frac(x))-1 + 1 */
3792: emit_byte(0xd9);
3793: emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */
3794: emit_byte(0xdd);
3795: emit_byte(0xd1); /* fst copy e^x */
3796: emit_byte(0xd8);
3797: emit_byte(0xc2); /* fadd (e^x)+(e^-x) */
3798: emit_byte(0xd9);
3799: emit_byte(0xca); /* fxch swap with e^-x */
3800: emit_byte(0xde);
3801: emit_byte(0xe9); /* fsubp (e^x)-(e^-x) */
3802: if (tr>=0) {
3803: emit_byte(0xdb);
3804: emit_byte(0x2c);
3805: emit_byte(0x24); /* fld load temp-reg from [esp] */
3806: emit_byte(0xd9);
3807: emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */
3808: emit_byte(0xde);
3809: emit_byte(0xf9); /* fdivp ((e^x)-(e^-x))/((e^x)+(e^-x)) */
1.1.1.2 ! root 3810: emit_byte(0x83);
! 3811: emit_byte(0xc4);
! 3812: emit_byte(0x0c); /* delayed add +12 to esp */
1.1 root 3813: }
3814: else {
3815: emit_byte(0xde);
3816: emit_byte(0xf1); /* fdivrp ((e^x)-(e^-x))/((e^x)+(e^-x)) */
3817: }
3818: if (s!=d)
3819: tos_make(d); /* store y=tanh(x) */
3820: }
3821: LENDFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s))
3822:
3823: LOWFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s))
3824: {
3825: int ds;
3826:
3827: if (d!=s) {
3828: ds=stackpos(s);
3829: emit_byte(0xd9);
3830: emit_byte(0xc0+ds); /* duplicate source */
3831: emit_byte(0xd9);
3832: emit_byte(0xe0); /* take fchs */
3833: tos_make(d); /* store to destination */
3834: }
3835: else {
3836: make_tos(d);
3837: emit_byte(0xd9);
3838: emit_byte(0xe0); /* take fchs */
3839: }
3840: }
3841: LENDFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s))
3842:
3843: LOWFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s))
3844: {
3845: int ds;
3846:
3847: if (live.spos[s]==live.tos) {
3848: /* Source is on top of stack */
3849: ds=stackpos(d);
3850: emit_byte(0xdc);
3851: emit_byte(0xc0+ds); /* add source to dest*/
3852: }
3853: else {
3854: make_tos(d);
3855: ds=stackpos(s);
3856:
3857: emit_byte(0xd8);
3858: emit_byte(0xc0+ds); /* add source to dest*/
3859: }
3860: }
3861: LENDFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s))
3862:
3863: LOWFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s))
3864: {
3865: int ds;
3866:
3867: if (live.spos[s]==live.tos) {
3868: /* Source is on top of stack */
3869: ds=stackpos(d);
3870: emit_byte(0xdc);
3871: emit_byte(0xe8+ds); /* sub source from dest*/
3872: }
3873: else {
3874: make_tos(d);
3875: ds=stackpos(s);
3876:
3877: emit_byte(0xd8);
3878: emit_byte(0xe0+ds); /* sub src from dest */
3879: }
3880: }
3881: LENDFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s))
3882:
3883: LOWFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s))
3884: {
3885: int ds;
3886:
3887: make_tos(d);
3888: ds=stackpos(s);
3889:
3890: emit_byte(0xdd);
3891: emit_byte(0xe0+ds); /* cmp dest with source*/
3892: }
3893: LENDFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s))
3894:
3895: LOWFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s))
3896: {
3897: int ds;
3898:
3899: if (live.spos[s]==live.tos) {
3900: /* Source is on top of stack */
3901: ds=stackpos(d);
3902: emit_byte(0xdc);
3903: emit_byte(0xc8+ds); /* mul dest by source*/
3904: }
3905: else {
3906: make_tos(d);
3907: ds=stackpos(s);
3908:
3909: emit_byte(0xd8);
3910: emit_byte(0xc8+ds); /* mul dest by source*/
3911: }
3912: }
3913: LENDFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s))
3914:
3915: LOWFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s))
3916: {
3917: int ds;
3918:
3919: if (live.spos[s]==live.tos) {
3920: /* Source is on top of stack */
3921: ds=stackpos(d);
3922: emit_byte(0xdc);
3923: emit_byte(0xf8+ds); /* div dest by source */
3924: }
3925: else {
3926: make_tos(d);
3927: ds=stackpos(s);
3928:
3929: emit_byte(0xd8);
3930: emit_byte(0xf0+ds); /* div dest by source*/
3931: }
3932: }
3933: LENDFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s))
3934:
3935: LOWFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s))
3936: {
3937: int ds;
3938:
3939: if (live.spos[d]==live.tos && live.spos[s]==live.tos-1) {
1.1.1.2 ! root 3940: //write_log (_T("frem found x in TOS-1 and y in TOS\n"));
1.1 root 3941: emit_byte(0xd9);
3942: emit_byte(0xf8); /* fprem rem(y/x) */
3943: }
3944: else {
3945: make_tos(s); /* tos=x */
3946: ds=stackpos(d);
3947: emit_byte(0xd9);
3948: emit_byte(0xc0+ds); /* fld y */
3949: emit_byte(0xd9);
3950: emit_byte(0xf8); /* fprem rem(y/x) */
3951: tos_make(d); /* store y=rem(y/x) */
3952: }
3953: }
3954: LENDFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s))
3955:
3956: LOWFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s))
3957: {
3958: int ds;
3959:
3960: if (live.spos[d]==live.tos && live.spos[s]==live.tos-1) {
1.1.1.2 ! root 3961: //write_log (_T("frem1 found x in TOS-1 and y in TOS\n"));
1.1 root 3962: emit_byte(0xd9);
3963: emit_byte(0xf5); /* fprem1 rem1(y/x) */
3964: }
3965: else {
3966: make_tos(s); /* tos=x */
3967: ds=stackpos(d);
3968: emit_byte(0xd9);
3969: emit_byte(0xc0+ds); /* fld y */
3970: emit_byte(0xd9);
3971: emit_byte(0xf5); /* fprem1 rem1(y/x) */
3972: tos_make(d); /* store y=rem(y/x) */
3973: }
3974: }
3975: LENDFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s))
3976:
3977: LOWFUNC(NONE,NONE,1,raw_ftst_r,(FR r))
3978: {
3979: make_tos(r);
3980: emit_byte(0xd9); /* ftst */
3981: emit_byte(0xe4);
3982: }
3983: LENDFUNC(NONE,NONE,1,raw_ftst_r,(FR r))
3984:
3985: STATIC_INLINE void raw_fflags_into_flags(int r)
3986: {
3987: int p;
3988:
3989: usereg(r);
3990: p=stackpos(r);
3991:
3992: emit_byte(0xd9);
3993: emit_byte(0xee); /* Push 0 */
3994: emit_byte(0xd9);
3995: emit_byte(0xc9+p); /* swap top two around */
3996: if (have_cmov) {
3997: // gb-- fucomi is for P6 cores only, not K6-2 then...
3998: emit_byte(0xdb);
3999: emit_byte(0xe9+p); /* fucomi them */
4000: }
4001: else {
4002: emit_byte(0xdd);
4003: emit_byte(0xe1+p); /* fucom them */
4004: emit_byte(0x9b);
4005: emit_byte(0xdf);
4006: emit_byte(0xe0); /* fstsw ax */
4007: raw_sahf(0); /* sahf */
4008: }
4009: emit_byte(0xdd);
4010: emit_byte(0xd9+p); /* store value back, and get rid of 0 */
4011: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.