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

File Contents

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