ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpp.cpp
Revision: 1.1
Committed: 1999-10-03T14:16:26Z (24 years, 9 months ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * UAE - The Un*x Amiga Emulator
3     *
4     * MC68881 emulation
5     *
6     * Copyright 1996 Herman ten Brugge
7     */
8    
9     #include <math.h>
10     #include <stdio.h>
11    
12     #include "sysdeps.h"
13    
14     #include "memory.h"
15     #include "readcpu.h"
16     #include "newcpu.h"
17    
18     #if 1
19    
20     #define DEBUG_FPP 0
21    
22     /* single : S 8*E 23*F */
23     /* double : S 11*E 52*F */
24     /* extended : S 15*E 64*F */
25     /* E = 0 & F = 0 -> 0 */
26     /* E = MAX & F = 0 -> Infin */
27     /* E = MAX & F # 0 -> NotANumber */
28     /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
29    
30     static __inline__ double to_single (uae_u32 value)
31     {
32     double frac;
33    
34     if ((value & 0x7fffffff) == 0)
35     return (0.0);
36     frac = (double) ((value & 0x7fffff) | 0x800000) / 8388608.0;
37     if (value & 0x80000000)
38     frac = -frac;
39     return (ldexp (frac, ((value >> 23) & 0xff) - 127));
40     }
41    
42     static __inline__ uae_u32 from_single (double src)
43     {
44     int expon;
45     uae_u32 tmp;
46     double frac;
47    
48     if (src == 0.0)
49     return 0;
50     if (src < 0) {
51     tmp = 0x80000000;
52     src = -src;
53     } else {
54     tmp = 0;
55     }
56     frac = frexp (src, &expon);
57     frac += 0.5 / 16777216.0;
58     if (frac >= 1.0) {
59     frac /= 2.0;
60     expon++;
61     }
62     return (tmp | (((expon + 127 - 1) & 0xff) << 23) |
63     (((int) (frac * 16777216.0)) & 0x7fffff));
64     }
65    
66     static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
67     {
68     double frac;
69    
70     if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
71     return 0.0;
72     frac = (double) wrd2 / 2147483648.0 +
73     (double) wrd3 / 9223372036854775808.0;
74     if (wrd1 & 0x80000000)
75     frac = -frac;
76     return ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383);
77     }
78    
79     static __inline__ void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
80     {
81     int expon;
82     double frac;
83    
84     if (src == 0.0) {
85     *wrd1 = 0;
86     *wrd2 = 0;
87     *wrd3 = 0;
88     return;
89     }
90     if (src < 0) {
91     *wrd1 = 0x80000000;
92     src = -src;
93     } else {
94     *wrd1 = 0;
95     }
96     frac = frexp (src, &expon);
97     frac += 0.5 / 18446744073709551616.0;
98     if (frac >= 1.0) {
99     frac /= 2.0;
100     expon++;
101     }
102     *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
103     *wrd2 = (uae_u32) (frac * 4294967296.0);
104     *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0);
105     }
106    
107     static __inline__ double to_double(uae_u32 wrd1, uae_u32 wrd2)
108     {
109     double frac;
110    
111     if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0)
112     return 0.0;
113     frac = (double) ((wrd1 & 0xfffff) | 0x100000) / 1048576.0 +
114     (double) wrd2 / 4503599627370496.0;
115     if (wrd1 & 0x80000000)
116     frac = -frac;
117     return ldexp (frac, ((wrd1 >> 20) & 0x7ff) - 1023);
118     }
119    
120     static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2)
121     {
122     int expon;
123     int tmp;
124     double frac;
125    
126     if (src == 0.0) {
127     *wrd1 = 0;
128     *wrd2 = 0;
129     return;
130     }
131     if (src < 0) {
132     *wrd1 = 0x80000000;
133     src = -src;
134     } else {
135     *wrd1 = 0;
136     }
137     frac = frexp (src, &expon);
138     frac += 0.5 / 9007199254740992.0;
139     if (frac >= 1.0) {
140     frac /= 2.0;
141     expon++;
142     }
143     tmp = (uae_u32) (frac * 2097152.0);
144     *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff);
145     *wrd2 = (uae_u32) (frac * 9007199254740992.0 - tmp * 4294967296.0);
146     }
147    
148     static __inline__ double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
149     {
150     double d;
151     char *cp;
152     char str[100];
153    
154     cp = str;
155     if (wrd1 & 0x80000000)
156     *cp++ = '-';
157     *cp++ = (wrd1 & 0xf) + '0';
158     *cp++ = '.';
159     *cp++ = ((wrd2 >> 28) & 0xf) + '0';
160     *cp++ = ((wrd2 >> 24) & 0xf) + '0';
161     *cp++ = ((wrd2 >> 20) & 0xf) + '0';
162     *cp++ = ((wrd2 >> 16) & 0xf) + '0';
163     *cp++ = ((wrd2 >> 12) & 0xf) + '0';
164     *cp++ = ((wrd2 >> 8) & 0xf) + '0';
165     *cp++ = ((wrd2 >> 4) & 0xf) + '0';
166     *cp++ = ((wrd2 >> 0) & 0xf) + '0';
167     *cp++ = ((wrd3 >> 28) & 0xf) + '0';
168     *cp++ = ((wrd3 >> 24) & 0xf) + '0';
169     *cp++ = ((wrd3 >> 20) & 0xf) + '0';
170     *cp++ = ((wrd3 >> 16) & 0xf) + '0';
171     *cp++ = ((wrd3 >> 12) & 0xf) + '0';
172     *cp++ = ((wrd3 >> 8) & 0xf) + '0';
173     *cp++ = ((wrd3 >> 4) & 0xf) + '0';
174     *cp++ = ((wrd3 >> 0) & 0xf) + '0';
175     *cp++ = 'E';
176     if (wrd1 & 0x40000000)
177     *cp++ = '-';
178     *cp++ = ((wrd1 >> 24) & 0xf) + '0';
179     *cp++ = ((wrd1 >> 20) & 0xf) + '0';
180     *cp++ = ((wrd1 >> 16) & 0xf) + '0';
181     *cp = 0;
182     sscanf(str, "%le", &d);
183     return d;
184     }
185    
186     static __inline__ void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
187     {
188     int i;
189     int t;
190     char *cp;
191     char str[100];
192    
193     sprintf(str, "%.16e", src);
194     cp = str;
195     *wrd1 = *wrd2 = *wrd3 = 0;
196     if (*cp == '-') {
197     cp++;
198     *wrd1 = 0x80000000;
199     }
200     if (*cp == '+')
201     cp++;
202     *wrd1 |= (*cp++ - '0');
203     if (*cp == '.')
204     cp++;
205     for (i = 0; i < 8; i++) {
206     *wrd2 <<= 4;
207     if (*cp >= '0' && *cp <= '9')
208     *wrd2 |= *cp++ - '0';
209     }
210     for (i = 0; i < 8; i++) {
211     *wrd3 <<= 4;
212     if (*cp >= '0' && *cp <= '9')
213     *wrd3 |= *cp++ - '0';
214     }
215     if (*cp == 'e' || *cp == 'E') {
216     cp++;
217     if (*cp == '-') {
218     cp++;
219     *wrd1 |= 0x40000000;
220     }
221     if (*cp == '+')
222     cp++;
223     t = 0;
224     for (i = 0; i < 3; i++) {
225     if (*cp >= '0' && *cp <= '9')
226     t = (t << 4) | (*cp++ - '0');
227     }
228     *wrd1 |= t << 16;
229     }
230     }
231    
232     static __inline__ int get_fp_value (uae_u32 opcode, uae_u16 extra, double *src)
233     {
234     uaecptr tmppc;
235     uae_u16 tmp;
236     int size;
237     int mode;
238     int reg;
239     uae_u32 ad = 0;
240     static int sz1[8] =
241     {4, 4, 12, 12, 2, 8, 1, 0};
242     static int sz2[8] =
243     {4, 4, 12, 12, 2, 8, 2, 0};
244    
245     if ((extra & 0x4000) == 0) {
246     *src = regs.fp[(extra >> 10) & 7];
247     return 1;
248     }
249     mode = (opcode >> 3) & 7;
250     reg = opcode & 7;
251     size = (extra >> 10) & 7;
252     switch (mode) {
253     case 0:
254     switch (size) {
255     case 6:
256     *src = (double) (uae_s8) m68k_dreg (regs, reg);
257     break;
258     case 4:
259     *src = (double) (uae_s16) m68k_dreg (regs, reg);
260     break;
261     case 0:
262     *src = (double) (uae_s32) m68k_dreg (regs, reg);
263     break;
264     case 1:
265     *src = to_single(m68k_dreg (regs, reg));
266     break;
267     default:
268     return 0;
269     }
270     return 1;
271     case 1:
272     return 0;
273     case 2:
274     ad = m68k_areg (regs, reg);
275     break;
276     case 3:
277     ad = m68k_areg (regs, reg);
278     m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
279     break;
280     case 4:
281     m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
282     ad = m68k_areg (regs, reg);
283     break;
284     case 5:
285     ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
286     break;
287     case 6:
288     ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
289     break;
290     case 7:
291     switch (reg) {
292     case 0:
293     ad = (uae_s32) (uae_s16) next_iword();
294     break;
295     case 1:
296     ad = next_ilong();
297     break;
298     case 2:
299     ad = m68k_getpc ();
300     ad += (uae_s32) (uae_s16) next_iword();
301     break;
302     case 3:
303     tmppc = m68k_getpc ();
304     tmp = next_iword();
305     ad = get_disp_ea_020 (tmppc, tmp);
306     break;
307     case 4:
308     ad = m68k_getpc ();
309     m68k_setpc (ad + sz2[size]);
310     break;
311     default:
312     return 0;
313     }
314     }
315     switch (size) {
316     case 0:
317     *src = (double) (uae_s32) get_long (ad);
318     break;
319     case 1:
320     *src = to_single(get_long (ad));
321     break;
322     case 2:{
323     uae_u32 wrd1, wrd2, wrd3;
324     wrd1 = get_long (ad);
325     ad += 4;
326     wrd2 = get_long (ad);
327     ad += 4;
328     wrd3 = get_long (ad);
329     *src = to_exten(wrd1, wrd2, wrd3);
330     }
331     break;
332     case 3:{
333     uae_u32 wrd1, wrd2, wrd3;
334     wrd1 = get_long (ad);
335     ad += 4;
336     wrd2 = get_long (ad);
337     ad += 4;
338     wrd3 = get_long (ad);
339     *src = to_pack(wrd1, wrd2, wrd3);
340     }
341     break;
342     case 4:
343     *src = (double) (uae_s16) get_word(ad);
344     break;
345     case 5:{
346     uae_u32 wrd1, wrd2;
347     wrd1 = get_long (ad);
348     ad += 4;
349     wrd2 = get_long (ad);
350     *src = to_double(wrd1, wrd2);
351     }
352     break;
353     case 6:
354     *src = (double) (uae_s8) get_byte(ad);
355     break;
356     default:
357     return 0;
358     }
359     return 1;
360     }
361    
362     static __inline__ int put_fp_value (double value, uae_u32 opcode, uae_u16 extra)
363     {
364     uae_u16 tmp;
365     uaecptr tmppc;
366     int size;
367     int mode;
368     int reg;
369     uae_u32 ad;
370     static int sz1[8] =
371     {4, 4, 12, 12, 2, 8, 1, 0};
372     static int sz2[8] =
373     {4, 4, 12, 12, 2, 8, 2, 0};
374    
375     if ((extra & 0x4000) == 0) {
376     regs.fp[(extra >> 10) & 7] = value;
377     return 1;
378     }
379     mode = (opcode >> 3) & 7;
380     reg = opcode & 7;
381     size = (extra >> 10) & 7;
382     ad = 0xffffffff;
383     switch (mode) {
384     case 0:
385     switch (size) {
386     case 6:
387     m68k_dreg (regs, reg) = (((int) value & 0xff)
388     | (m68k_dreg (regs, reg) & ~0xff));
389     break;
390     case 4:
391     m68k_dreg (regs, reg) = (((int) value & 0xffff)
392     | (m68k_dreg (regs, reg) & ~0xffff));
393     break;
394     case 0:
395     m68k_dreg (regs, reg) = (int) value;
396     break;
397     case 1:
398     m68k_dreg (regs, reg) = from_single(value);
399     break;
400     default:
401     return 0;
402     }
403     return 1;
404     case 1:
405     return 0;
406     case 2:
407     ad = m68k_areg (regs, reg);
408     break;
409     case 3:
410     ad = m68k_areg (regs, reg);
411     m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
412     break;
413     case 4:
414     m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
415     ad = m68k_areg (regs, reg);
416     break;
417     case 5:
418     ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
419     break;
420     case 6:
421     ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
422     break;
423     case 7:
424     switch (reg) {
425     case 0:
426     ad = (uae_s32) (uae_s16) next_iword();
427     break;
428     case 1:
429     ad = next_ilong();
430     break;
431     case 2:
432     ad = m68k_getpc ();
433     ad += (uae_s32) (uae_s16) next_iword();
434     break;
435     case 3:
436     tmppc = m68k_getpc ();
437     tmp = next_iword();
438     ad = get_disp_ea_020 (tmppc, tmp);
439     break;
440     case 4:
441     ad = m68k_getpc ();
442     m68k_setpc (ad + sz2[size]);
443     break;
444     default:
445     return 0;
446     }
447     }
448     switch (size) {
449     case 0:
450     put_long (ad, (uae_s32) value);
451     break;
452     case 1:
453     put_long (ad, from_single(value));
454     break;
455     case 2:
456     {
457     uae_u32 wrd1, wrd2, wrd3;
458     from_exten(value, &wrd1, &wrd2, &wrd3);
459     put_long (ad, wrd1);
460     ad += 4;
461     put_long (ad, wrd2);
462     ad += 4;
463     put_long (ad, wrd3);
464     }
465     break;
466     case 3:
467     {
468     uae_u32 wrd1, wrd2, wrd3;
469     from_pack(value, &wrd1, &wrd2, &wrd3);
470     put_long (ad, wrd1);
471     ad += 4;
472     put_long (ad, wrd2);
473     ad += 4;
474     put_long (ad, wrd3);
475     }
476     break;
477     case 4:
478     put_word(ad, (uae_s16) value);
479     break;
480     case 5:{
481     uae_u32 wrd1, wrd2;
482     from_double(value, &wrd1, &wrd2);
483     put_long (ad, wrd1);
484     ad += 4;
485     put_long (ad, wrd2);
486     }
487     break;
488     case 6:
489     put_byte(ad, (uae_s8) value);
490     break;
491     default:
492     return 0;
493     }
494     return 1;
495     }
496    
497     static __inline__ int get_fp_ad(uae_u32 opcode, uae_u32 * ad)
498     {
499     uae_u16 tmp;
500     uaecptr tmppc;
501     int mode;
502     int reg;
503    
504     mode = (opcode >> 3) & 7;
505     reg = opcode & 7;
506     switch (mode) {
507     case 0:
508     case 1:
509     return 0;
510     case 2:
511     *ad = m68k_areg (regs, reg);
512     break;
513     case 3:
514     *ad = m68k_areg (regs, reg);
515     break;
516     case 4:
517     *ad = m68k_areg (regs, reg);
518     break;
519     case 5:
520     *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
521     break;
522     case 6:
523     *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
524     break;
525     case 7:
526     switch (reg) {
527     case 0:
528     *ad = (uae_s32) (uae_s16) next_iword();
529     break;
530     case 1:
531     *ad = next_ilong();
532     break;
533     case 2:
534     *ad = m68k_getpc ();
535     *ad += (uae_s32) (uae_s16) next_iword();
536     break;
537     case 3:
538     tmppc = m68k_getpc ();
539     tmp = next_iword();
540     *ad = get_disp_ea_020 (tmppc, tmp);
541     break;
542     default:
543     return 0;
544     }
545     }
546     return 1;
547     }
548    
549     static __inline__ int fpp_cond(uae_u32 opcode, int contition)
550     {
551     int N = (regs.fpsr & 0x8000000) != 0;
552     int Z = (regs.fpsr & 0x4000000) != 0;
553     /* int I = (regs.fpsr & 0x2000000) != 0; */
554     int NotANumber = (regs.fpsr & 0x1000000) != 0;
555    
556     switch (contition) {
557     case 0x00:
558     return 0;
559     case 0x01:
560     return Z;
561     case 0x02:
562     return !(NotANumber || Z || N);
563     case 0x03:
564     return Z || !(NotANumber || N);
565     case 0x04:
566     return N && !(NotANumber || Z);
567     case 0x05:
568     return Z || (N && !NotANumber);
569     case 0x06:
570     return !(NotANumber || Z);
571     case 0x07:
572     return !NotANumber;
573     case 0x08:
574     return NotANumber;
575     case 0x09:
576     return NotANumber || Z;
577     case 0x0a:
578     return NotANumber || !(N || Z);
579     case 0x0b:
580     return NotANumber || Z || !N;
581     case 0x0c:
582     return NotANumber || (N && !Z);
583     case 0x0d:
584     return NotANumber || Z || N;
585     case 0x0e:
586     return !Z;
587     case 0x0f:
588     return 1;
589     case 0x10:
590     return 0;
591     case 0x11:
592     return Z;
593     case 0x12:
594     return !(NotANumber || Z || N);
595     case 0x13:
596     return Z || !(NotANumber || N);
597     case 0x14:
598     return N && !(NotANumber || Z);
599     case 0x15:
600     return Z || (N && !NotANumber);
601     case 0x16:
602     return !(NotANumber || Z);
603     case 0x17:
604     return !NotANumber;
605     case 0x18:
606     return NotANumber;
607     case 0x19:
608     return NotANumber || Z;
609     case 0x1a:
610     return NotANumber || !(N || Z);
611     case 0x1b:
612     return NotANumber || Z || !N;
613     case 0x1c:
614     return NotANumber || (Z && N);
615     case 0x1d:
616     return NotANumber || Z || N;
617     case 0x1e:
618     return !Z;
619     case 0x1f:
620     return 1;
621     }
622     return -1;
623     }
624    
625     void fdbcc_opp(uae_u32 opcode, uae_u16 extra)
626     {
627     uaecptr pc = (uae_u32) m68k_getpc ();
628     uae_s32 disp = (uae_s32) (uae_s16) next_iword();
629     int cc;
630    
631     #if DEBUG_FPP
632     printf("fdbcc_opp at %08lx\n", m68k_getpc ());
633     fflush(stdout);
634     #endif
635     cc = fpp_cond(opcode, extra & 0x3f);
636     if (cc == -1) {
637     m68k_setpc (pc - 4);
638     op_illg (opcode);
639     } else if (!cc) {
640     int reg = opcode & 0x7;
641    
642     m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff)
643     | ((m68k_dreg (regs, reg) - 1) & 0xffff));
644     if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff)
645     m68k_setpc (pc + disp);
646     }
647     }
648    
649     void fscc_opp(uae_u32 opcode, uae_u16 extra)
650     {
651     uae_u32 ad;
652     int cc;
653    
654     #if DEBUG_FPP
655     printf("fscc_opp at %08lx\n", m68k_getpc ());
656     fflush(stdout);
657     #endif
658     cc = fpp_cond(opcode, extra & 0x3f);
659     if (cc == -1) {
660     m68k_setpc (m68k_getpc () - 4);
661     op_illg (opcode);
662     } else if ((opcode & 0x38) == 0) {
663     m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) |
664     (cc ? 0xff : 0x00);
665     } else {
666     if (get_fp_ad(opcode, &ad) == 0) {
667     m68k_setpc (m68k_getpc () - 4);
668     op_illg (opcode);
669     } else
670     put_byte(ad, cc ? 0xff : 0x00);
671     }
672     }
673    
674     void ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
675     {
676     int cc;
677    
678     #if DEBUG_FPP
679     printf("ftrapcc_opp at %08lx\n", m68k_getpc ());
680     fflush(stdout);
681     #endif
682     cc = fpp_cond(opcode, opcode & 0x3f);
683     if (cc == -1) {
684     m68k_setpc (oldpc);
685     op_illg (opcode);
686     }
687     if (cc)
688     Exception(7, oldpc - 2);
689     }
690    
691     void fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
692     {
693     int cc;
694    
695     #if DEBUG_FPP
696     printf("fbcc_opp at %08lx\n", m68k_getpc ());
697     fflush(stdout);
698     #endif
699     cc = fpp_cond(opcode, opcode & 0x3f);
700     if (cc == -1) {
701     m68k_setpc (pc);
702     op_illg (opcode);
703     } else if (cc) {
704     if ((opcode & 0x40) == 0)
705     extra = (uae_s32) (uae_s16) extra;
706     m68k_setpc (pc + extra);
707     }
708     }
709    
710     void fsave_opp(uae_u32 opcode)
711     {
712     uae_u32 ad;
713     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
714     int i;
715    
716     #if DEBUG_FPP
717     printf("fsave_opp at %08lx\n", m68k_getpc ());
718     fflush(stdout);
719     #endif
720     if (get_fp_ad(opcode, &ad) == 0) {
721     m68k_setpc (m68k_getpc () - 2);
722     op_illg (opcode);
723     return;
724     }
725     if (incr < 0) {
726     ad -= 4;
727     put_long (ad, 0x70000000);
728     for (i = 0; i < 5; i++) {
729     ad -= 4;
730     put_long (ad, 0x00000000);
731     }
732     ad -= 4;
733     put_long (ad, 0x1f180000);
734     } else {
735     put_long (ad, 0x1f180000);
736     ad += 4;
737     for (i = 0; i < 5; i++) {
738     put_long (ad, 0x00000000);
739     ad += 4;
740     }
741     put_long (ad, 0x70000000);
742     ad += 4;
743     }
744     if ((opcode & 0x38) == 0x18)
745     m68k_areg (regs, opcode & 7) = ad;
746     if ((opcode & 0x38) == 0x20)
747     m68k_areg (regs, opcode & 7) = ad;
748     }
749    
750     void frestore_opp(uae_u32 opcode)
751     {
752     uae_u32 ad;
753     uae_u32 d;
754     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
755    
756     #if DEBUG_FPP
757     printf("frestore_opp at %08lx\n", m68k_getpc ());
758     fflush(stdout);
759     #endif
760     if (get_fp_ad(opcode, &ad) == 0) {
761     m68k_setpc (m68k_getpc () - 2);
762     op_illg (opcode);
763     return;
764     }
765     if (incr < 0) {
766     ad -= 4;
767     d = get_long (ad);
768     if ((d & 0xff000000) != 0) {
769     if ((d & 0x00ff0000) == 0x00180000)
770     ad -= 6 * 4;
771     else if ((d & 0x00ff0000) == 0x00380000)
772     ad -= 14 * 4;
773     else if ((d & 0x00ff0000) == 0x00b40000)
774     ad -= 45 * 4;
775     }
776     } else {
777     d = get_long (ad);
778     ad += 4;
779     if ((d & 0xff000000) != 0) {
780     if ((d & 0x00ff0000) == 0x00180000)
781     ad += 6 * 4;
782     else if ((d & 0x00ff0000) == 0x00380000)
783     ad += 14 * 4;
784     else if ((d & 0x00ff0000) == 0x00b40000)
785     ad += 45 * 4;
786     }
787     }
788     if ((opcode & 0x38) == 0x18)
789     m68k_areg (regs, opcode & 7) = ad;
790     if ((opcode & 0x38) == 0x20)
791     m68k_areg (regs, opcode & 7) = ad;
792     }
793    
794     void fpp_opp(uae_u32 opcode, uae_u16 extra)
795     {
796     int reg;
797     double src;
798    
799     #if DEBUG_FPP
800     printf("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff,
801     m68k_getpc () - 4);
802     fflush(stdout);
803     #endif
804     switch ((extra >> 13) & 0x7) {
805     case 3:
806     if (put_fp_value (regs.fp[(extra >> 7) & 7], opcode, extra) == 0) {
807     m68k_setpc (m68k_getpc () - 4);
808     op_illg (opcode);
809     }
810     return;
811     case 4:
812     case 5:
813     if ((opcode & 0x38) == 0) {
814     if (extra & 0x2000) {
815     if (extra & 0x1000)
816     m68k_dreg (regs, opcode & 7) = regs.fpcr;
817     if (extra & 0x0800)
818     m68k_dreg (regs, opcode & 7) = regs.fpsr;
819     if (extra & 0x0400)
820     m68k_dreg (regs, opcode & 7) = regs.fpiar;
821     } else {
822     if (extra & 0x1000)
823     regs.fpcr = m68k_dreg (regs, opcode & 7);
824     if (extra & 0x0800)
825     regs.fpsr = m68k_dreg (regs, opcode & 7);
826     if (extra & 0x0400)
827     regs.fpiar = m68k_dreg (regs, opcode & 7);
828     }
829     } else if ((opcode & 0x38) == 1) {
830     if (extra & 0x2000) {
831     if (extra & 0x1000)
832     m68k_areg (regs, opcode & 7) = regs.fpcr;
833     if (extra & 0x0800)
834     m68k_areg (regs, opcode & 7) = regs.fpsr;
835     if (extra & 0x0400)
836     m68k_areg (regs, opcode & 7) = regs.fpiar;
837     } else {
838     if (extra & 0x1000)
839     regs.fpcr = m68k_areg (regs, opcode & 7);
840     if (extra & 0x0800)
841     regs.fpsr = m68k_areg (regs, opcode & 7);
842     if (extra & 0x0400)
843     regs.fpiar = m68k_areg (regs, opcode & 7);
844     }
845     } else if ((opcode & 0x3f) == 0x3c) {
846     if ((extra & 0x2000) == 0) {
847     if (extra & 0x1000)
848     regs.fpcr = next_ilong();
849     if (extra & 0x0800)
850     regs.fpsr = next_ilong();
851     if (extra & 0x0400)
852     regs.fpiar = next_ilong();
853     }
854     } else if (extra & 0x2000) {
855     /* FMOVEM FPP->memory */
856     uae_u32 ad;
857     int incr = 0;
858    
859     if (get_fp_ad(opcode, &ad) == 0) {
860     m68k_setpc (m68k_getpc () - 4);
861     op_illg (opcode);
862     return;
863     }
864     if ((opcode & 0x38) == 0x20) {
865     if (extra & 0x1000)
866     incr += 4;
867     if (extra & 0x0800)
868     incr += 4;
869     if (extra & 0x0400)
870     incr += 4;
871     }
872     ad -= incr;
873     if (extra & 0x1000) {
874     put_long (ad, regs.fpcr);
875     ad += 4;
876     }
877     if (extra & 0x0800) {
878     put_long (ad, regs.fpsr);
879     ad += 4;
880     }
881     if (extra & 0x0400) {
882     put_long (ad, regs.fpiar);
883     ad += 4;
884     }
885     ad -= incr;
886     if ((opcode & 0x38) == 0x18)
887     m68k_areg (regs, opcode & 7) = ad;
888     if ((opcode & 0x38) == 0x20)
889     m68k_areg (regs, opcode & 7) = ad;
890     } else {
891     /* FMOVEM memory->FPP */
892     uae_u32 ad;
893    
894     if (get_fp_ad(opcode, &ad) == 0) {
895     m68k_setpc (m68k_getpc () - 4);
896     op_illg (opcode);
897     return;
898     }
899     ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad;
900     if (extra & 0x1000) {
901     regs.fpcr = get_long (ad);
902     ad += 4;
903     }
904     if (extra & 0x0800) {
905     regs.fpsr = get_long (ad);
906     ad += 4;
907     }
908     if (extra & 0x0400) {
909     regs.fpiar = get_long (ad);
910     ad += 4;
911     }
912     if ((opcode & 0x38) == 0x18)
913     m68k_areg (regs, opcode & 7) = ad;
914     if ((opcode & 0x38) == 0x20)
915     m68k_areg (regs, opcode & 7) = ad - 12;
916     }
917     return;
918     case 6:
919     case 7:
920     {
921     uae_u32 ad, list = 0;
922     int incr = 0;
923     if (extra & 0x2000) {
924     /* FMOVEM FPP->memory */
925     if (get_fp_ad(opcode, &ad) == 0) {
926     m68k_setpc (m68k_getpc () - 4);
927     op_illg (opcode);
928     return;
929     }
930     switch ((extra >> 11) & 3) {
931     case 0: /* static pred */
932     list = extra & 0xff;
933     incr = -1;
934     break;
935     case 1: /* dynamic pred */
936     list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
937     incr = -1;
938     break;
939     case 2: /* static postinc */
940     list = extra & 0xff;
941     incr = 1;
942     break;
943     case 3: /* dynamic postinc */
944     list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
945     incr = 1;
946     break;
947     }
948     while (list) {
949     uae_u32 wrd1, wrd2, wrd3;
950     if (incr < 0) {
951     from_exten(regs.fp[fpp_movem_index2[list]],
952     &wrd1, &wrd2, &wrd3);
953     ad -= 4;
954     put_long (ad, wrd3);
955     ad -= 4;
956     put_long (ad, wrd2);
957     ad -= 4;
958     put_long (ad, wrd1);
959     } else {
960     from_exten(regs.fp[fpp_movem_index1[list]],
961     &wrd1, &wrd2, &wrd3);
962     put_long (ad, wrd1);
963     ad += 4;
964     put_long (ad, wrd2);
965     ad += 4;
966     put_long (ad, wrd3);
967     ad += 4;
968     }
969     list = fpp_movem_next[list];
970     }
971     if ((opcode & 0x38) == 0x18)
972     m68k_areg (regs, opcode & 7) = ad;
973     if ((opcode & 0x38) == 0x20)
974     m68k_areg (regs, opcode & 7) = ad;
975     } else {
976     /* FMOVEM memory->FPP */
977     if (get_fp_ad(opcode, &ad) == 0) {
978     m68k_setpc (m68k_getpc () - 4);
979     op_illg (opcode);
980     return;
981     }
982     switch ((extra >> 11) & 3) {
983     case 0: /* static pred */
984     list = extra & 0xff;
985     incr = -1;
986     break;
987     case 1: /* dynamic pred */
988     list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
989     incr = -1;
990     break;
991     case 2: /* static postinc */
992     list = extra & 0xff;
993     incr = 1;
994     break;
995     case 3: /* dynamic postinc */
996     list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
997     incr = 1;
998     break;
999     }
1000     while (list) {
1001     uae_u32 wrd1, wrd2, wrd3;
1002     if (incr < 0) {
1003     ad -= 4;
1004     wrd3 = get_long (ad);
1005     ad -= 4;
1006     wrd2 = get_long (ad);
1007     ad -= 4;
1008     wrd1 = get_long (ad);
1009     regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3);
1010     } else {
1011     wrd1 = get_long (ad);
1012     ad += 4;
1013     wrd2 = get_long (ad);
1014     ad += 4;
1015     wrd3 = get_long (ad);
1016     ad += 4;
1017     regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3);
1018     }
1019     list = fpp_movem_next[list];
1020     }
1021     if ((opcode & 0x38) == 0x18)
1022     m68k_areg (regs, opcode & 7) = ad;
1023     if ((opcode & 0x38) == 0x20)
1024     m68k_areg (regs, opcode & 7) = ad;
1025     }
1026     }
1027     return;
1028     case 0:
1029     case 2:
1030     reg = (extra >> 7) & 7;
1031     if ((extra & 0xfc00) == 0x5c00) {
1032     switch (extra & 0x7f) {
1033     case 0x00:
1034     regs.fp[reg] = 4.0 * atan(1.0);
1035     break;
1036     case 0x0b:
1037     regs.fp[reg] = log10 (2.0);
1038     break;
1039     case 0x0c:
1040     regs.fp[reg] = exp (1.0);
1041     break;
1042     case 0x0d:
1043     regs.fp[reg] = log (exp (1.0)) / log (2.0);
1044     break;
1045     case 0x0e:
1046     regs.fp[reg] = log (exp (1.0)) / log (10.0);
1047     break;
1048     case 0x0f:
1049     regs.fp[reg] = 0.0;
1050     break;
1051     case 0x30:
1052     regs.fp[reg] = log (2.0);
1053     break;
1054     case 0x31:
1055     regs.fp[reg] = log (10.0);
1056     break;
1057     case 0x32:
1058     regs.fp[reg] = 1.0e0;
1059     break;
1060     case 0x33:
1061     regs.fp[reg] = 1.0e1;
1062     break;
1063     case 0x34:
1064     regs.fp[reg] = 1.0e2;
1065     break;
1066     case 0x35:
1067     regs.fp[reg] = 1.0e4;
1068     break;
1069     case 0x36:
1070     regs.fp[reg] = 1.0e8;
1071     break;
1072     case 0x37:
1073     regs.fp[reg] = 1.0e16;
1074     break;
1075     case 0x38:
1076     regs.fp[reg] = 1.0e32;
1077     break;
1078     case 0x39:
1079     regs.fp[reg] = 1.0e64;
1080     break;
1081     case 0x3a:
1082     regs.fp[reg] = 1.0e128;
1083     break;
1084     case 0x3b:
1085     regs.fp[reg] = 1.0e256;
1086     break;
1087     #if 0
1088     case 0x3c:
1089     regs.fp[reg] = 1.0e512;
1090     break;
1091     case 0x3d:
1092     regs.fp[reg] = 1.0e1024;
1093     break;
1094     case 0x3e:
1095     regs.fp[reg] = 1.0e2048;
1096     break;
1097     case 0x3f:
1098     regs.fp[reg] = 1.0e4096;
1099     break;
1100     #endif
1101     default:
1102     m68k_setpc (m68k_getpc () - 4);
1103     op_illg (opcode);
1104     break;
1105     }
1106     return;
1107     }
1108     if (get_fp_value (opcode, extra, &src) == 0) {
1109     m68k_setpc (m68k_getpc () - 4);
1110     op_illg (opcode);
1111     return;
1112     }
1113     switch (extra & 0x7f) {
1114     case 0x00: /* FMOVE */
1115     regs.fp[reg] = src;
1116     break;
1117     case 0x01: /* FINT */
1118     regs.fp[reg] = (int) (src + 0.5);
1119     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1120     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1121     break;
1122     case 0x02: /* FSINH */
1123     regs.fp[reg] = sinh (src);
1124     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1125     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1126     break;
1127     case 0x03: /* FINTRZ */
1128     regs.fp[reg] = (int) src;
1129     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1130     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1131     break;
1132     case 0x04: /* FSQRT */
1133     regs.fp[reg] = sqrt (src);
1134     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1135     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1136     break;
1137     case 0x06: /* FLOGNP1 */
1138     regs.fp[reg] = log (src + 1.0);
1139     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1140     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1141     break;
1142     case 0x08: /* FETOXM1 */
1143     regs.fp[reg] = exp (src) - 1.0;
1144     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1145     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1146     break;
1147     case 0x09: /* FTANH */
1148     regs.fp[reg] = tanh (src);
1149     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1150     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1151     break;
1152     case 0x0a: /* FATAN */
1153     regs.fp[reg] = atan (src);
1154     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1155     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1156     break;
1157     case 0x0c: /* FASIN */
1158     regs.fp[reg] = asin (src);
1159     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1160     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1161     break;
1162     case 0x0d: /* FATANH */
1163     #if 1 /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */
1164     regs.fp[reg] = log ((1 + src) / (1 - src)) / 2;
1165     #else
1166     regs.fp[reg] = atanh (src);
1167     #endif
1168     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1169     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1170     break;
1171     case 0x0e: /* FSIN */
1172     regs.fp[reg] = sin (src);
1173     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1174     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1175     break;
1176     case 0x0f: /* FTAN */
1177     regs.fp[reg] = tan (src);
1178     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1179     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1180     break;
1181     case 0x10: /* FETOX */
1182     regs.fp[reg] = exp (src);
1183     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1184     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1185     break;
1186     case 0x11: /* FTWOTOX */
1187     regs.fp[reg] = pow(2.0, src);
1188     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1189     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1190     break;
1191     case 0x12: /* FTENTOX */
1192     regs.fp[reg] = pow(10.0, src);
1193     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1194     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1195     break;
1196     case 0x14: /* FLOGN */
1197     regs.fp[reg] = log (src);
1198     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1199     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1200     break;
1201     case 0x15: /* FLOG10 */
1202     regs.fp[reg] = log10 (src);
1203     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1204     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1205     break;
1206     case 0x16: /* FLOG2 */
1207     regs.fp[reg] = log (src) / log (2.0);
1208     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1209     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1210     break;
1211     case 0x18: /* FABS */
1212     regs.fp[reg] = src < 0 ? -src : src;
1213     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1214     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1215     break;
1216     case 0x19: /* FCOSH */
1217     regs.fp[reg] = cosh(src);
1218     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1219     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1220     break;
1221     case 0x1a: /* FNEG */
1222     regs.fp[reg] = -src;
1223     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1224     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1225     break;
1226     case 0x1c: /* FACOS */
1227     regs.fp[reg] = acos(src);
1228     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1229     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1230     break;
1231     case 0x1d: /* FCOS */
1232     regs.fp[reg] = cos(src);
1233     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1234     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1235     break;
1236     case 0x1e: /* FGETEXP */
1237     {
1238     int expon;
1239     frexp (src, &expon);
1240     regs.fp[reg] = (double) (expon - 1);
1241     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1242     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1243     }
1244     break;
1245     case 0x1f: /* FGETMAN */
1246     {
1247     int expon;
1248     regs.fp[reg] = frexp (src, &expon) * 2.0;
1249     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1250     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1251     }
1252     break;
1253     case 0x20: /* FDIV */
1254     regs.fp[reg] /= src;
1255     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1256     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1257     break;
1258     case 0x21: /* FMOD */
1259     regs.fp[reg] = regs.fp[reg] -
1260     (double) ((int) (regs.fp[reg] / src)) * src;
1261     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1262     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1263     break;
1264     case 0x22: /* FADD */
1265     regs.fp[reg] += src;
1266     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1267     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1268     break;
1269     case 0x23: /* FMUL */
1270     regs.fp[reg] *= src;
1271     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1272     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1273     break;
1274     case 0x24: /* FSGLDIV */
1275     regs.fp[reg] /= src;
1276     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1277     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1278     break;
1279     case 0x25: /* FREM */
1280     regs.fp[reg] = regs.fp[reg] -
1281     (double) ((int) (regs.fp[reg] / src + 0.5)) * src;
1282     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1283     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1284     break;
1285     case 0x26: /* FSCALE */
1286     regs.fp[reg] *= exp (log (2.0) * src);
1287     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1288     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1289     break;
1290     case 0x27: /* FSGLMUL */
1291     regs.fp[reg] *= src;
1292     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1293     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1294     break;
1295     case 0x28: /* FSUB */
1296     regs.fp[reg] -= src;
1297     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1298     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1299     break;
1300     case 0x30: /* FSINCOS */
1301     case 0x31:
1302     case 0x32:
1303     case 0x33:
1304     case 0x34:
1305     case 0x35:
1306     case 0x36:
1307     case 0x37:
1308     regs.fp[reg] = sin (src);
1309     regs.fp[extra & 7] = cos(src);
1310     regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1311     (regs.fp[reg] < 0 ? 0x8000000 : 0);
1312     break;
1313     case 0x38: /* FCMP */
1314     {
1315     double tmp = regs.fp[reg] - src;
1316     regs.fpsr = (tmp == 0 ? 0x4000000 : 0) |
1317     (tmp < 0 ? 0x8000000 : 0);
1318     }
1319     break;
1320     case 0x3a: /* FTST */
1321     regs.fpsr = (src == 0 ? 0x4000000 : 0) |
1322     (src < 0 ? 0x8000000 : 0);
1323     break;
1324     default:
1325     m68k_setpc (m68k_getpc () - 4);
1326     op_illg (opcode);
1327     break;
1328     }
1329     return;
1330     }
1331     m68k_setpc (m68k_getpc () - 4);
1332     op_illg (opcode);
1333     }
1334    
1335     #endif