ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp
Revision: 1.9
Committed: 2005-04-24T23:00:08Z (19 years, 7 months ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-19, nigel-build-17
Changes since 1.8: +88 -85 lines
Log Message:
Fix build with gcc4 on x86-64: ignore errors when casting pointers to int
from regs & fpu members + code cache. This is possible because data is
allocated in 32-bit space and we force allocation of translation cache to
those bounds too.

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