ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp
Revision: 1.7
Committed: 2004-11-02T23:28:19Z (20 years ago) by gbeauche
Branch: MAIN
Changes since 1.6: +1 -1 lines
Log Message:
fix JIT FPU for x86_64

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 cebix 1.6 * Adaptation for Basilisk II and improvements, copyright 2000-2004
7 gbeauche 1.3 * Gwenole Beauchesne
8     *
9 cebix 1.6 * Basilisk II (C) 1997-2004 Christian Bauer
10 gbeauche 1.3 *
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 gbeauche 1.7 uae_s32 temp_fp[4]; /* To convert between FP/integer */
96 gbeauche 1.1
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 gbeauche 1.5 abort();
987 gbeauche 1.1 m68k_setpc (m68k_getpc () - 4);
988     fpuop_illg (opcode,extra);
989     return;
990     }
991     switch ((extra >> 11) & 3) {
992     case 0: /* static pred */
993     list = extra & 0xff;
994     incr = -1;
995     break;
996     case 2: /* static postinc */
997     list = extra & 0xff;
998     incr = 1;
999     break;
1000     case 1: /* dynamic pred */
1001     case 3: /* dynamic postinc */
1002     abort();
1003     }
1004     if (incr < 0) { /* Predecrement */
1005     for (reg = 7; reg >= 0; reg--) {
1006     if (list & 0x80) {
1007     fmov_ext_mr((uae_u32)temp_fp,reg);
1008     delay;
1009     sub_l_ri(ad,4);
1010     mov_l_rm(S2,(uae_u32)temp_fp);
1011     writelong_clobber(ad,S2,S3);
1012     sub_l_ri(ad,4);
1013     mov_l_rm(S2,(uae_u32)temp_fp+4);
1014     writelong_clobber(ad,S2,S3);
1015     sub_l_ri(ad,4);
1016     mov_w_rm(S2,(uae_u32)temp_fp+8);
1017     writeword_clobber(ad,S2,S3);
1018     }
1019     list <<= 1;
1020     }
1021     }
1022     else { /* Postincrement */
1023     for (reg = 0; reg < 8; reg++) {
1024     if (list & 0x80) {
1025     fmov_ext_mr((uae_u32)temp_fp,reg);
1026     delay;
1027     mov_w_rm(S2,(uae_u32)temp_fp+8);
1028     writeword_clobber(ad,S2,S3);
1029     add_l_ri(ad,4);
1030     mov_l_rm(S2,(uae_u32)temp_fp+4);
1031     writelong_clobber(ad,S2,S3);
1032     add_l_ri(ad,4);
1033     mov_l_rm(S2,(uae_u32)temp_fp);
1034     writelong_clobber(ad,S2,S3);
1035     add_l_ri(ad,4);
1036     }
1037     list <<= 1;
1038     }
1039     }
1040     if ((opcode & 0x38) == 0x18)
1041     mov_l_rr((opcode & 7)+8,ad);
1042     if ((opcode & 0x38) == 0x20)
1043     mov_l_rr((opcode & 7)+8,ad);
1044     } else {
1045     /* FMOVEM memory->FPP */
1046    
1047     uae_u32 ad;
1048     switch ((extra >> 11) & 3) { /* Get out early if failure */
1049     case 0:
1050     case 2:
1051     break;
1052     case 1:
1053     case 3:
1054     default:
1055     FAIL(1); return;
1056     }
1057     ad=get_fp_ad (opcode, &ad);
1058     if (ad<0) {
1059 gbeauche 1.5 abort();
1060 gbeauche 1.1 m68k_setpc (m68k_getpc () - 4);
1061     write_log("no ad\n");
1062     fpuop_illg (opcode,extra);
1063     return;
1064     }
1065     switch ((extra >> 11) & 3) {
1066     case 0: /* static pred */
1067     list = extra & 0xff;
1068     incr = -1;
1069     break;
1070     case 2: /* static postinc */
1071     list = extra & 0xff;
1072     incr = 1;
1073     break;
1074     case 1: /* dynamic pred */
1075     case 3: /* dynamic postinc */
1076     abort();
1077     }
1078    
1079     if (incr < 0) {
1080     // not reached
1081     for (reg = 7; reg >= 0; reg--) {
1082     uae_u32 wrd1, wrd2, wrd3;
1083     if (list & 0x80) {
1084     sub_l_ri(ad,4);
1085     readlong(ad,S2,S3);
1086     mov_l_mr((uae_u32)(temp_fp),S2);
1087     sub_l_ri(ad,4);
1088     readlong(ad,S2,S3);
1089     mov_l_mr((uae_u32)(temp_fp)+4,S2);
1090     sub_l_ri(ad,4);
1091     readword(ad,S2,S3);
1092     mov_w_mr(((uae_u32)temp_fp)+8,S2);
1093     delay2;
1094     fmov_ext_rm(reg,(uae_u32)(temp_fp));
1095     }
1096     list <<= 1;
1097     }
1098     }
1099     else {
1100     for (reg = 0; reg < 8; reg++) {
1101     uae_u32 wrd1, wrd2, wrd3;
1102     if (list & 0x80) {
1103     readword(ad,S2,S3);
1104     mov_w_mr(((uae_u32)temp_fp)+8,S2);
1105     add_l_ri(ad,4);
1106     readlong(ad,S2,S3);
1107     mov_l_mr((uae_u32)(temp_fp)+4,S2);
1108     add_l_ri(ad,4);
1109     readlong(ad,S2,S3);
1110     mov_l_mr((uae_u32)(temp_fp),S2);
1111     add_l_ri(ad,4);
1112     delay2;
1113     fmov_ext_rm(reg,(uae_u32)(temp_fp));
1114     }
1115     list <<= 1;
1116     }
1117     }
1118     if ((opcode & 0x38) == 0x18)
1119     mov_l_rr((opcode & 7)+8,ad);
1120     if ((opcode & 0x38) == 0x20)
1121     mov_l_rr((opcode & 7)+8,ad);
1122     }
1123     }
1124     return;
1125    
1126     case 4:
1127     case 5: /* rare */
1128     if ((opcode & 0x30) == 0) {
1129     if (extra & 0x2000) {
1130     if (extra & 0x1000) {
1131     #if HANDLE_FPCR
1132     mov_l_rm(opcode & 15, (uae_u32)&fpu.fpcr.rounding_mode);
1133     or_l_rm(opcode & 15, (uae_u32)&fpu.fpcr.rounding_precision);
1134     #else
1135     FAIL(1);
1136     return;
1137     #endif
1138     }
1139     if (extra & 0x0800) {
1140     FAIL(1);
1141     return;
1142     }
1143     if (extra & 0x0400) {
1144     mov_l_rm(opcode & 15,(uae_u32)&fpu.instruction_address);
1145     return;
1146     }
1147     } else {
1148     // gb-- moved here so that we may FAIL() without generating any code
1149     if (extra & 0x0800) {
1150     // set_fpsr(m68k_dreg (regs, opcode & 15));
1151     FAIL(1);
1152     return;
1153     }
1154     if (extra & 0x1000) {
1155     #if HANDLE_FPCR
1156     #if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
1157     FAIL(1);
1158     return;
1159     #endif
1160     mov_l_rr(S1,opcode & 15);
1161     mov_l_rr(S2,opcode & 15);
1162     and_l_ri(S1,FPCR_ROUNDING_PRECISION);
1163     and_l_ri(S2,FPCR_ROUNDING_MODE);
1164     mov_l_mr((uae_u32)&fpu.fpcr.rounding_precision,S1);
1165     mov_l_mr((uae_u32)&fpu.fpcr.rounding_mode,S2);
1166     #else
1167     FAIL(1);
1168     return;
1169     #endif
1170     // return; gb-- FMOVEM could also operate on fpiar
1171     }
1172     if (extra & 0x0400) {
1173     mov_l_mr((uae_u32)&fpu.instruction_address,opcode & 15);
1174     // return; gb-- we have to process all FMOVEM bits before returning
1175     }
1176     return;
1177     }
1178     } else if ((opcode & 0x3f) == 0x3c) {
1179     if ((extra & 0x2000) == 0) {
1180     // gb-- moved here so that we may FAIL() without generating any code
1181     if (extra & 0x0800) {
1182     FAIL(1);
1183     return;
1184     }
1185     if (extra & 0x1000) {
1186     uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4);
1187     #if HANDLE_FPCR
1188     #if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
1189     FAIL(1);
1190     return;
1191     #endif
1192     // mov_l_mi((uae_u32)&regs.fpcr,val);
1193     mov_l_ri(S1,val);
1194     mov_l_ri(S2,val);
1195     and_l_ri(S1,FPCR_ROUNDING_PRECISION);
1196     and_l_ri(S2,FPCR_ROUNDING_MODE);
1197     mov_l_mr((uae_u32)&fpu.fpcr.rounding_precision,S1);
1198     mov_l_mr((uae_u32)&fpu.fpcr.rounding_mode,S2);
1199     #else
1200     FAIL(1);
1201     return;
1202     #endif
1203     // return; gb-- FMOVEM could also operate on fpiar
1204     }
1205     if (extra & 0x0400) {
1206     uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4);
1207     mov_l_mi((uae_u32)&fpu.instruction_address,val);
1208     // return; gb-- we have to process all FMOVEM bits before returning
1209     }
1210     return;
1211     }
1212     FAIL(1);
1213     return;
1214     } else if (extra & 0x2000) {
1215     FAIL(1);
1216     return;
1217     } else {
1218     FAIL(1);
1219     return;
1220     }
1221     FAIL(1);
1222     return;
1223    
1224     case 0:
1225     case 2: /* Extremely common */
1226     reg = (extra >> 7) & 7;
1227     if ((extra & 0xfc00) == 0x5c00) {
1228     switch (extra & 0x7f) {
1229     case 0x00:
1230     fmov_pi(reg);
1231     break;
1232     case 0x0b:
1233     fmov_log10_2(reg);
1234     break;
1235     case 0x0c:
1236     #if USE_LONG_DOUBLE
1237     fmov_ext_rm(reg,(uae_u32)&const_e);
1238     #else
1239     fmov_rm(reg,(uae_u32)&const_e);
1240     #endif
1241     break;
1242     case 0x0d:
1243     fmov_log2_e(reg);
1244     break;
1245     case 0x0e:
1246     #if USE_LONG_DOUBLE
1247     fmov_ext_rm(reg,(uae_u32)&const_log10_e);
1248     #else
1249     fmov_rm(reg,(uae_u32)&const_log10_e);
1250     #endif
1251     break;
1252     case 0x0f:
1253     fmov_0(reg);
1254     break;
1255     case 0x30:
1256     fmov_loge_2(reg);
1257     break;
1258     case 0x31:
1259     #if USE_LONG_DOUBLE
1260     fmov_ext_rm(reg,(uae_u32)&const_loge_10);
1261     #else
1262     fmov_rm(reg,(uae_u32)&const_loge_10);
1263     #endif
1264     break;
1265     case 0x32:
1266     fmov_1(reg);
1267     break;
1268     case 0x33:
1269     case 0x34:
1270     case 0x35:
1271     case 0x36:
1272     case 0x37:
1273     case 0x38:
1274     case 0x39:
1275     case 0x3a:
1276     case 0x3b:
1277     #if USE_LONG_DOUBLE
1278     case 0x3c:
1279     case 0x3d:
1280     case 0x3e:
1281     case 0x3f:
1282     fmov_ext_rm(reg,(uae_u32)(power10+(extra & 0x7f)-0x32));
1283     #else
1284     fmov_rm(reg,(uae_u32)(power10+(extra & 0x7f)-0x32));
1285     #endif
1286     break;
1287     default:
1288     /* This is not valid, so we fail */
1289     FAIL(1);
1290     return;
1291     }
1292     return;
1293     }
1294    
1295     switch (extra & 0x7f) {
1296     case 0x00: /* FMOVE */
1297     case 0x40: /* Explicit rounding. This is just a quick fix. Same
1298     * for all other cases that have three choices */
1299     case 0x44:
1300     dont_care_fflags();
1301     src=get_fp_value (opcode, extra);
1302     if (src < 0) {
1303     FAIL(1); /* Illegal instruction */
1304     return;
1305     }
1306     fmov_rr(reg,src);
1307     MAKE_FPSR (src);
1308     break;
1309     case 0x01: /* FINT */
1310     FAIL(1);
1311     return;
1312     dont_care_fflags();
1313     case 0x02: /* FSINH */
1314     FAIL(1);
1315     return;
1316     dont_care_fflags();
1317     break;
1318     case 0x03: /* FINTRZ */
1319     #if USE_X86_FPUCW
1320     /* If we have control over the CW, we can do this */
1321     dont_care_fflags();
1322     src=get_fp_value (opcode, extra);
1323     if (src < 0) {
1324     FAIL(1); /* Illegal instruction */
1325     return;
1326     }
1327     mov_l_ri(S1,16); /* Switch to "round to zero" mode */
1328     fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
1329    
1330     frndint_rr(reg,src);
1331    
1332     /* restore control word */
1333     mov_l_rm(S1,(uae_u32)&regs.fpcr);
1334     and_l_ri(S1,0x000000f0);
1335     fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
1336    
1337     MAKE_FPSR (reg);
1338     break;
1339     #endif
1340     FAIL(1);
1341     return;
1342     break;
1343     case 0x04: /* FSQRT */
1344     case 0x41:
1345     case 0x45:
1346     dont_care_fflags();
1347     src=get_fp_value (opcode, extra);
1348     if (src < 0) {
1349     FAIL(1); /* Illegal instruction */
1350     return;
1351     }
1352     fsqrt_rr(reg,src);
1353     MAKE_FPSR (reg);
1354     break;
1355     case 0x06: /* FLOGNP1 */
1356     FAIL(1);
1357     return;
1358     dont_care_fflags();
1359     break;
1360     case 0x08: /* FETOXM1 */
1361     FAIL(1);
1362     return;
1363     dont_care_fflags();
1364     break;
1365     case 0x09: /* FTANH */
1366     FAIL(1);
1367     return;
1368     dont_care_fflags();
1369     break;
1370     case 0x0a: /* FATAN */
1371     FAIL(1);
1372     return;
1373     dont_care_fflags();
1374     break;
1375     case 0x0c: /* FASIN */
1376     FAIL(1);
1377     return;
1378     dont_care_fflags();
1379     break;
1380     case 0x0d: /* FATANH */
1381     FAIL(1);
1382     return;
1383     dont_care_fflags();
1384     break;
1385     case 0x0e: /* FSIN */
1386     dont_care_fflags();
1387     src=get_fp_value (opcode, extra);
1388     if (src < 0) {
1389     FAIL(1); /* Illegal instruction */
1390     return;
1391     }
1392     fsin_rr(reg,src);
1393     MAKE_FPSR (reg);
1394     break;
1395     case 0x0f: /* FTAN */
1396     FAIL(1);
1397     return;
1398     dont_care_fflags();
1399     break;
1400     case 0x10: /* FETOX */
1401     dont_care_fflags();
1402     src=get_fp_value (opcode, extra);
1403     if (src < 0) {
1404     FAIL(1); /* Illegal instruction */
1405     return;
1406     }
1407     fetox_rr(reg,src);
1408     MAKE_FPSR (reg);
1409     break;
1410     case 0x11: /* FTWOTOX */
1411     dont_care_fflags();
1412     src=get_fp_value (opcode, extra);
1413     if (src < 0) {
1414     FAIL(1); /* Illegal instruction */
1415     return;
1416     }
1417     ftwotox_rr(reg,src);
1418     MAKE_FPSR (reg);
1419     break;
1420     case 0x12: /* FTENTOX */
1421     FAIL(1);
1422     return;
1423     dont_care_fflags();
1424     break;
1425     case 0x14: /* FLOGN */
1426     FAIL(1);
1427     return;
1428     dont_care_fflags();
1429     break;
1430     case 0x15: /* FLOG10 */
1431     FAIL(1);
1432     return;
1433     dont_care_fflags();
1434     break;
1435     case 0x16: /* FLOG2 */
1436     dont_care_fflags();
1437     src=get_fp_value (opcode, extra);
1438     if (src < 0) {
1439     FAIL(1); /* Illegal instruction */
1440     return;
1441     }
1442     flog2_rr(reg,src);
1443     MAKE_FPSR (reg);
1444     break;
1445     case 0x18: /* FABS */
1446     case 0x58:
1447     case 0x5c:
1448     dont_care_fflags();
1449     src=get_fp_value (opcode, extra);
1450     if (src < 0) {
1451     FAIL(1); /* Illegal instruction */
1452     return;
1453     }
1454     fabs_rr(reg,src);
1455     MAKE_FPSR (reg);
1456     break;
1457     case 0x19: /* FCOSH */
1458     FAIL(1);
1459     return;
1460     dont_care_fflags();
1461     break;
1462     case 0x1a: /* FNEG */
1463     case 0x5a:
1464     case 0x5e:
1465     dont_care_fflags();
1466     src=get_fp_value (opcode, extra);
1467     if (src < 0) {
1468     FAIL(1); /* Illegal instruction */
1469     return;
1470     }
1471     fneg_rr(reg,src);
1472     MAKE_FPSR (reg);
1473     break;
1474     case 0x1c: /* FACOS */
1475     FAIL(1);
1476     return;
1477     dont_care_fflags();
1478     break;
1479     case 0x1d: /* FCOS */
1480     dont_care_fflags();
1481     src=get_fp_value (opcode, extra);
1482     if (src < 0) {
1483     FAIL(1); /* Illegal instruction */
1484     return;
1485     }
1486     fcos_rr(reg,src);
1487     MAKE_FPSR (reg);
1488     break;
1489     case 0x1e: /* FGETEXP */
1490     FAIL(1);
1491     return;
1492     dont_care_fflags();
1493     break;
1494     case 0x1f: /* FGETMAN */
1495     FAIL(1);
1496     return;
1497     dont_care_fflags();
1498     break;
1499     case 0x20: /* FDIV */
1500     case 0x60:
1501     case 0x64:
1502     dont_care_fflags();
1503     src=get_fp_value (opcode, extra);
1504     if (src < 0) {
1505     FAIL(1); /* Illegal instruction */
1506     return;
1507     }
1508     fdiv_rr(reg,src);
1509     MAKE_FPSR (reg);
1510     break;
1511     case 0x21: /* FMOD */
1512     dont_care_fflags();
1513     src=get_fp_value (opcode, extra);
1514     if (src < 0) {
1515     FAIL(1); /* Illegal instruction */
1516     return;
1517     }
1518     frem_rr(reg,src);
1519     MAKE_FPSR (reg);
1520     break;
1521     case 0x22: /* FADD */
1522     case 0x62:
1523     case 0x66:
1524     dont_care_fflags();
1525     src=get_fp_value (opcode, extra);
1526     if (src < 0) {
1527     FAIL(1); /* Illegal instruction */
1528     return;
1529     }
1530     fadd_rr(reg,src);
1531     MAKE_FPSR (reg);
1532     break;
1533     case 0x23: /* FMUL */
1534     case 0x63:
1535     case 0x67:
1536     dont_care_fflags();
1537     src=get_fp_value (opcode, extra);
1538     if (src < 0) {
1539     FAIL(1); /* Illegal instruction */
1540     return;
1541     }
1542     fmul_rr(reg,src);
1543     MAKE_FPSR (reg);
1544     break;
1545     case 0x24: /* FSGLDIV */
1546     dont_care_fflags();
1547     src=get_fp_value (opcode, extra);
1548     if (src < 0) {
1549     FAIL(1); /* Illegal instruction */
1550     return;
1551     }
1552     fdiv_rr(reg,src);
1553     MAKE_FPSR (reg);
1554     break;
1555     case 0x25: /* FREM */
1556     // gb-- disabled because the quotient byte must be computed
1557     // otherwise, free rotation in ClarisWorks doesn't work.
1558     FAIL(1);
1559     return;
1560     dont_care_fflags();
1561     src=get_fp_value (opcode, extra);
1562     if (src < 0) {
1563     FAIL(1); /* Illegal instruction */
1564     return;
1565     }
1566     frem1_rr(reg,src);
1567     MAKE_FPSR (reg);
1568     break;
1569     case 0x26: /* FSCALE */
1570     dont_care_fflags();
1571     FAIL(1);
1572     return;
1573     break;
1574     case 0x27: /* FSGLMUL */
1575     dont_care_fflags();
1576     src=get_fp_value (opcode, extra);
1577     if (src < 0) {
1578     FAIL(1); /* Illegal instruction */
1579     return;
1580     }
1581     fmul_rr(reg,src);
1582     MAKE_FPSR (reg);
1583     break;
1584     case 0x28: /* FSUB */
1585     case 0x68:
1586     case 0x6c:
1587     dont_care_fflags();
1588     src=get_fp_value (opcode, extra);
1589     if (src < 0) {
1590     FAIL(1); /* Illegal instruction */
1591     return;
1592     }
1593     fsub_rr(reg,src);
1594     MAKE_FPSR (reg);
1595     break;
1596     case 0x30: /* FSINCOS */
1597     case 0x31:
1598     case 0x32:
1599     case 0x33:
1600     case 0x34:
1601     case 0x35:
1602     case 0x36:
1603     case 0x37:
1604     FAIL(1);
1605     return;
1606     dont_care_fflags();
1607     break;
1608     case 0x38: /* FCMP */
1609     src=get_fp_value (opcode, extra);
1610     if (src < 0) {
1611     FAIL(1); /* Illegal instruction */
1612     return;
1613     }
1614     fmov_rr(FP_RESULT,reg);
1615     fsub_rr(FP_RESULT,src); /* Right way? */
1616     break;
1617     case 0x3a: /* FTST */
1618     src=get_fp_value (opcode, extra);
1619     if (src < 0) {
1620     FAIL(1); /* Illegal instruction */
1621     return;
1622     }
1623     fmov_rr(FP_RESULT,src);
1624     break;
1625     default:
1626     FAIL(1);
1627     return;
1628     break;
1629     }
1630     return;
1631     }
1632     m68k_setpc (m68k_getpc () - 4);
1633     fpuop_illg (opcode,extra);
1634     }