ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp
Revision: 1.4
Committed: 2003-03-21T19:12:44Z (21 years, 8 months ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-12, nigel-build-13
Changes since 1.3: +0 -3 lines
Log Message:
Remove some dead code. Start implementation of optimized calls to interpretive
fallbacks for untranslatable instruction handlers. Disabled for now since
call_m_01() is not correctly imeplemented yet.

File Contents

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