ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp
Revision: 1.2
Committed: 2002-10-03T14:58:02Z (22 years, 2 months ago) by gbeauche
Branch: MAIN
Changes since 1.1: +0 -4 lines
Log Message:
Do translate FMUL instructions, the core needs to be fixed and this is
not translation of that instruction. I believe this is related to some
misgeneration of FPU core sequence and allocation of FP registers?

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * UAE - The Un*x Amiga Emulator
3     *
4     * MC68881 emulation
5     *
6     * Copyright 1996 Herman ten Brugge
7     * Adapted for JIT compilation (c) Bernd Meyer, 2000
8     */
9    
10     #include "sysdeps.h"
11    
12     #include <math.h>
13     #include <stdio.h>
14    
15     #include "memory.h"
16     #include "readcpu.h"
17     #include "newcpu.h"
18     #include "main.h"
19     #include "compiler/compemu.h"
20     #include "fpu/fpu.h"
21     #include "fpu/flags.h"
22     #include "fpu/exceptions.h"
23     #include "fpu/rounding.h"
24    
25     #define DEBUG 0
26     #include "debug.h"
27    
28     // gb-- WARNING: get_fpcr() and set_fpcr() support is experimental
29     #define HANDLE_FPCR 0
30    
31     // - IEEE-based fpu core must be used
32     #if defined(FPU_IEEE)
33     # define CAN_HANDLE_FPCR
34     #endif
35    
36     // - Generic rounding mode and precision modes are supported if set together
37     #if defined(FPU_USE_GENERIC_ROUNDING_MODE) && defined(FPU_USE_GENERIC_ROUNDING_PRECISION)
38     # define CAN_HANDLE_FPCR
39     #endif
40    
41     // - X86 rounding mode and precision modes are *not* supported but might work (?!)
42     #if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
43     # define CAN_HANDLE_FPCR
44     #endif
45    
46     #if HANDLE_FPCR && !defined(CAN_HANDLE_FPCR)
47     # warning "Can't handle FPCR, will FAIL(1) at runtime"
48     # undef HANDLE_FPCR
49     # define HANDLE_FPCR 0
50     #endif
51    
52     #define STATIC_INLINE static inline
53     #define MAKE_FPSR(r) do { fmov_rr(FP_RESULT,r); } while (0)
54    
55     #define delay nop() ;nop()
56     #define delay2 nop() ;nop()
57    
58     #define UNKNOWN_EXTRA 0xFFFFFFFF
59     static void fpuop_illg(uae_u32 opcode, uae_u32 extra)
60     {
61     /*
62     if (extra == UNKNOWN_EXTRA)
63     printf("FPU opcode %x, extra UNKNOWN_EXTRA\n",opcode & 0xFFFF);
64     else
65     printf("FPU opcode %x, extra %x\n",opcode & 0xFFFF,extra & 0xFFFF);
66     */
67     op_illg(opcode);
68     }
69    
70     uae_s32 temp_fp[3]; /* To convert between FP/integer */
71    
72     /* return register number, or -1 for failure */
73     STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra)
74     {
75     uaecptr tmppc;
76     uae_u16 tmp;
77     int size;
78     int mode;
79     int reg;
80     double* src;
81     uae_u32 ad = 0;
82     static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
83     static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
84    
85     if ((extra & 0x4000) == 0) {
86     return ((extra >> 10) & 7);
87     }
88    
89     mode = (opcode >> 3) & 7;
90     reg = opcode & 7;
91     size = (extra >> 10) & 7;
92     switch (mode) {
93     case 0:
94     switch (size) {
95     case 6:
96     sign_extend_8_rr(S1,reg);
97     mov_l_mr((uae_u32)temp_fp,S1);
98     delay2;
99     fmovi_rm(FS1,(uae_u32)temp_fp);
100     return FS1;
101     case 4:
102     sign_extend_16_rr(S1,reg);
103     mov_l_mr((uae_u32)temp_fp,S1);
104     delay2;
105     fmovi_rm(FS1,(uae_u32)temp_fp);
106     return FS1;
107     case 0:
108     mov_l_mr((uae_u32)temp_fp,reg);
109     delay2;
110     fmovi_rm(FS1,(uae_u32)temp_fp);
111     return FS1;
112     case 1:
113     mov_l_mr((uae_u32)temp_fp,reg);
114     delay2;
115     fmovs_rm(FS1,(uae_u32)temp_fp);
116     return FS1;
117     default:
118     return -1;
119     }
120     return -1; /* Should be unreachable */
121     case 1:
122     return -1; /* Genuine invalid instruction */
123     default:
124     break;
125     }
126     /* OK, we *will* have to load something from an address. Let's make
127     sure we know how to handle that, or quit early --- i.e. *before*
128     we do any postincrement/predecrement that we may regret */
129    
130     switch (size) {
131     case 3:
132     return -1;
133     case 0:
134     case 1:
135     case 2:
136     case 4:
137     case 5:
138     case 6:
139     break;
140     default:
141     return -1;
142     }
143    
144     switch (mode) {
145     case 2:
146     ad=S1; /* We will change it, anyway ;-) */
147     mov_l_rr(ad,reg+8);
148     break;
149     case 3:
150     ad=S1;
151     mov_l_rr(ad,reg+8);
152     lea_l_brr(reg+8,reg+8,(reg == 7?sz2[size]:sz1[size]));
153     break;
154     case 4:
155     ad=S1;
156    
157     lea_l_brr(reg+8,reg+8,-(reg == 7?sz2[size]:sz1[size]));
158     mov_l_rr(ad,reg+8);
159     break;
160     case 5:
161     {
162     uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
163     ad=S1;
164     mov_l_rr(ad,reg+8);
165     lea_l_brr(ad,ad,off);
166     break;
167     }
168     case 6:
169     {
170     uae_u32 dp=comp_get_iword((m68k_pc_offset+=2)-2);
171     ad=S1;
172     calc_disp_ea_020(reg+8,dp,ad,S2);
173     break;
174     }
175     case 7:
176     switch (reg) {
177     case 0:
178     {
179     uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
180     ad=S1;
181     mov_l_ri(ad,off);
182     break;
183     }
184     case 1:
185     {
186     uae_u32 off=comp_get_ilong((m68k_pc_offset+=4)-4);
187     ad=S1;
188     mov_l_ri(ad,off);
189     break;
190     }
191     case 2:
192     {
193     uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+
194     m68k_pc_offset;
195     uae_s32 PC16off =(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)
196     -2);
197     ad=S1;
198     mov_l_ri(ad,address+PC16off);
199     break;
200     }
201     case 3:
202     return -1;
203     tmppc = m68k_getpc ();
204     tmp = next_iword ();
205     ad = get_disp_ea_020 (tmppc, tmp);
206     break;
207     case 4:
208     {
209     uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ m68k_pc_offset;
210     ad=S1;
211     // Immediate addressing mode && Operation Length == Byte ->
212     // Use the low-order byte of the extension word.
213     if (size == 6) address++;
214     mov_l_ri(ad,address);
215     m68k_pc_offset+=sz2[size];
216     break;
217     }
218     default:
219     return -1;
220     }
221     }
222    
223     switch (size) {
224     case 0:
225     readlong(ad,S2,S3);
226     mov_l_mr((uae_u32)temp_fp,S2);
227     delay2;
228     fmovi_rm(FS1,(uae_u32)temp_fp);
229     break;
230     case 1:
231     readlong(ad,S2,S3);
232     mov_l_mr((uae_u32)temp_fp,S2);
233     delay2;
234     fmovs_rm(FS1,(uae_u32)temp_fp);
235     break;
236     case 2:
237     readword(ad,S2,S3);
238     mov_w_mr(((uae_u32)temp_fp)+8,S2);
239     add_l_ri(ad,4);
240     readlong(ad,S2,S3);
241     mov_l_mr((uae_u32)(temp_fp)+4,S2);
242     add_l_ri(ad,4);
243     readlong(ad,S2,S3);
244     mov_l_mr((uae_u32)(temp_fp),S2);
245     delay2;
246     fmov_ext_rm(FS1,(uae_u32)(temp_fp));
247     break;
248     case 3:
249     return -1; /* Some silly "packed" stuff */
250     case 4:
251     readword(ad,S2,S3);
252     sign_extend_16_rr(S2,S2);
253     mov_l_mr((uae_u32)temp_fp,S2);
254     delay2;
255     fmovi_rm(FS1,(uae_u32)temp_fp);
256     break;
257     case 5:
258     readlong(ad,S2,S3);
259     mov_l_mr(((uae_u32)temp_fp)+4,S2);
260     add_l_ri(ad,4);
261     readlong(ad,S2,S3);
262     mov_l_mr((uae_u32)(temp_fp),S2);
263     delay2;
264     fmov_rm(FS1,(uae_u32)(temp_fp));
265     break;
266     case 6:
267     readbyte(ad,S2,S3);
268     sign_extend_8_rr(S2,S2);
269     mov_l_mr((uae_u32)temp_fp,S2);
270     delay2;
271     fmovi_rm(FS1,(uae_u32)temp_fp);
272     break;
273     default:
274     return -1;
275     }
276     return FS1;
277     }
278    
279     /* return of -1 means failure, >=0 means OK */
280     STATIC_INLINE int put_fp_value (int val, uae_u32 opcode, uae_u16 extra)
281     {
282     uae_u16 tmp;
283     uaecptr tmppc;
284     int size;
285     int mode;
286     int reg;
287     uae_u32 ad;
288     static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
289     static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
290    
291     if ((extra & 0x4000) == 0) {
292     const int dest_reg = (extra >> 10) & 7;
293     fmov_rr(dest_reg, val);
294     // gb-- status register is affected
295     MAKE_FPSR(dest_reg);
296     return 0;
297     }
298    
299     mode = (opcode >> 3) & 7;
300     reg = opcode & 7;
301     size = (extra >> 10) & 7;
302     ad = (uae_u32)-1;
303     switch (mode) {
304     case 0:
305     switch (size) {
306     case 6:
307     fmovi_mr((uae_u32)temp_fp,val);
308     delay;
309     mov_b_rm(reg,(uae_u32)temp_fp);
310     return 0;
311     case 4:
312     fmovi_mr((uae_u32)temp_fp,val);
313     delay;
314     mov_w_rm(reg,(uae_u32)temp_fp);
315     return 0;
316     case 0:
317     fmovi_mr((uae_u32)temp_fp,val);
318     delay;
319     mov_l_rm(reg,(uae_u32)temp_fp);
320     return 0;
321     case 1:
322     fmovs_mr((uae_u32)temp_fp,val);
323     delay;
324     mov_l_rm(reg,(uae_u32)temp_fp);
325     return 0;
326     default:
327     return -1;
328     }
329     case 1:
330     return -1; /* genuine invalid instruction */
331     default: break;
332     }
333    
334     /* Let's make sure we get out *before* doing something silly if
335     we can't handle the size */
336     switch (size) {
337     case 0:
338     case 4:
339     case 5:
340     case 6:
341     case 2:
342     case 1:
343     break;
344     case 3:
345     default:
346     return -1;
347     }
348    
349     switch (mode) {
350     case 2:
351     ad=S1;
352     mov_l_rr(ad,reg+8);
353     break;
354     case 3:
355     ad=S1;
356     mov_l_rr(ad,reg+8);
357     lea_l_brr(reg+8,reg+8,(reg == 7?sz2[size]:sz1[size]));
358     break;
359     case 4:
360     ad=S1;
361     lea_l_brr(reg+8,reg+8,-(reg == 7?sz2[size]:sz1[size]));
362     mov_l_rr(ad,reg+8);
363     break;
364     case 5:
365     {
366     uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
367     ad=S1;
368     mov_l_rr(ad,reg+8);
369     add_l_ri(ad,off);
370     break;
371     }
372     case 6:
373     {
374     uae_u32 dp=comp_get_iword((m68k_pc_offset+=2)-2);
375     ad=S1;
376     calc_disp_ea_020(reg+8,dp,ad,S2);
377     break;
378     }
379     case 7:
380     switch (reg) {
381     case 0:
382     {
383     uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
384     ad=S1;
385     mov_l_ri(ad,off);
386     break;
387     }
388     case 1:
389     {
390     uae_u32 off=comp_get_ilong((m68k_pc_offset+=4)-4);
391     ad=S1;
392     mov_l_ri(ad,off);
393     break;
394     }
395     case 2:
396     {
397     uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+
398     m68k_pc_offset;
399     uae_s32 PC16off =(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
400     ad=S1;
401     mov_l_ri(ad,address+PC16off);
402     break;
403     }
404     case 3:
405     return -1;
406     tmppc = m68k_getpc ();
407     tmp = next_iword ();
408     ad = get_disp_ea_020 (tmppc, tmp);
409     break;
410     case 4:
411     {
412     uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+
413     m68k_pc_offset;
414     ad=S1;
415     mov_l_ri(ad,address);
416     m68k_pc_offset+=sz2[size];
417     break;
418     }
419     default:
420     return -1;
421     }
422     }
423     switch (size) {
424     case 0:
425     fmovi_mr((uae_u32)temp_fp,val);
426     delay;
427     mov_l_rm(S2,(uae_u32)temp_fp);
428     writelong_clobber(ad,S2,S3);
429     break;
430     case 1:
431     fmovs_mr((uae_u32)temp_fp,val);
432     delay;
433     mov_l_rm(S2,(uae_u32)temp_fp);
434     writelong_clobber(ad,S2,S3);
435     break;
436     case 2:
437     fmov_ext_mr((uae_u32)temp_fp,val);
438     delay;
439     mov_w_rm(S2,(uae_u32)temp_fp+8);
440     writeword_clobber(ad,S2,S3);
441     add_l_ri(ad,4);
442     mov_l_rm(S2,(uae_u32)temp_fp+4);
443     writelong_clobber(ad,S2,S3);
444     add_l_ri(ad,4);
445     mov_l_rm(S2,(uae_u32)temp_fp);
446     writelong_clobber(ad,S2,S3);
447     break;
448     case 3: return -1; /* Packed */
449    
450     case 4:
451     fmovi_mr((uae_u32)temp_fp,val);
452     delay;
453     mov_l_rm(S2,(uae_u32)temp_fp);
454     writeword_clobber(ad,S2,S3);
455     break;
456     case 5:
457     fmov_mr((uae_u32)temp_fp,val);
458     delay;
459     mov_l_rm(S2,(uae_u32)temp_fp+4);
460     writelong_clobber(ad,S2,S3);
461     add_l_ri(ad,4);
462     mov_l_rm(S2,(uae_u32)temp_fp);
463     writelong_clobber(ad,S2,S3);
464     break;
465     case 6:
466     fmovi_mr((uae_u32)temp_fp,val);
467     delay;
468     mov_l_rm(S2,(uae_u32)temp_fp);
469     writebyte(ad,S2,S3);
470     break;
471     default:
472     return -1;
473     }
474     return 0;
475     }
476    
477     /* return -1 for failure, or register number for success */
478     STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
479     {
480     uae_u16 tmp;
481     uaecptr tmppc;
482     int mode;
483     int reg;
484     uae_s32 off;
485    
486     mode = (opcode >> 3) & 7;
487     reg = opcode & 7;
488     switch (mode) {
489     case 0:
490     case 1:
491     return -1;
492     case 2:
493     case 3:
494     case 4:
495     mov_l_rr(S1,8+reg);
496     return S1;
497     *ad = m68k_areg (regs, reg);
498     break;
499     case 5:
500     off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
501    
502     mov_l_rr(S1,8+reg);
503     add_l_ri(S1,off);
504     return S1;
505     case 6:
506     return -1;
507     break;
508     case 7:
509     switch (reg) {
510     case 0:
511     off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
512     mov_l_ri(S1,off);
513     return S1;
514     case 1:
515     off=comp_get_ilong((m68k_pc_offset+=4)-4);
516     mov_l_ri(S1,off);
517     return S1;
518     case 2:
519     return -1;
520     // *ad = m68k_getpc ();
521     // *ad += (uae_s32) (uae_s16) next_iword ();
522     off=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;
523     off+=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
524     mov_l_ri(S1,off);
525     return S1;
526     case 3:
527     return -1;
528     tmppc = m68k_getpc ();
529     tmp = next_iword ();
530     *ad = get_disp_ea_020 (tmppc, tmp);
531     break;
532     default:
533     return -1;
534     }
535     }
536     abort();
537     }
538    
539     void comp_fdbcc_opp (uae_u32 opcode, uae_u16 extra)
540     {
541     FAIL(1);
542     return;
543     }
544    
545     void comp_fscc_opp (uae_u32 opcode, uae_u16 extra)
546     {
547     uae_u32 ad;
548     int cc;
549     int reg;
550    
551     #if DEBUG_FPP
552     printf ("fscc_opp at %08lx\n", m68k_getpc ());
553     fflush (stdout);
554     #endif
555    
556    
557     if (extra&0x20) { /* only cc from 00 to 1f are defined */
558     FAIL(1);
559     return;
560     }
561     if ((opcode & 0x38) != 0) { /* We can only do to integer register */
562     FAIL(1);
563     return;
564     }
565    
566     fflags_into_flags(S2);
567     reg=(opcode&7);
568    
569     mov_l_ri(S1,255);
570     mov_l_ri(S4,0);
571     switch(extra&0x0f) { /* according to fpp.c, the 0x10 bit is ignored
572     */
573     case 0: break; /* set never */
574     case 1: mov_l_rr(S2,S4);
575     cmov_l_rr(S4,S1,4);
576     cmov_l_rr(S4,S2,10); break;
577     case 2: cmov_l_rr(S4,S1,7); break;
578     case 3: cmov_l_rr(S4,S1,3); break;
579     case 4: mov_l_rr(S2,S4);
580     cmov_l_rr(S4,S1,2);
581     cmov_l_rr(S4,S2,10); break;
582     case 5: mov_l_rr(S2,S4);
583     cmov_l_rr(S4,S1,6);
584     cmov_l_rr(S4,S2,10); break;
585     case 6: cmov_l_rr(S4,S1,5); break;
586     case 7: cmov_l_rr(S4,S1,11); break;
587     case 8: cmov_l_rr(S4,S1,10); break;
588     case 9: cmov_l_rr(S4,S1,4); break;
589     case 10: cmov_l_rr(S4,S1,10); cmov_l_rr(S4,S1,7); break;
590     case 11: cmov_l_rr(S4,S1,4); cmov_l_rr(S4,S1,3); break;
591     case 12: cmov_l_rr(S4,S1,2); break;
592     case 13: cmov_l_rr(S4,S1,6); break;
593     case 14: cmov_l_rr(S4,S1,5); cmov_l_rr(S4,S1,10); break;
594     case 15: mov_l_rr(S4,S1); break;
595     }
596    
597     if ((opcode & 0x38) == 0) {
598     mov_b_rr(reg,S4);
599     } else {
600     abort();
601     if (get_fp_ad (opcode, &ad) == 0) {
602     m68k_setpc (m68k_getpc () - 4);
603     fpuop_illg (opcode,extra);
604     } else
605     put_byte (ad, cc ? 0xff : 0x00);
606     }
607     }
608    
609     void comp_ftrapcc_opp (uae_u32 opcode, uaecptr oldpc)
610     {
611     int cc;
612    
613     FAIL(1);
614     return;
615     }
616    
617     extern unsigned long foink3, oink;
618    
619     void comp_fbcc_opp (uae_u32 opcode)
620     {
621     uae_u32 start_68k_offset=m68k_pc_offset;
622     uae_u32 off;
623     uae_u32 v1;
624     uae_u32 v2;
625     uae_u32 nh;
626     int cc;
627    
628     if (opcode&0x20) { /* only cc from 00 to 1f are defined */
629     FAIL(1);
630     return;
631     }
632     if ((opcode&0x40)==0) {
633     off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
634     }
635     else {
636     off=comp_get_ilong((m68k_pc_offset+=4)-4);
637     }
638     mov_l_ri(S1,(uae_u32)
639     (comp_pc_p+off-(m68k_pc_offset-start_68k_offset)));
640     mov_l_ri(PC_P,(uae_u32)comp_pc_p);
641    
642     /* Now they are both constant. Might as well fold in m68k_pc_offset */
643     add_l_ri(S1,m68k_pc_offset);
644     add_l_ri(PC_P,m68k_pc_offset);
645     m68k_pc_offset=0;
646    
647     /* according to fpp.c, the 0x10 bit is ignored
648     (it handles exception handling, which we don't
649     do, anyway ;-) */
650     cc=opcode&0x0f;
651     v1=get_const(PC_P);
652     v2=get_const(S1);
653     fflags_into_flags(S2);
654    
655     // mov_l_mi((uae_u32)&foink3,cc);
656     switch(cc) {
657     case 0: break; /* jump never */
658     case 1:
659     mov_l_rr(S2,PC_P);
660     cmov_l_rr(PC_P,S1,4);
661     cmov_l_rr(PC_P,S2,10); break;
662     case 2: register_branch(v1,v2,7); break;
663     case 3: register_branch(v1,v2,3); break;
664     case 4:
665     mov_l_rr(S2,PC_P);
666     cmov_l_rr(PC_P,S1,2);
667     cmov_l_rr(PC_P,S2,10); break;
668     case 5:
669     mov_l_rr(S2,PC_P);
670     cmov_l_rr(PC_P,S1,6);
671     cmov_l_rr(PC_P,S2,10); break;
672     case 6: register_branch(v1,v2,5); break;
673     case 7: register_branch(v1,v2,11); break;
674     case 8: register_branch(v1,v2,10); break;
675     case 9: register_branch(v1,v2,4); break;
676     case 10:
677     cmov_l_rr(PC_P,S1,10);
678     cmov_l_rr(PC_P,S1,7); break;
679     case 11:
680     cmov_l_rr(PC_P,S1,4);
681     cmov_l_rr(PC_P,S1,3); break;
682     case 12: register_branch(v1,v2,2); break;
683     case 13: register_branch(v1,v2,6); break;
684     case 14:
685     cmov_l_rr(PC_P,S1,5);
686     cmov_l_rr(PC_P,S1,10); break;
687     case 15: mov_l_rr(PC_P,S1); break;
688     }
689     }
690    
691     /* Floating point conditions
692     The "NotANumber" part could be problematic; Howver, when NaN is
693     encountered, the ftst instruction sets bot N and Z to 1 on the x87,
694     so quite often things just fall into place. This is probably not
695     accurate wrt the 68k FPU, but it is *as* accurate as this was before.
696     However, some more thought should go into fixing this stuff up so
697     it accurately emulates the 68k FPU.
698     >=<U
699     0000 0x00: 0 --- Never jump
700     0101 0x01: Z --- jump if zero (x86: 4)
701     1000 0x02: !(NotANumber || Z || N) --- Neither Z nor N set (x86: 7)
702     1101 0x03: Z || !(NotANumber || N); --- Z or !N (x86: 4 and 3)
703     0010 0x04: N && !(NotANumber || Z); --- N and !Z (x86: hard!)
704     0111 0x05: Z || (N && !NotANumber); --- Z or N (x86: 6)
705     1010 0x06: !(NotANumber || Z); --- not Z (x86: 5)
706     1110 0x07: !NotANumber; --- not NaN (x86: 11, not parity)
707     0001 0x08: NotANumber; --- NaN (x86: 10)
708     0101 0x09: NotANumber || Z; --- Z (x86: 4)
709     1001 0x0a: NotANumber || !(N || Z); --- NaN or neither N nor Z (x86: 10 and 7)
710     1101 0x0b: NotANumber || Z || !N; --- Z or !N (x86: 4 and 3)
711     0011 0x0c: NotANumber || (N && !Z); --- N (x86: 2)
712     0111 0x0d: NotANumber || Z || N; --- Z or N (x86: 6)
713     1010 0x0e: !Z; --- not Z (x86: 5)
714     1111 0x0f: 1; --- always
715    
716     This is not how the 68k handles things, though --- it sets Z to 0 and N
717     to the NaN's sign.... ('o' and 'i' denote differences from the above
718     table)
719    
720     >=<U
721     0000 0x00: 0 --- Never jump
722     010o 0x01: Z --- jump if zero (x86: 4, not 10)
723     1000 0x02: !(NotANumber || Z || N) --- Neither Z nor N set (x86: 7)
724     110o 0x03: Z || !(NotANumber || N); --- Z or !N (x86: 3)
725     0010 0x04: N && !(NotANumber || Z); --- N and !Z (x86: 2, not 10)
726     011o 0x05: Z || (N && !NotANumber); --- Z or N (x86: 6, not 10)
727     1010 0x06: !(NotANumber || Z); --- not Z (x86: 5)
728     1110 0x07: !NotANumber; --- not NaN (x86: 11, not parity)
729     0001 0x08: NotANumber; --- NaN (x86: 10)
730     0101 0x09: NotANumber || Z; --- Z (x86: 4)
731     1001 0x0a: NotANumber || !(N || Z); --- NaN or neither N nor Z (x86: 10 and 7)
732     1101 0x0b: NotANumber || Z || !N; --- Z or !N (x86: 4 and 3)
733     0011 0x0c: NotANumber || (N && !Z); --- N (x86: 2)
734     0111 0x0d: NotANumber || Z || N; --- Z or N (x86: 6)
735     101i 0x0e: !Z; --- not Z (x86: 5 and 10)
736     1111 0x0f: 1; --- always
737    
738     Of course, this *still* doesn't mean that the x86 and 68k conditions are
739     equivalent --- the handling of infinities is different, for one thing.
740     On the 68k, +infinity minus +infinity is NotANumber (as it should be). On
741     the x86, it is +infinity, and some exception is raised (which I suspect
742     is promptly ignored) STUPID!
743     The more I learn about their CPUs, the more I detest Intel....
744    
745     You can see this in action if you have "Benoit" (see Aminet) and
746     set the exponent to 16. Wait for a long time, and marvel at the extra black
747     areas outside the center one. That's where Benoit expects NaN, and the x86
748     gives +infinity. [Ooops --- that must have been some kind of bug in my code.
749     it no longer happens, and the resulting graphic looks much better, too]
750    
751     x86 conditions
752     0011 : 2
753     1100 : 3
754     0101 : 4
755     1010 : 5
756     0111 : 6
757     1000 : 7
758     0001 : 10
759     1110 : 11
760     */
761     void comp_fsave_opp (uae_u32 opcode)
762     {
763     uae_u32 ad;
764     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
765     int i;
766    
767     FAIL(1);
768     return;
769    
770     #if DEBUG_FPP
771     printf ("fsave_opp at %08lx\n", m68k_getpc ());
772     fflush (stdout);
773     #endif
774     if (get_fp_ad (opcode, &ad) == 0) {
775     m68k_setpc (m68k_getpc () - 2);
776     fpuop_illg (opcode,UNKNOWN_EXTRA);
777     return;
778     }
779    
780     if (CPUType == 4) {
781     /* 4 byte 68040 IDLE frame. */
782     if (incr < 0) {
783     ad -= 4;
784     put_long (ad, 0x41000000);
785     } else {
786     put_long (ad, 0x41000000);
787     ad += 4;
788     }
789     } else {
790     if (incr < 0) {
791     ad -= 4;
792     put_long (ad, 0x70000000);
793     for (i = 0; i < 5; i++) {
794     ad -= 4;
795     put_long (ad, 0x00000000);
796     }
797     ad -= 4;
798     put_long (ad, 0x1f180000);
799     } else {
800     put_long (ad, 0x1f180000);
801     ad += 4;
802     for (i = 0; i < 5; i++) {
803     put_long (ad, 0x00000000);
804     ad += 4;
805     }
806     put_long (ad, 0x70000000);
807     ad += 4;
808     }
809     }
810     if ((opcode & 0x38) == 0x18)
811     m68k_areg (regs, opcode & 7) = ad;
812     if ((opcode & 0x38) == 0x20)
813     m68k_areg (regs, opcode & 7) = ad;
814     }
815    
816     void comp_frestore_opp (uae_u32 opcode)
817     {
818     uae_u32 ad;
819     uae_u32 d;
820     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
821    
822     FAIL(1);
823     return;
824    
825     #if DEBUG_FPP
826     printf ("frestore_opp at %08lx\n", m68k_getpc ());
827     fflush (stdout);
828     #endif
829     if (get_fp_ad (opcode, &ad) == 0) {
830     m68k_setpc (m68k_getpc () - 2);
831     fpuop_illg (opcode,UNKNOWN_EXTRA);
832     return;
833     }
834     if (CPUType == 4) {
835     /* 68040 */
836     if (incr < 0) {
837     /* @@@ This may be wrong. */
838     ad -= 4;
839     d = get_long (ad);
840     if ((d & 0xff000000) != 0) { /* Not a NULL frame? */
841     if ((d & 0x00ff0000) == 0) { /* IDLE */
842     } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */
843     ad -= 44;
844     } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */
845     ad -= 92;
846     }
847     }
848     } else {
849     d = get_long (ad);
850     ad += 4;
851     if ((d & 0xff000000) != 0) { /* Not a NULL frame? */
852     if ((d & 0x00ff0000) == 0) { /* IDLE */
853     } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */
854     ad += 44;
855     } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */
856     ad += 92;
857     }
858     }
859     }
860     } else {
861     if (incr < 0) {
862     ad -= 4;
863     d = get_long (ad);
864     if ((d & 0xff000000) != 0) {
865     if ((d & 0x00ff0000) == 0x00180000)
866     ad -= 6 * 4;
867     else if ((d & 0x00ff0000) == 0x00380000)
868     ad -= 14 * 4;
869     else if ((d & 0x00ff0000) == 0x00b40000)
870     ad -= 45 * 4;
871     }
872     } else {
873     d = get_long (ad);
874     ad += 4;
875     if ((d & 0xff000000) != 0) {
876     if ((d & 0x00ff0000) == 0x00180000)
877     ad += 6 * 4;
878     else if ((d & 0x00ff0000) == 0x00380000)
879     ad += 14 * 4;
880     else if ((d & 0x00ff0000) == 0x00b40000)
881     ad += 45 * 4;
882     }
883     }
884     }
885     if ((opcode & 0x38) == 0x18)
886     m68k_areg (regs, opcode & 7) = ad;
887     if ((opcode & 0x38) == 0x20)
888     m68k_areg (regs, opcode & 7) = ad;
889     }
890    
891     #if USE_LONG_DOUBLE
892     static const fpu_register const_e = 2.7182818284590452353602874713526625L;
893     static const fpu_register const_log10_e = 0.4342944819032518276511289189166051L;
894     static const fpu_register const_loge_10 = 2.3025850929940456840179914546843642L;
895     #else
896     static const fpu_register const_e = 2.7182818284590452354;
897     static const fpu_register const_log10_e = 0.43429448190325182765;
898     static const fpu_register const_loge_10 = 2.30258509299404568402;
899     #endif
900    
901     static const fpu_register power10[] = {
902     1e0, 1e1, 1e2, 1e4, 1e8, 1e16, 1e32, 1e64, 1e128, 1e256
903     #if USE_LONG_DOUBLE
904     , 1e512, 1e1024, 1e2048, 1e4096
905     #endif
906     };
907    
908     /* 128 words, indexed through the low byte of the 68k fpu control word */
909     static uae_u16 x86_fpucw[]={
910     0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, /* p0r0 */
911     0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, /* p0r1 */
912     0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, /* p0r2 */
913     0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, /* p0r3 */
914    
915     0x107f, 0x107f, 0x107f, 0x107f, 0x107f, 0x107f, 0x107f, 0x107f, /* p1r0 */
916     0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, /* p1r1 */
917     0x147f, 0x147f, 0x147f, 0x147f, 0x147f, 0x147f, 0x147f, 0x147f, /* p1r2 */
918     0x187f, 0x187f, 0x187f, 0x187f, 0x187f, 0x187f, 0x187f, 0x187f, /* p1r3 */
919    
920     0x127f, 0x127f, 0x127f, 0x127f, 0x127f, 0x127f, 0x127f, 0x127f, /* p2r0 */
921     0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, /* p2r1 */
922     0x167f, 0x167f, 0x167f, 0x167f, 0x167f, 0x167f, 0x167f, 0x167f, /* p2r2 */
923     0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, /* p2r3 */
924    
925     0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, /* p3r0 */
926     0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, /* p3r1 */
927     0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, /* p3r2 */
928     0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f /* p3r3 */
929     };
930    
931     void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
932     {
933     int reg;
934     int src;
935    
936     switch ((extra >> 13) & 0x7) {
937     case 3: /* 2nd most common */
938     if (put_fp_value ((extra >> 7)&7 , opcode, extra) < 0) {
939     FAIL(1);
940     return;
941    
942     }
943     return;
944     case 6:
945     case 7:
946     {
947     uae_u32 ad, list = 0;
948     int incr = 0;
949     if (extra & 0x2000) {
950     uae_u32 ad;
951    
952     /* FMOVEM FPP->memory */
953     switch ((extra >> 11) & 3) { /* Get out early if failure */
954     case 0:
955     case 2:
956     break;
957     case 1:
958     case 3:
959     default:
960     FAIL(1); return;
961     }
962     ad=get_fp_ad (opcode, &ad);
963     if (ad<0) {
964     m68k_setpc (m68k_getpc () - 4);
965     fpuop_illg (opcode,extra);
966     return;
967     }
968     switch ((extra >> 11) & 3) {
969     case 0: /* static pred */
970     list = extra & 0xff;
971     incr = -1;
972     break;
973     case 2: /* static postinc */
974     list = extra & 0xff;
975     incr = 1;
976     break;
977     case 1: /* dynamic pred */
978     case 3: /* dynamic postinc */
979     abort();
980     }
981     if (incr < 0) { /* Predecrement */
982     for (reg = 7; reg >= 0; reg--) {
983     if (list & 0x80) {
984     fmov_ext_mr((uae_u32)temp_fp,reg);
985     delay;
986     sub_l_ri(ad,4);
987     mov_l_rm(S2,(uae_u32)temp_fp);
988     writelong_clobber(ad,S2,S3);
989     sub_l_ri(ad,4);
990     mov_l_rm(S2,(uae_u32)temp_fp+4);
991     writelong_clobber(ad,S2,S3);
992     sub_l_ri(ad,4);
993     mov_w_rm(S2,(uae_u32)temp_fp+8);
994     writeword_clobber(ad,S2,S3);
995     }
996     list <<= 1;
997     }
998     }
999     else { /* Postincrement */
1000     for (reg = 0; reg < 8; reg++) {
1001     if (list & 0x80) {
1002     fmov_ext_mr((uae_u32)temp_fp,reg);
1003     delay;
1004     mov_w_rm(S2,(uae_u32)temp_fp+8);
1005     writeword_clobber(ad,S2,S3);
1006     add_l_ri(ad,4);
1007     mov_l_rm(S2,(uae_u32)temp_fp+4);
1008     writelong_clobber(ad,S2,S3);
1009     add_l_ri(ad,4);
1010     mov_l_rm(S2,(uae_u32)temp_fp);
1011     writelong_clobber(ad,S2,S3);
1012     add_l_ri(ad,4);
1013     }
1014     list <<= 1;
1015     }
1016     }
1017     if ((opcode & 0x38) == 0x18)
1018     mov_l_rr((opcode & 7)+8,ad);
1019     if ((opcode & 0x38) == 0x20)
1020     mov_l_rr((opcode & 7)+8,ad);
1021     } else {
1022     /* FMOVEM memory->FPP */
1023    
1024     uae_u32 ad;
1025     switch ((extra >> 11) & 3) { /* Get out early if failure */
1026     case 0:
1027     case 2:
1028     break;
1029     case 1:
1030     case 3:
1031     default:
1032     FAIL(1); return;
1033     }
1034     ad=get_fp_ad (opcode, &ad);
1035     if (ad<0) {
1036     m68k_setpc (m68k_getpc () - 4);
1037     write_log("no ad\n");
1038     fpuop_illg (opcode,extra);
1039     return;
1040     }
1041     switch ((extra >> 11) & 3) {
1042     case 0: /* static pred */
1043     list = extra & 0xff;
1044     incr = -1;
1045     break;
1046     case 2: /* static postinc */
1047     list = extra & 0xff;
1048     incr = 1;
1049     break;
1050     case 1: /* dynamic pred */
1051     case 3: /* dynamic postinc */
1052     abort();
1053     }
1054    
1055     if (incr < 0) {
1056     // not reached
1057     for (reg = 7; reg >= 0; reg--) {
1058     uae_u32 wrd1, wrd2, wrd3;
1059     if (list & 0x80) {
1060     sub_l_ri(ad,4);
1061     readlong(ad,S2,S3);
1062     mov_l_mr((uae_u32)(temp_fp),S2);
1063     sub_l_ri(ad,4);
1064     readlong(ad,S2,S3);
1065     mov_l_mr((uae_u32)(temp_fp)+4,S2);
1066     sub_l_ri(ad,4);
1067     readword(ad,S2,S3);
1068     mov_w_mr(((uae_u32)temp_fp)+8,S2);
1069     delay2;
1070     fmov_ext_rm(reg,(uae_u32)(temp_fp));
1071     }
1072     list <<= 1;
1073     }
1074     }
1075     else {
1076     for (reg = 0; reg < 8; reg++) {
1077     uae_u32 wrd1, wrd2, wrd3;
1078     if (list & 0x80) {
1079     readword(ad,S2,S3);
1080     mov_w_mr(((uae_u32)temp_fp)+8,S2);
1081     add_l_ri(ad,4);
1082     readlong(ad,S2,S3);
1083     mov_l_mr((uae_u32)(temp_fp)+4,S2);
1084     add_l_ri(ad,4);
1085     readlong(ad,S2,S3);
1086     mov_l_mr((uae_u32)(temp_fp),S2);
1087     add_l_ri(ad,4);
1088     delay2;
1089     fmov_ext_rm(reg,(uae_u32)(temp_fp));
1090     }
1091     list <<= 1;
1092     }
1093     }
1094     if ((opcode & 0x38) == 0x18)
1095     mov_l_rr((opcode & 7)+8,ad);
1096     if ((opcode & 0x38) == 0x20)
1097     mov_l_rr((opcode & 7)+8,ad);
1098     }
1099     }
1100     return;
1101    
1102     case 4:
1103     case 5: /* rare */
1104     if ((opcode & 0x30) == 0) {
1105     if (extra & 0x2000) {
1106     if (extra & 0x1000) {
1107     #if HANDLE_FPCR
1108     mov_l_rm(opcode & 15, (uae_u32)&fpu.fpcr.rounding_mode);
1109     or_l_rm(opcode & 15, (uae_u32)&fpu.fpcr.rounding_precision);
1110     #else
1111     FAIL(1);
1112     return;
1113     #endif
1114     }
1115     if (extra & 0x0800) {
1116     FAIL(1);
1117     return;
1118     }
1119     if (extra & 0x0400) {
1120     mov_l_rm(opcode & 15,(uae_u32)&fpu.instruction_address);
1121     return;
1122     }
1123     } else {
1124     // gb-- moved here so that we may FAIL() without generating any code
1125     if (extra & 0x0800) {
1126     // set_fpsr(m68k_dreg (regs, opcode & 15));
1127     FAIL(1);
1128     return;
1129     }
1130     if (extra & 0x1000) {
1131     #if HANDLE_FPCR
1132     #if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
1133     FAIL(1);
1134     return;
1135     #endif
1136     mov_l_rr(S1,opcode & 15);
1137     mov_l_rr(S2,opcode & 15);
1138     and_l_ri(S1,FPCR_ROUNDING_PRECISION);
1139     and_l_ri(S2,FPCR_ROUNDING_MODE);
1140     mov_l_mr((uae_u32)&fpu.fpcr.rounding_precision,S1);
1141     mov_l_mr((uae_u32)&fpu.fpcr.rounding_mode,S2);
1142     #else
1143     FAIL(1);
1144     return;
1145     #endif
1146     // return; gb-- FMOVEM could also operate on fpiar
1147     }
1148     if (extra & 0x0400) {
1149     mov_l_mr((uae_u32)&fpu.instruction_address,opcode & 15);
1150     // return; gb-- we have to process all FMOVEM bits before returning
1151     }
1152     return;
1153     }
1154     } else if ((opcode & 0x3f) == 0x3c) {
1155     if ((extra & 0x2000) == 0) {
1156     // gb-- moved here so that we may FAIL() without generating any code
1157     if (extra & 0x0800) {
1158     FAIL(1);
1159     return;
1160     }
1161     if (extra & 0x1000) {
1162     uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4);
1163     #if HANDLE_FPCR
1164     #if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
1165     FAIL(1);
1166     return;
1167     #endif
1168     // mov_l_mi((uae_u32)&regs.fpcr,val);
1169     mov_l_ri(S1,val);
1170     mov_l_ri(S2,val);
1171     and_l_ri(S1,FPCR_ROUNDING_PRECISION);
1172     and_l_ri(S2,FPCR_ROUNDING_MODE);
1173     mov_l_mr((uae_u32)&fpu.fpcr.rounding_precision,S1);
1174     mov_l_mr((uae_u32)&fpu.fpcr.rounding_mode,S2);
1175     #else
1176     FAIL(1);
1177     return;
1178     #endif
1179     // return; gb-- FMOVEM could also operate on fpiar
1180     }
1181     if (extra & 0x0400) {
1182     uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4);
1183     mov_l_mi((uae_u32)&fpu.instruction_address,val);
1184     // return; gb-- we have to process all FMOVEM bits before returning
1185     }
1186     return;
1187     }
1188     FAIL(1);
1189     return;
1190     } else if (extra & 0x2000) {
1191     FAIL(1);
1192     return;
1193     } else {
1194     FAIL(1);
1195     return;
1196     }
1197     FAIL(1);
1198     return;
1199    
1200     case 0:
1201     case 2: /* Extremely common */
1202     reg = (extra >> 7) & 7;
1203     if ((extra & 0xfc00) == 0x5c00) {
1204     switch (extra & 0x7f) {
1205     case 0x00:
1206     fmov_pi(reg);
1207     break;
1208     case 0x0b:
1209     fmov_log10_2(reg);
1210     break;
1211     case 0x0c:
1212     #if USE_LONG_DOUBLE
1213     fmov_ext_rm(reg,(uae_u32)&const_e);
1214     #else
1215     fmov_rm(reg,(uae_u32)&const_e);
1216     #endif
1217     break;
1218     case 0x0d:
1219     fmov_log2_e(reg);
1220     break;
1221     case 0x0e:
1222     #if USE_LONG_DOUBLE
1223     fmov_ext_rm(reg,(uae_u32)&const_log10_e);
1224     #else
1225     fmov_rm(reg,(uae_u32)&const_log10_e);
1226     #endif
1227     break;
1228     case 0x0f:
1229     fmov_0(reg);
1230     break;
1231     case 0x30:
1232     fmov_loge_2(reg);
1233     break;
1234     case 0x31:
1235     #if USE_LONG_DOUBLE
1236     fmov_ext_rm(reg,(uae_u32)&const_loge_10);
1237     #else
1238     fmov_rm(reg,(uae_u32)&const_loge_10);
1239     #endif
1240     break;
1241     case 0x32:
1242     fmov_1(reg);
1243     break;
1244     case 0x33:
1245     case 0x34:
1246     case 0x35:
1247     case 0x36:
1248     case 0x37:
1249     case 0x38:
1250     case 0x39:
1251     case 0x3a:
1252     case 0x3b:
1253     #if USE_LONG_DOUBLE
1254     case 0x3c:
1255     case 0x3d:
1256     case 0x3e:
1257     case 0x3f:
1258     fmov_ext_rm(reg,(uae_u32)(power10+(extra & 0x7f)-0x32));
1259     #else
1260     fmov_rm(reg,(uae_u32)(power10+(extra & 0x7f)-0x32));
1261     #endif
1262     break;
1263     default:
1264     /* This is not valid, so we fail */
1265     FAIL(1);
1266     return;
1267     }
1268     return;
1269     }
1270    
1271     switch (extra & 0x7f) {
1272     case 0x00: /* FMOVE */
1273     case 0x40: /* Explicit rounding. This is just a quick fix. Same
1274     * for all other cases that have three choices */
1275     case 0x44:
1276     dont_care_fflags();
1277     src=get_fp_value (opcode, extra);
1278     if (src < 0) {
1279     FAIL(1); /* Illegal instruction */
1280     return;
1281     }
1282     fmov_rr(reg,src);
1283     MAKE_FPSR (src);
1284     break;
1285     case 0x01: /* FINT */
1286     FAIL(1);
1287     return;
1288     dont_care_fflags();
1289     case 0x02: /* FSINH */
1290     FAIL(1);
1291     return;
1292     dont_care_fflags();
1293     break;
1294     case 0x03: /* FINTRZ */
1295     #if USE_X86_FPUCW
1296     /* If we have control over the CW, we can do this */
1297     dont_care_fflags();
1298     src=get_fp_value (opcode, extra);
1299     if (src < 0) {
1300     FAIL(1); /* Illegal instruction */
1301     return;
1302     }
1303     mov_l_ri(S1,16); /* Switch to "round to zero" mode */
1304     fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
1305    
1306     frndint_rr(reg,src);
1307    
1308     /* restore control word */
1309     mov_l_rm(S1,(uae_u32)&regs.fpcr);
1310     and_l_ri(S1,0x000000f0);
1311     fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
1312    
1313     MAKE_FPSR (reg);
1314     break;
1315     #endif
1316     FAIL(1);
1317     return;
1318     break;
1319     case 0x04: /* FSQRT */
1320     case 0x41:
1321     case 0x45:
1322     dont_care_fflags();
1323     src=get_fp_value (opcode, extra);
1324     if (src < 0) {
1325     FAIL(1); /* Illegal instruction */
1326     return;
1327     }
1328     fsqrt_rr(reg,src);
1329     MAKE_FPSR (reg);
1330     break;
1331     case 0x06: /* FLOGNP1 */
1332     FAIL(1);
1333     return;
1334     dont_care_fflags();
1335     break;
1336     case 0x08: /* FETOXM1 */
1337     FAIL(1);
1338     return;
1339     dont_care_fflags();
1340     break;
1341     case 0x09: /* FTANH */
1342     FAIL(1);
1343     return;
1344     dont_care_fflags();
1345     break;
1346     case 0x0a: /* FATAN */
1347     FAIL(1);
1348     return;
1349     dont_care_fflags();
1350     break;
1351     case 0x0c: /* FASIN */
1352     FAIL(1);
1353     return;
1354     dont_care_fflags();
1355     break;
1356     case 0x0d: /* FATANH */
1357     FAIL(1);
1358     return;
1359     dont_care_fflags();
1360     break;
1361     case 0x0e: /* FSIN */
1362     dont_care_fflags();
1363     src=get_fp_value (opcode, extra);
1364     if (src < 0) {
1365     FAIL(1); /* Illegal instruction */
1366     return;
1367     }
1368     fsin_rr(reg,src);
1369     MAKE_FPSR (reg);
1370     break;
1371     case 0x0f: /* FTAN */
1372     FAIL(1);
1373     return;
1374     dont_care_fflags();
1375     break;
1376     case 0x10: /* FETOX */
1377     dont_care_fflags();
1378     src=get_fp_value (opcode, extra);
1379     if (src < 0) {
1380     FAIL(1); /* Illegal instruction */
1381     return;
1382     }
1383     fetox_rr(reg,src);
1384     MAKE_FPSR (reg);
1385     break;
1386     case 0x11: /* FTWOTOX */
1387     dont_care_fflags();
1388     src=get_fp_value (opcode, extra);
1389     if (src < 0) {
1390     FAIL(1); /* Illegal instruction */
1391     return;
1392     }
1393     ftwotox_rr(reg,src);
1394     MAKE_FPSR (reg);
1395     break;
1396     case 0x12: /* FTENTOX */
1397     FAIL(1);
1398     return;
1399     dont_care_fflags();
1400     break;
1401     case 0x14: /* FLOGN */
1402     FAIL(1);
1403     return;
1404     dont_care_fflags();
1405     break;
1406     case 0x15: /* FLOG10 */
1407     FAIL(1);
1408     return;
1409     dont_care_fflags();
1410     break;
1411     case 0x16: /* FLOG2 */
1412     dont_care_fflags();
1413     src=get_fp_value (opcode, extra);
1414     if (src < 0) {
1415     FAIL(1); /* Illegal instruction */
1416     return;
1417     }
1418     flog2_rr(reg,src);
1419     MAKE_FPSR (reg);
1420     break;
1421     case 0x18: /* FABS */
1422     case 0x58:
1423     case 0x5c:
1424     dont_care_fflags();
1425     src=get_fp_value (opcode, extra);
1426     if (src < 0) {
1427     FAIL(1); /* Illegal instruction */
1428     return;
1429     }
1430     fabs_rr(reg,src);
1431     MAKE_FPSR (reg);
1432     break;
1433     case 0x19: /* FCOSH */
1434     FAIL(1);
1435     return;
1436     dont_care_fflags();
1437     break;
1438     case 0x1a: /* FNEG */
1439     case 0x5a:
1440     case 0x5e:
1441     dont_care_fflags();
1442     src=get_fp_value (opcode, extra);
1443     if (src < 0) {
1444     FAIL(1); /* Illegal instruction */
1445     return;
1446     }
1447     fneg_rr(reg,src);
1448     MAKE_FPSR (reg);
1449     break;
1450     case 0x1c: /* FACOS */
1451     FAIL(1);
1452     return;
1453     dont_care_fflags();
1454     break;
1455     case 0x1d: /* FCOS */
1456     dont_care_fflags();
1457     src=get_fp_value (opcode, extra);
1458     if (src < 0) {
1459     FAIL(1); /* Illegal instruction */
1460     return;
1461     }
1462     fcos_rr(reg,src);
1463     MAKE_FPSR (reg);
1464     break;
1465     case 0x1e: /* FGETEXP */
1466     FAIL(1);
1467     return;
1468     dont_care_fflags();
1469     break;
1470     case 0x1f: /* FGETMAN */
1471     FAIL(1);
1472     return;
1473     dont_care_fflags();
1474     break;
1475     case 0x20: /* FDIV */
1476     case 0x60:
1477     case 0x64:
1478     dont_care_fflags();
1479     src=get_fp_value (opcode, extra);
1480     if (src < 0) {
1481     FAIL(1); /* Illegal instruction */
1482     return;
1483     }
1484     fdiv_rr(reg,src);
1485     MAKE_FPSR (reg);
1486     break;
1487     case 0x21: /* FMOD */
1488     dont_care_fflags();
1489     src=get_fp_value (opcode, extra);
1490     if (src < 0) {
1491     FAIL(1); /* Illegal instruction */
1492     return;
1493     }
1494     frem_rr(reg,src);
1495     MAKE_FPSR (reg);
1496     break;
1497     case 0x22: /* FADD */
1498     case 0x62:
1499     case 0x66:
1500     dont_care_fflags();
1501     src=get_fp_value (opcode, extra);
1502     if (src < 0) {
1503     FAIL(1); /* Illegal instruction */
1504     return;
1505     }
1506     fadd_rr(reg,src);
1507     MAKE_FPSR (reg);
1508     break;
1509     case 0x23: /* FMUL */
1510     case 0x63:
1511     case 0x67:
1512     dont_care_fflags();
1513     src=get_fp_value (opcode, extra);
1514     if (src < 0) {
1515     FAIL(1); /* Illegal instruction */
1516     return;
1517     }
1518     fmul_rr(reg,src);
1519     MAKE_FPSR (reg);
1520     break;
1521     case 0x24: /* FSGLDIV */
1522     dont_care_fflags();
1523     src=get_fp_value (opcode, extra);
1524     if (src < 0) {
1525     FAIL(1); /* Illegal instruction */
1526     return;
1527     }
1528     fdiv_rr(reg,src);
1529     MAKE_FPSR (reg);
1530     break;
1531     case 0x25: /* FREM */
1532     // gb-- disabled because the quotient byte must be computed
1533     // otherwise, free rotation in ClarisWorks doesn't work.
1534     FAIL(1);
1535     return;
1536     dont_care_fflags();
1537     src=get_fp_value (opcode, extra);
1538     if (src < 0) {
1539     FAIL(1); /* Illegal instruction */
1540     return;
1541     }
1542     frem1_rr(reg,src);
1543     MAKE_FPSR (reg);
1544     break;
1545     case 0x26: /* FSCALE */
1546     dont_care_fflags();
1547     FAIL(1);
1548     return;
1549     break;
1550     case 0x27: /* FSGLMUL */
1551     dont_care_fflags();
1552     src=get_fp_value (opcode, extra);
1553     if (src < 0) {
1554     FAIL(1); /* Illegal instruction */
1555     return;
1556     }
1557     fmul_rr(reg,src);
1558     MAKE_FPSR (reg);
1559     break;
1560     case 0x28: /* FSUB */
1561     case 0x68:
1562     case 0x6c:
1563     dont_care_fflags();
1564     src=get_fp_value (opcode, extra);
1565     if (src < 0) {
1566     FAIL(1); /* Illegal instruction */
1567     return;
1568     }
1569     fsub_rr(reg,src);
1570     MAKE_FPSR (reg);
1571     break;
1572     case 0x30: /* FSINCOS */
1573     case 0x31:
1574     case 0x32:
1575     case 0x33:
1576     case 0x34:
1577     case 0x35:
1578     case 0x36:
1579     case 0x37:
1580     FAIL(1);
1581     return;
1582     dont_care_fflags();
1583     break;
1584     case 0x38: /* FCMP */
1585     src=get_fp_value (opcode, extra);
1586     if (src < 0) {
1587     FAIL(1); /* Illegal instruction */
1588     return;
1589     }
1590     fmov_rr(FP_RESULT,reg);
1591     fsub_rr(FP_RESULT,src); /* Right way? */
1592     break;
1593     case 0x3a: /* FTST */
1594     src=get_fp_value (opcode, extra);
1595     if (src < 0) {
1596     FAIL(1); /* Illegal instruction */
1597     return;
1598     }
1599     fmov_rr(FP_RESULT,src);
1600     break;
1601     default:
1602     FAIL(1);
1603     return;
1604     break;
1605     }
1606     return;
1607     }
1608     m68k_setpc (m68k_getpc () - 4);
1609     fpuop_illg (opcode,extra);
1610     }