ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp
Revision: 1.3
Committed: 2002-10-03T16:13:46Z (21 years, 11 months ago) by gbeauche
Branch: MAIN
Changes since 1.2: +25 -0 lines
Log Message:
JIT add copyright notices just to notify people that's real derivative
work from GPL code (UAE-JIT). Additions and improvements are from B2
developers.

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     extern unsigned long foink3, oink;
643    
644     void comp_fbcc_opp (uae_u32 opcode)
645     {
646     uae_u32 start_68k_offset=m68k_pc_offset;
647     uae_u32 off;
648     uae_u32 v1;
649     uae_u32 v2;
650     uae_u32 nh;
651     int cc;
652    
653     if (opcode&0x20) { /* only cc from 00 to 1f are defined */
654     FAIL(1);
655     return;
656     }
657     if ((opcode&0x40)==0) {
658     off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2);
659     }
660     else {
661     off=comp_get_ilong((m68k_pc_offset+=4)-4);
662     }
663     mov_l_ri(S1,(uae_u32)
664     (comp_pc_p+off-(m68k_pc_offset-start_68k_offset)));
665     mov_l_ri(PC_P,(uae_u32)comp_pc_p);
666    
667     /* Now they are both constant. Might as well fold in m68k_pc_offset */
668     add_l_ri(S1,m68k_pc_offset);
669     add_l_ri(PC_P,m68k_pc_offset);
670     m68k_pc_offset=0;
671    
672     /* according to fpp.c, the 0x10 bit is ignored
673     (it handles exception handling, which we don't
674     do, anyway ;-) */
675     cc=opcode&0x0f;
676     v1=get_const(PC_P);
677     v2=get_const(S1);
678     fflags_into_flags(S2);
679    
680     // mov_l_mi((uae_u32)&foink3,cc);
681     switch(cc) {
682     case 0: break; /* jump never */
683     case 1:
684     mov_l_rr(S2,PC_P);
685     cmov_l_rr(PC_P,S1,4);
686     cmov_l_rr(PC_P,S2,10); break;
687     case 2: register_branch(v1,v2,7); break;
688     case 3: register_branch(v1,v2,3); break;
689     case 4:
690     mov_l_rr(S2,PC_P);
691     cmov_l_rr(PC_P,S1,2);
692     cmov_l_rr(PC_P,S2,10); break;
693     case 5:
694     mov_l_rr(S2,PC_P);
695     cmov_l_rr(PC_P,S1,6);
696     cmov_l_rr(PC_P,S2,10); break;
697     case 6: register_branch(v1,v2,5); break;
698     case 7: register_branch(v1,v2,11); break;
699     case 8: register_branch(v1,v2,10); break;
700     case 9: register_branch(v1,v2,4); break;
701     case 10:
702     cmov_l_rr(PC_P,S1,10);
703     cmov_l_rr(PC_P,S1,7); break;
704     case 11:
705     cmov_l_rr(PC_P,S1,4);
706     cmov_l_rr(PC_P,S1,3); break;
707     case 12: register_branch(v1,v2,2); break;
708     case 13: register_branch(v1,v2,6); break;
709     case 14:
710     cmov_l_rr(PC_P,S1,5);
711     cmov_l_rr(PC_P,S1,10); break;
712     case 15: mov_l_rr(PC_P,S1); break;
713     }
714     }
715    
716     /* Floating point conditions
717     The "NotANumber" part could be problematic; Howver, when NaN is
718     encountered, the ftst instruction sets bot N and Z to 1 on the x87,
719     so quite often things just fall into place. This is probably not
720     accurate wrt the 68k FPU, but it is *as* accurate as this was before.
721     However, some more thought should go into fixing this stuff up so
722     it accurately emulates the 68k FPU.
723     >=<U
724     0000 0x00: 0 --- Never jump
725     0101 0x01: Z --- jump if zero (x86: 4)
726     1000 0x02: !(NotANumber || Z || N) --- Neither Z nor N set (x86: 7)
727     1101 0x03: Z || !(NotANumber || N); --- Z or !N (x86: 4 and 3)
728     0010 0x04: N && !(NotANumber || Z); --- N and !Z (x86: hard!)
729     0111 0x05: Z || (N && !NotANumber); --- Z or N (x86: 6)
730     1010 0x06: !(NotANumber || Z); --- not Z (x86: 5)
731     1110 0x07: !NotANumber; --- not NaN (x86: 11, not parity)
732     0001 0x08: NotANumber; --- NaN (x86: 10)
733     0101 0x09: NotANumber || Z; --- Z (x86: 4)
734     1001 0x0a: NotANumber || !(N || Z); --- NaN or neither N nor Z (x86: 10 and 7)
735     1101 0x0b: NotANumber || Z || !N; --- Z or !N (x86: 4 and 3)
736     0011 0x0c: NotANumber || (N && !Z); --- N (x86: 2)
737     0111 0x0d: NotANumber || Z || N; --- Z or N (x86: 6)
738     1010 0x0e: !Z; --- not Z (x86: 5)
739     1111 0x0f: 1; --- always
740    
741     This is not how the 68k handles things, though --- it sets Z to 0 and N
742     to the NaN's sign.... ('o' and 'i' denote differences from the above
743     table)
744    
745     >=<U
746     0000 0x00: 0 --- Never jump
747     010o 0x01: Z --- jump if zero (x86: 4, not 10)
748     1000 0x02: !(NotANumber || Z || N) --- Neither Z nor N set (x86: 7)
749     110o 0x03: Z || !(NotANumber || N); --- Z or !N (x86: 3)
750     0010 0x04: N && !(NotANumber || Z); --- N and !Z (x86: 2, not 10)
751     011o 0x05: Z || (N && !NotANumber); --- Z or N (x86: 6, not 10)
752     1010 0x06: !(NotANumber || Z); --- not Z (x86: 5)
753     1110 0x07: !NotANumber; --- not NaN (x86: 11, not parity)
754     0001 0x08: NotANumber; --- NaN (x86: 10)
755     0101 0x09: NotANumber || Z; --- Z (x86: 4)
756     1001 0x0a: NotANumber || !(N || Z); --- NaN or neither N nor Z (x86: 10 and 7)
757     1101 0x0b: NotANumber || Z || !N; --- Z or !N (x86: 4 and 3)
758     0011 0x0c: NotANumber || (N && !Z); --- N (x86: 2)
759     0111 0x0d: NotANumber || Z || N; --- Z or N (x86: 6)
760     101i 0x0e: !Z; --- not Z (x86: 5 and 10)
761     1111 0x0f: 1; --- always
762    
763     Of course, this *still* doesn't mean that the x86 and 68k conditions are
764     equivalent --- the handling of infinities is different, for one thing.
765     On the 68k, +infinity minus +infinity is NotANumber (as it should be). On
766     the x86, it is +infinity, and some exception is raised (which I suspect
767     is promptly ignored) STUPID!
768     The more I learn about their CPUs, the more I detest Intel....
769    
770     You can see this in action if you have "Benoit" (see Aminet) and
771     set the exponent to 16. Wait for a long time, and marvel at the extra black
772     areas outside the center one. That's where Benoit expects NaN, and the x86
773     gives +infinity. [Ooops --- that must have been some kind of bug in my code.
774     it no longer happens, and the resulting graphic looks much better, too]
775    
776     x86 conditions
777     0011 : 2
778     1100 : 3
779     0101 : 4
780     1010 : 5
781     0111 : 6
782     1000 : 7
783     0001 : 10
784     1110 : 11
785     */
786     void comp_fsave_opp (uae_u32 opcode)
787     {
788     uae_u32 ad;
789     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
790     int i;
791    
792     FAIL(1);
793     return;
794    
795     #if DEBUG_FPP
796     printf ("fsave_opp at %08lx\n", m68k_getpc ());
797     fflush (stdout);
798     #endif
799     if (get_fp_ad (opcode, &ad) == 0) {
800     m68k_setpc (m68k_getpc () - 2);
801     fpuop_illg (opcode,UNKNOWN_EXTRA);
802     return;
803     }
804    
805     if (CPUType == 4) {
806     /* 4 byte 68040 IDLE frame. */
807     if (incr < 0) {
808     ad -= 4;
809     put_long (ad, 0x41000000);
810     } else {
811     put_long (ad, 0x41000000);
812     ad += 4;
813     }
814     } else {
815     if (incr < 0) {
816     ad -= 4;
817     put_long (ad, 0x70000000);
818     for (i = 0; i < 5; i++) {
819     ad -= 4;
820     put_long (ad, 0x00000000);
821     }
822     ad -= 4;
823     put_long (ad, 0x1f180000);
824     } else {
825     put_long (ad, 0x1f180000);
826     ad += 4;
827     for (i = 0; i < 5; i++) {
828     put_long (ad, 0x00000000);
829     ad += 4;
830     }
831     put_long (ad, 0x70000000);
832     ad += 4;
833     }
834     }
835     if ((opcode & 0x38) == 0x18)
836     m68k_areg (regs, opcode & 7) = ad;
837     if ((opcode & 0x38) == 0x20)
838     m68k_areg (regs, opcode & 7) = ad;
839     }
840    
841     void comp_frestore_opp (uae_u32 opcode)
842     {
843     uae_u32 ad;
844     uae_u32 d;
845     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
846    
847     FAIL(1);
848     return;
849    
850     #if DEBUG_FPP
851     printf ("frestore_opp at %08lx\n", m68k_getpc ());
852     fflush (stdout);
853     #endif
854     if (get_fp_ad (opcode, &ad) == 0) {
855     m68k_setpc (m68k_getpc () - 2);
856     fpuop_illg (opcode,UNKNOWN_EXTRA);
857     return;
858     }
859     if (CPUType == 4) {
860     /* 68040 */
861     if (incr < 0) {
862     /* @@@ This may be wrong. */
863     ad -= 4;
864     d = get_long (ad);
865     if ((d & 0xff000000) != 0) { /* Not a NULL frame? */
866     if ((d & 0x00ff0000) == 0) { /* IDLE */
867     } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */
868     ad -= 44;
869     } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */
870     ad -= 92;
871     }
872     }
873     } else {
874     d = get_long (ad);
875     ad += 4;
876     if ((d & 0xff000000) != 0) { /* Not a NULL frame? */
877     if ((d & 0x00ff0000) == 0) { /* IDLE */
878     } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */
879     ad += 44;
880     } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */
881     ad += 92;
882     }
883     }
884     }
885     } else {
886     if (incr < 0) {
887     ad -= 4;
888     d = get_long (ad);
889     if ((d & 0xff000000) != 0) {
890     if ((d & 0x00ff0000) == 0x00180000)
891     ad -= 6 * 4;
892     else if ((d & 0x00ff0000) == 0x00380000)
893     ad -= 14 * 4;
894     else if ((d & 0x00ff0000) == 0x00b40000)
895     ad -= 45 * 4;
896     }
897     } else {
898     d = get_long (ad);
899     ad += 4;
900     if ((d & 0xff000000) != 0) {
901     if ((d & 0x00ff0000) == 0x00180000)
902     ad += 6 * 4;
903     else if ((d & 0x00ff0000) == 0x00380000)
904     ad += 14 * 4;
905     else if ((d & 0x00ff0000) == 0x00b40000)
906     ad += 45 * 4;
907     }
908     }
909     }
910     if ((opcode & 0x38) == 0x18)
911     m68k_areg (regs, opcode & 7) = ad;
912     if ((opcode & 0x38) == 0x20)
913     m68k_areg (regs, opcode & 7) = ad;
914     }
915    
916     #if USE_LONG_DOUBLE
917     static const fpu_register const_e = 2.7182818284590452353602874713526625L;
918     static const fpu_register const_log10_e = 0.4342944819032518276511289189166051L;
919     static const fpu_register const_loge_10 = 2.3025850929940456840179914546843642L;
920     #else
921     static const fpu_register const_e = 2.7182818284590452354;
922     static const fpu_register const_log10_e = 0.43429448190325182765;
923     static const fpu_register const_loge_10 = 2.30258509299404568402;
924     #endif
925    
926     static const fpu_register power10[] = {
927     1e0, 1e1, 1e2, 1e4, 1e8, 1e16, 1e32, 1e64, 1e128, 1e256
928     #if USE_LONG_DOUBLE
929     , 1e512, 1e1024, 1e2048, 1e4096
930     #endif
931     };
932    
933     /* 128 words, indexed through the low byte of the 68k fpu control word */
934     static uae_u16 x86_fpucw[]={
935     0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, /* p0r0 */
936     0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, /* p0r1 */
937     0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, /* p0r2 */
938     0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, /* p0r3 */
939    
940     0x107f, 0x107f, 0x107f, 0x107f, 0x107f, 0x107f, 0x107f, 0x107f, /* p1r0 */
941     0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, /* p1r1 */
942     0x147f, 0x147f, 0x147f, 0x147f, 0x147f, 0x147f, 0x147f, 0x147f, /* p1r2 */
943     0x187f, 0x187f, 0x187f, 0x187f, 0x187f, 0x187f, 0x187f, 0x187f, /* p1r3 */
944    
945     0x127f, 0x127f, 0x127f, 0x127f, 0x127f, 0x127f, 0x127f, 0x127f, /* p2r0 */
946     0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, /* p2r1 */
947     0x167f, 0x167f, 0x167f, 0x167f, 0x167f, 0x167f, 0x167f, 0x167f, /* p2r2 */
948     0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, /* p2r3 */
949    
950     0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, /* p3r0 */
951     0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, /* p3r1 */
952     0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, /* p3r2 */
953     0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f /* p3r3 */
954     };
955    
956     void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
957     {
958     int reg;
959     int src;
960    
961     switch ((extra >> 13) & 0x7) {
962     case 3: /* 2nd most common */
963     if (put_fp_value ((extra >> 7)&7 , opcode, extra) < 0) {
964     FAIL(1);
965     return;
966    
967     }
968     return;
969     case 6:
970     case 7:
971     {
972     uae_u32 ad, list = 0;
973     int incr = 0;
974     if (extra & 0x2000) {
975     uae_u32 ad;
976    
977     /* FMOVEM FPP->memory */
978     switch ((extra >> 11) & 3) { /* Get out early if failure */
979     case 0:
980     case 2:
981     break;
982     case 1:
983     case 3:
984     default:
985     FAIL(1); return;
986     }
987     ad=get_fp_ad (opcode, &ad);
988     if (ad<0) {
989     m68k_setpc (m68k_getpc () - 4);
990     fpuop_illg (opcode,extra);
991     return;
992     }
993     switch ((extra >> 11) & 3) {
994     case 0: /* static pred */
995     list = extra & 0xff;
996     incr = -1;
997     break;
998     case 2: /* static postinc */
999     list = extra & 0xff;
1000     incr = 1;
1001     break;
1002     case 1: /* dynamic pred */
1003     case 3: /* dynamic postinc */
1004     abort();
1005     }
1006     if (incr < 0) { /* Predecrement */
1007     for (reg = 7; reg >= 0; reg--) {
1008     if (list & 0x80) {
1009     fmov_ext_mr((uae_u32)temp_fp,reg);
1010     delay;
1011     sub_l_ri(ad,4);
1012     mov_l_rm(S2,(uae_u32)temp_fp);
1013     writelong_clobber(ad,S2,S3);
1014     sub_l_ri(ad,4);
1015     mov_l_rm(S2,(uae_u32)temp_fp+4);
1016     writelong_clobber(ad,S2,S3);
1017     sub_l_ri(ad,4);
1018     mov_w_rm(S2,(uae_u32)temp_fp+8);
1019     writeword_clobber(ad,S2,S3);
1020     }
1021     list <<= 1;
1022     }
1023     }
1024     else { /* Postincrement */
1025     for (reg = 0; reg < 8; reg++) {
1026     if (list & 0x80) {
1027     fmov_ext_mr((uae_u32)temp_fp,reg);
1028     delay;
1029     mov_w_rm(S2,(uae_u32)temp_fp+8);
1030     writeword_clobber(ad,S2,S3);
1031     add_l_ri(ad,4);
1032     mov_l_rm(S2,(uae_u32)temp_fp+4);
1033     writelong_clobber(ad,S2,S3);
1034     add_l_ri(ad,4);
1035     mov_l_rm(S2,(uae_u32)temp_fp);
1036     writelong_clobber(ad,S2,S3);
1037     add_l_ri(ad,4);
1038     }
1039     list <<= 1;
1040     }
1041     }
1042     if ((opcode & 0x38) == 0x18)
1043     mov_l_rr((opcode & 7)+8,ad);
1044     if ((opcode & 0x38) == 0x20)
1045     mov_l_rr((opcode & 7)+8,ad);
1046     } else {
1047     /* FMOVEM memory->FPP */
1048    
1049     uae_u32 ad;
1050     switch ((extra >> 11) & 3) { /* Get out early if failure */
1051     case 0:
1052     case 2:
1053     break;
1054     case 1:
1055     case 3:
1056     default:
1057     FAIL(1); return;
1058     }
1059     ad=get_fp_ad (opcode, &ad);
1060     if (ad<0) {
1061     m68k_setpc (m68k_getpc () - 4);
1062     write_log("no ad\n");
1063     fpuop_illg (opcode,extra);
1064     return;
1065     }
1066     switch ((extra >> 11) & 3) {
1067     case 0: /* static pred */
1068     list = extra & 0xff;
1069     incr = -1;
1070     break;
1071     case 2: /* static postinc */
1072     list = extra & 0xff;
1073     incr = 1;
1074     break;
1075     case 1: /* dynamic pred */
1076     case 3: /* dynamic postinc */
1077     abort();
1078     }
1079    
1080     if (incr < 0) {
1081     // not reached
1082     for (reg = 7; reg >= 0; reg--) {
1083     uae_u32 wrd1, wrd2, wrd3;
1084     if (list & 0x80) {
1085     sub_l_ri(ad,4);
1086     readlong(ad,S2,S3);
1087     mov_l_mr((uae_u32)(temp_fp),S2);
1088     sub_l_ri(ad,4);
1089     readlong(ad,S2,S3);
1090     mov_l_mr((uae_u32)(temp_fp)+4,S2);
1091     sub_l_ri(ad,4);
1092     readword(ad,S2,S3);
1093     mov_w_mr(((uae_u32)temp_fp)+8,S2);
1094     delay2;
1095     fmov_ext_rm(reg,(uae_u32)(temp_fp));
1096     }
1097     list <<= 1;
1098     }
1099     }
1100     else {
1101     for (reg = 0; reg < 8; reg++) {
1102     uae_u32 wrd1, wrd2, wrd3;
1103     if (list & 0x80) {
1104     readword(ad,S2,S3);
1105     mov_w_mr(((uae_u32)temp_fp)+8,S2);
1106     add_l_ri(ad,4);
1107     readlong(ad,S2,S3);
1108     mov_l_mr((uae_u32)(temp_fp)+4,S2);
1109     add_l_ri(ad,4);
1110     readlong(ad,S2,S3);
1111     mov_l_mr((uae_u32)(temp_fp),S2);
1112     add_l_ri(ad,4);
1113     delay2;
1114     fmov_ext_rm(reg,(uae_u32)(temp_fp));
1115     }
1116     list <<= 1;
1117     }
1118     }
1119     if ((opcode & 0x38) == 0x18)
1120     mov_l_rr((opcode & 7)+8,ad);
1121     if ((opcode & 0x38) == 0x20)
1122     mov_l_rr((opcode & 7)+8,ad);
1123     }
1124     }
1125     return;
1126    
1127     case 4:
1128     case 5: /* rare */
1129     if ((opcode & 0x30) == 0) {
1130     if (extra & 0x2000) {
1131     if (extra & 0x1000) {
1132     #if HANDLE_FPCR
1133     mov_l_rm(opcode & 15, (uae_u32)&fpu.fpcr.rounding_mode);
1134     or_l_rm(opcode & 15, (uae_u32)&fpu.fpcr.rounding_precision);
1135     #else
1136     FAIL(1);
1137     return;
1138     #endif
1139     }
1140     if (extra & 0x0800) {
1141     FAIL(1);
1142     return;
1143     }
1144     if (extra & 0x0400) {
1145     mov_l_rm(opcode & 15,(uae_u32)&fpu.instruction_address);
1146     return;
1147     }
1148     } else {
1149     // gb-- moved here so that we may FAIL() without generating any code
1150     if (extra & 0x0800) {
1151     // set_fpsr(m68k_dreg (regs, opcode & 15));
1152     FAIL(1);
1153     return;
1154     }
1155     if (extra & 0x1000) {
1156     #if HANDLE_FPCR
1157     #if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
1158     FAIL(1);
1159     return;
1160     #endif
1161     mov_l_rr(S1,opcode & 15);
1162     mov_l_rr(S2,opcode & 15);
1163     and_l_ri(S1,FPCR_ROUNDING_PRECISION);
1164     and_l_ri(S2,FPCR_ROUNDING_MODE);
1165     mov_l_mr((uae_u32)&fpu.fpcr.rounding_precision,S1);
1166     mov_l_mr((uae_u32)&fpu.fpcr.rounding_mode,S2);
1167     #else
1168     FAIL(1);
1169     return;
1170     #endif
1171     // return; gb-- FMOVEM could also operate on fpiar
1172     }
1173     if (extra & 0x0400) {
1174     mov_l_mr((uae_u32)&fpu.instruction_address,opcode & 15);
1175     // return; gb-- we have to process all FMOVEM bits before returning
1176     }
1177     return;
1178     }
1179     } else if ((opcode & 0x3f) == 0x3c) {
1180     if ((extra & 0x2000) == 0) {
1181     // gb-- moved here so that we may FAIL() without generating any code
1182     if (extra & 0x0800) {
1183     FAIL(1);
1184     return;
1185     }
1186     if (extra & 0x1000) {
1187     uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4);
1188     #if HANDLE_FPCR
1189     #if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
1190     FAIL(1);
1191     return;
1192     #endif
1193     // mov_l_mi((uae_u32)&regs.fpcr,val);
1194     mov_l_ri(S1,val);
1195     mov_l_ri(S2,val);
1196     and_l_ri(S1,FPCR_ROUNDING_PRECISION);
1197     and_l_ri(S2,FPCR_ROUNDING_MODE);
1198     mov_l_mr((uae_u32)&fpu.fpcr.rounding_precision,S1);
1199     mov_l_mr((uae_u32)&fpu.fpcr.rounding_mode,S2);
1200     #else
1201     FAIL(1);
1202     return;
1203     #endif
1204     // return; gb-- FMOVEM could also operate on fpiar
1205     }
1206     if (extra & 0x0400) {
1207     uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4);
1208     mov_l_mi((uae_u32)&fpu.instruction_address,val);
1209     // return; gb-- we have to process all FMOVEM bits before returning
1210     }
1211     return;
1212     }
1213     FAIL(1);
1214     return;
1215     } else if (extra & 0x2000) {
1216     FAIL(1);
1217     return;
1218     } else {
1219     FAIL(1);
1220     return;
1221     }
1222     FAIL(1);
1223     return;
1224    
1225     case 0:
1226     case 2: /* Extremely common */
1227     reg = (extra >> 7) & 7;
1228     if ((extra & 0xfc00) == 0x5c00) {
1229     switch (extra & 0x7f) {
1230     case 0x00:
1231     fmov_pi(reg);
1232     break;
1233     case 0x0b:
1234     fmov_log10_2(reg);
1235     break;
1236     case 0x0c:
1237     #if USE_LONG_DOUBLE
1238     fmov_ext_rm(reg,(uae_u32)&const_e);
1239     #else
1240     fmov_rm(reg,(uae_u32)&const_e);
1241     #endif
1242     break;
1243     case 0x0d:
1244     fmov_log2_e(reg);
1245     break;
1246     case 0x0e:
1247     #if USE_LONG_DOUBLE
1248     fmov_ext_rm(reg,(uae_u32)&const_log10_e);
1249     #else
1250     fmov_rm(reg,(uae_u32)&const_log10_e);
1251     #endif
1252     break;
1253     case 0x0f:
1254     fmov_0(reg);
1255     break;
1256     case 0x30:
1257     fmov_loge_2(reg);
1258     break;
1259     case 0x31:
1260     #if USE_LONG_DOUBLE
1261     fmov_ext_rm(reg,(uae_u32)&const_loge_10);
1262     #else
1263     fmov_rm(reg,(uae_u32)&const_loge_10);
1264     #endif
1265     break;
1266     case 0x32:
1267     fmov_1(reg);
1268     break;
1269     case 0x33:
1270     case 0x34:
1271     case 0x35:
1272     case 0x36:
1273     case 0x37:
1274     case 0x38:
1275     case 0x39:
1276     case 0x3a:
1277     case 0x3b:
1278     #if USE_LONG_DOUBLE
1279     case 0x3c:
1280     case 0x3d:
1281     case 0x3e:
1282     case 0x3f:
1283     fmov_ext_rm(reg,(uae_u32)(power10+(extra & 0x7f)-0x32));
1284     #else
1285     fmov_rm(reg,(uae_u32)(power10+(extra & 0x7f)-0x32));
1286     #endif
1287     break;
1288     default:
1289     /* This is not valid, so we fail */
1290     FAIL(1);
1291     return;
1292     }
1293     return;
1294     }
1295    
1296     switch (extra & 0x7f) {
1297     case 0x00: /* FMOVE */
1298     case 0x40: /* Explicit rounding. This is just a quick fix. Same
1299     * for all other cases that have three choices */
1300     case 0x44:
1301     dont_care_fflags();
1302     src=get_fp_value (opcode, extra);
1303     if (src < 0) {
1304     FAIL(1); /* Illegal instruction */
1305     return;
1306     }
1307     fmov_rr(reg,src);
1308     MAKE_FPSR (src);
1309     break;
1310     case 0x01: /* FINT */
1311     FAIL(1);
1312     return;
1313     dont_care_fflags();
1314     case 0x02: /* FSINH */
1315     FAIL(1);
1316     return;
1317     dont_care_fflags();
1318     break;
1319     case 0x03: /* FINTRZ */
1320     #if USE_X86_FPUCW
1321     /* If we have control over the CW, we can do this */
1322     dont_care_fflags();
1323     src=get_fp_value (opcode, extra);
1324     if (src < 0) {
1325     FAIL(1); /* Illegal instruction */
1326     return;
1327     }
1328     mov_l_ri(S1,16); /* Switch to "round to zero" mode */
1329     fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
1330    
1331     frndint_rr(reg,src);
1332    
1333     /* restore control word */
1334     mov_l_rm(S1,(uae_u32)&regs.fpcr);
1335     and_l_ri(S1,0x000000f0);
1336     fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
1337    
1338     MAKE_FPSR (reg);
1339     break;
1340     #endif
1341     FAIL(1);
1342     return;
1343     break;
1344     case 0x04: /* FSQRT */
1345     case 0x41:
1346     case 0x45:
1347     dont_care_fflags();
1348     src=get_fp_value (opcode, extra);
1349     if (src < 0) {
1350     FAIL(1); /* Illegal instruction */
1351     return;
1352     }
1353     fsqrt_rr(reg,src);
1354     MAKE_FPSR (reg);
1355     break;
1356     case 0x06: /* FLOGNP1 */
1357     FAIL(1);
1358     return;
1359     dont_care_fflags();
1360     break;
1361     case 0x08: /* FETOXM1 */
1362     FAIL(1);
1363     return;
1364     dont_care_fflags();
1365     break;
1366     case 0x09: /* FTANH */
1367     FAIL(1);
1368     return;
1369     dont_care_fflags();
1370     break;
1371     case 0x0a: /* FATAN */
1372     FAIL(1);
1373     return;
1374     dont_care_fflags();
1375     break;
1376     case 0x0c: /* FASIN */
1377     FAIL(1);
1378     return;
1379     dont_care_fflags();
1380     break;
1381     case 0x0d: /* FATANH */
1382     FAIL(1);
1383     return;
1384     dont_care_fflags();
1385     break;
1386     case 0x0e: /* FSIN */
1387     dont_care_fflags();
1388     src=get_fp_value (opcode, extra);
1389     if (src < 0) {
1390     FAIL(1); /* Illegal instruction */
1391     return;
1392     }
1393     fsin_rr(reg,src);
1394     MAKE_FPSR (reg);
1395     break;
1396     case 0x0f: /* FTAN */
1397     FAIL(1);
1398     return;
1399     dont_care_fflags();
1400     break;
1401     case 0x10: /* FETOX */
1402     dont_care_fflags();
1403     src=get_fp_value (opcode, extra);
1404     if (src < 0) {
1405     FAIL(1); /* Illegal instruction */
1406     return;
1407     }
1408     fetox_rr(reg,src);
1409     MAKE_FPSR (reg);
1410     break;
1411     case 0x11: /* FTWOTOX */
1412     dont_care_fflags();
1413     src=get_fp_value (opcode, extra);
1414     if (src < 0) {
1415     FAIL(1); /* Illegal instruction */
1416     return;
1417     }
1418     ftwotox_rr(reg,src);
1419     MAKE_FPSR (reg);
1420     break;
1421     case 0x12: /* FTENTOX */
1422     FAIL(1);
1423     return;
1424     dont_care_fflags();
1425     break;
1426     case 0x14: /* FLOGN */
1427     FAIL(1);
1428     return;
1429     dont_care_fflags();
1430     break;
1431     case 0x15: /* FLOG10 */
1432     FAIL(1);
1433     return;
1434     dont_care_fflags();
1435     break;
1436     case 0x16: /* FLOG2 */
1437     dont_care_fflags();
1438     src=get_fp_value (opcode, extra);
1439     if (src < 0) {
1440     FAIL(1); /* Illegal instruction */
1441     return;
1442     }
1443     flog2_rr(reg,src);
1444     MAKE_FPSR (reg);
1445     break;
1446     case 0x18: /* FABS */
1447     case 0x58:
1448     case 0x5c:
1449     dont_care_fflags();
1450     src=get_fp_value (opcode, extra);
1451     if (src < 0) {
1452     FAIL(1); /* Illegal instruction */
1453     return;
1454     }
1455     fabs_rr(reg,src);
1456     MAKE_FPSR (reg);
1457     break;
1458     case 0x19: /* FCOSH */
1459     FAIL(1);
1460     return;
1461     dont_care_fflags();
1462     break;
1463     case 0x1a: /* FNEG */
1464     case 0x5a:
1465     case 0x5e:
1466     dont_care_fflags();
1467     src=get_fp_value (opcode, extra);
1468     if (src < 0) {
1469     FAIL(1); /* Illegal instruction */
1470     return;
1471     }
1472     fneg_rr(reg,src);
1473     MAKE_FPSR (reg);
1474     break;
1475     case 0x1c: /* FACOS */
1476     FAIL(1);
1477     return;
1478     dont_care_fflags();
1479     break;
1480     case 0x1d: /* FCOS */
1481     dont_care_fflags();
1482     src=get_fp_value (opcode, extra);
1483     if (src < 0) {
1484     FAIL(1); /* Illegal instruction */
1485     return;
1486     }
1487     fcos_rr(reg,src);
1488     MAKE_FPSR (reg);
1489     break;
1490     case 0x1e: /* FGETEXP */
1491     FAIL(1);
1492     return;
1493     dont_care_fflags();
1494     break;
1495     case 0x1f: /* FGETMAN */
1496     FAIL(1);
1497     return;
1498     dont_care_fflags();
1499     break;
1500     case 0x20: /* FDIV */
1501     case 0x60:
1502     case 0x64:
1503     dont_care_fflags();
1504     src=get_fp_value (opcode, extra);
1505     if (src < 0) {
1506     FAIL(1); /* Illegal instruction */
1507     return;
1508     }
1509     fdiv_rr(reg,src);
1510     MAKE_FPSR (reg);
1511     break;
1512     case 0x21: /* FMOD */
1513     dont_care_fflags();
1514     src=get_fp_value (opcode, extra);
1515     if (src < 0) {
1516     FAIL(1); /* Illegal instruction */
1517     return;
1518     }
1519     frem_rr(reg,src);
1520     MAKE_FPSR (reg);
1521     break;
1522     case 0x22: /* FADD */
1523     case 0x62:
1524     case 0x66:
1525     dont_care_fflags();
1526     src=get_fp_value (opcode, extra);
1527     if (src < 0) {
1528     FAIL(1); /* Illegal instruction */
1529     return;
1530     }
1531     fadd_rr(reg,src);
1532     MAKE_FPSR (reg);
1533     break;
1534     case 0x23: /* FMUL */
1535     case 0x63:
1536     case 0x67:
1537     dont_care_fflags();
1538     src=get_fp_value (opcode, extra);
1539     if (src < 0) {
1540     FAIL(1); /* Illegal instruction */
1541     return;
1542     }
1543     fmul_rr(reg,src);
1544     MAKE_FPSR (reg);
1545     break;
1546     case 0x24: /* FSGLDIV */
1547     dont_care_fflags();
1548     src=get_fp_value (opcode, extra);
1549     if (src < 0) {
1550     FAIL(1); /* Illegal instruction */
1551     return;
1552     }
1553     fdiv_rr(reg,src);
1554     MAKE_FPSR (reg);
1555     break;
1556     case 0x25: /* FREM */
1557     // gb-- disabled because the quotient byte must be computed
1558     // otherwise, free rotation in ClarisWorks doesn't work.
1559     FAIL(1);
1560     return;
1561     dont_care_fflags();
1562     src=get_fp_value (opcode, extra);
1563     if (src < 0) {
1564     FAIL(1); /* Illegal instruction */
1565     return;
1566     }
1567     frem1_rr(reg,src);
1568     MAKE_FPSR (reg);
1569     break;
1570     case 0x26: /* FSCALE */
1571     dont_care_fflags();
1572     FAIL(1);
1573     return;
1574     break;
1575     case 0x27: /* FSGLMUL */
1576     dont_care_fflags();
1577     src=get_fp_value (opcode, extra);
1578     if (src < 0) {
1579     FAIL(1); /* Illegal instruction */
1580     return;
1581     }
1582     fmul_rr(reg,src);
1583     MAKE_FPSR (reg);
1584     break;
1585     case 0x28: /* FSUB */
1586     case 0x68:
1587     case 0x6c:
1588     dont_care_fflags();
1589     src=get_fp_value (opcode, extra);
1590     if (src < 0) {
1591     FAIL(1); /* Illegal instruction */
1592     return;
1593     }
1594     fsub_rr(reg,src);
1595     MAKE_FPSR (reg);
1596     break;
1597     case 0x30: /* FSINCOS */
1598     case 0x31:
1599     case 0x32:
1600     case 0x33:
1601     case 0x34:
1602     case 0x35:
1603     case 0x36:
1604     case 0x37:
1605     FAIL(1);
1606     return;
1607     dont_care_fflags();
1608     break;
1609     case 0x38: /* FCMP */
1610     src=get_fp_value (opcode, extra);
1611     if (src < 0) {
1612     FAIL(1); /* Illegal instruction */
1613     return;
1614     }
1615     fmov_rr(FP_RESULT,reg);
1616     fsub_rr(FP_RESULT,src); /* Right way? */
1617     break;
1618     case 0x3a: /* FTST */
1619     src=get_fp_value (opcode, extra);
1620     if (src < 0) {
1621     FAIL(1); /* Illegal instruction */
1622     return;
1623     }
1624     fmov_rr(FP_RESULT,src);
1625     break;
1626     default:
1627     FAIL(1);
1628     return;
1629     break;
1630     }
1631     return;
1632     }
1633     m68k_setpc (m68k_getpc () - 4);
1634     fpuop_illg (opcode,extra);
1635     }