Annotation of hatari/src/cpu/jit/compemu_fpp.c, revision 1.1.1.2

1.1       root        1: /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * MC68881 emulation
                      5:   *
                      6:   * Copyright 1996 Herman ten Brugge
                      7:   * Adapted for JIT compilation (c) Bernd Meyer, 2000
                      8:   * Modified 2005 Peter Keunecke
1.1.1.2 ! root        9:   */
1.1       root       10: 
                     11: #include "sysconfig.h"
                     12: #include "sysdeps.h"
                     13: 
                     14: #include "options.h"
                     15: #include "memory.h"
                     16: #include "custom.h"
                     17: #include "newcpu.h"
                     18: #include "ersatz.h"
                     19: #include "md-fpp.h"
                     20: #include "compemu.h"
                     21: 
                     22: #if defined(JIT)
1.1.1.2 ! root       23: uae_u32 temp_fp[] = { 0, 0, 0 };  /* To convert between FP and <EA> */
1.1       root       24: 
                     25: /* 128 words, indexed through the low byte of the 68k fpu control word */
1.1.1.2 ! root       26: static const uae_u16 x86_fpucw[] = {
        !            27:        0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, /* E-RN */
        !            28:        0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, /* E-RZ */
        !            29:        0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, /* E-RD */
        !            30:        0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, /* E-RU */
        !            31: 
        !            32:        0x107f, 0x107f, 0x107f, 0x107f, 0x107f, 0x107f, 0x107f, 0x107f, /* S-RN */
        !            33:        0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, 0x1c7f, /* S-RZ */
        !            34:        0x147f, 0x147f, 0x147f, 0x147f, 0x147f, 0x147f, 0x147f, 0x147f, /* S-RD */
        !            35:        0x187f, 0x187f, 0x187f, 0x187f, 0x187f, 0x187f, 0x187f, 0x187f, /* S-RU */
        !            36: 
        !            37:        0x127f, 0x127f, 0x127f, 0x127f, 0x127f, 0x127f, 0x127f, 0x127f, /* D-RN */
        !            38:        0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, 0x1e7f, /* D-RZ */
        !            39:        0x167f, 0x167f, 0x167f, 0x167f, 0x167f, 0x167f, 0x167f, 0x167f, /* D-RD */
        !            40:        0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, 0x1a7f, /* D-RU */
        !            41: 
        !            42:        0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, 0x137f, /* ?-RN */
        !            43:        0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, 0x1f7f, /* ?-RZ */
        !            44:        0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, 0x177f, /* ?-RD */
        !            45:        0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f, 0x1b7f  /* ?-RU */
1.1       root       46: };
                     47: static const int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
                     48: static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
                     49: 
                     50: static struct {
                     51:        double b[2];
                     52:        double w[2];
                     53:        double l[2];
                     54: } clamp_bounds = {
                     55:        { -128.0, 127.0 },
                     56:        { -32768.0, 32767.0 },
                     57:        { -2147483648.0, 2147483647.0 }
                     58: };
                     59: 
                     60: /* return the required floating point precision or -1 for failure, 0=E, 1=S, 2=D */
                     61: STATIC_INLINE int comp_fp_get (uae_u32 opcode, uae_u16 extra, int treg)
                     62: {
1.1.1.2 ! root       63:        int reg = opcode & 7;
        !            64:        int mode = (opcode >> 3) & 7;
        !            65:        int size = (extra >> 10) & 7;
        !            66: 
        !            67:        if (size == 3 || size == 7) /* 3 = packed decimal, 7 is not defined */
        !            68:                return -1;
        !            69:        switch (mode) {
        !            70:                case 0: /* Dn */
        !            71:                switch (size) {
        !            72:                        case 0: /* Long */
        !            73:                        mov_l_mr ((uae_u32) temp_fp, reg);
        !            74:                        fmovi_rm (treg, (uae_u32) temp_fp);
        !            75:                        return 2;
        !            76:                        case 1: /* Single */
        !            77:                        mov_l_mr ((uae_u32) temp_fp, reg);
        !            78:                        fmovs_rm (treg, (uae_u32) temp_fp);
1.1       root       79:                        return 1;
1.1.1.2 ! root       80:                        case 4: /* Word */
        !            81:                        sign_extend_16_rr (S1, reg);
        !            82:                        mov_l_mr ((uae_u32) temp_fp, S1);
        !            83:                        fmovi_rm (treg, (uae_u32) temp_fp);
1.1       root       84:                        return 1;
1.1.1.2 ! root       85:                        case 6: /* Byte */
        !            86:                        sign_extend_8_rr (S1, reg);
        !            87:                        mov_l_mr ((uae_u32) temp_fp, S1);
        !            88:                        fmovi_rm (treg, (uae_u32) temp_fp);
        !            89:                        return 1;
        !            90:                        default:
        !            91:                        return -1;
        !            92:                }
        !            93:                case 1: /* An,  invalid mode */
        !            94:                return -1;
        !            95:                case 2: /* (An) */
        !            96:                mov_l_rr (S1, reg + 8);
        !            97:                break;
        !            98:                case 3: /* (An)+ */
        !            99:                mov_l_rr (S1, reg + 8);
        !           100:                lea_l_brr (reg + 8, reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
        !           101:                break;
        !           102:                case 4: /* -(An) */
        !           103:                lea_l_brr (reg + 8, reg + 8, -(reg == 7 ? sz2[size] : sz1[size]));
        !           104:                mov_l_rr (S1, reg + 8);
        !           105:                break;
        !           106:                case 5: /* (d16,An)  */
        !           107:                {
        !           108:                        uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           109:                        mov_l_rr (S1, reg + 8);
        !           110:                        lea_l_brr (S1, S1, off);
        !           111:                        break;
        !           112:                }
        !           113:                case 6: /* (d8,An,Xn) or (bd,An,Xn) or ([bd,An,Xn],od) or ([bd,An],Xn,od) */
        !           114:                {
        !           115:                        uae_u32 dp = comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           116:                        calc_disp_ea_020 (reg + 8, dp, S1, S2);
        !           117:                        break;
        !           118:                }
        !           119:                case 7:
        !           120:                switch (reg) {
        !           121:                        case 0: /* (xxx).W */
        !           122:                        {
        !           123:                                uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           124:                                mov_l_ri (S1, off);
        !           125:                                break;
        !           126:                        }
        !           127:                        case 1: /* (xxx).L */
        !           128:                        {
        !           129:                                uae_u32 off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
        !           130:                                mov_l_ri (S1, off);
        !           131:                                break;
        !           132:                        }
        !           133:                        case 2: /* (d16,PC) */
        !           134:                        {
        !           135:                                uae_u32 address = start_pc + ((uae_char*) comp_pc_p - (uae_char*) start_pc_p) +
        !           136:                                        m68k_pc_offset;
        !           137:                                uae_s32 PC16off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           138:                                mov_l_ri (S1, address + PC16off);
        !           139:                                break;
        !           140:                        }
        !           141:                        case 3: /* (d8,PC,Xn) or (bd,PC,Xn) or ([bd,PC,Xn],od) or ([bd,PC],Xn,od) */
        !           142:                        return -1; /* rarely used, fallback to non-JIT */
        !           143:                        case 4: /* # < data >; Constants should be converted just once by the JIT */
        !           144:                        m68k_pc_offset += sz2[size];
        !           145:                        switch (size) {
        !           146:                                case 0:
        !           147:                                {
        !           148:                                        uae_s32 li = comp_get_ilong(m68k_pc_offset - 4);
        !           149:                                        float si = (float)li;
        !           150: 
        !           151:                                        if (li == (int)si) {
        !           152:                                                //write_log ("converted immediate LONG constant to SINGLE\n");
        !           153:                                                mov_l_mi((uae_u32)temp_fp, *(uae_u32 *)&si);
        !           154:                                                fmovs_rm(treg, (uae_u32)temp_fp);
        !           155:                                                return 1;
        !           156:                                        }
        !           157:                                        //write_log ("immediate LONG constant\n");
        !           158:                                        mov_l_mi((uae_u32)temp_fp, *(uae_u32 *)&li);
        !           159:                                        fmovi_rm(treg, (uae_u32)temp_fp);
        !           160:                                        return 2;
        !           161:                                }
        !           162:                                case 1:
        !           163:                                //write_log (_T("immediate SINGLE constant\n"));
        !           164:                                mov_l_mi((uae_u32)temp_fp, comp_get_ilong(m68k_pc_offset - 4));
        !           165:                                fmovs_rm(treg, (uae_u32)temp_fp);
        !           166:                                return 1;
        !           167:                                case 2:
        !           168:                                //write_log (_T("immediate LONG DOUBLE constant\n"));
        !           169:                                mov_l_mi((uae_u32)temp_fp, comp_get_ilong(m68k_pc_offset - 4));
        !           170:                                mov_l_mi(((uae_u32)temp_fp) + 4, comp_get_ilong(m68k_pc_offset - 8));
        !           171:                                mov_l_mi(((uae_u32)temp_fp) + 8, (uae_u32)comp_get_iword(m68k_pc_offset - 12));
        !           172:                                fmov_ext_rm(treg, (uae_u32)temp_fp);
        !           173:                                return 0;
        !           174:                                case 4:
        !           175:                                {
        !           176:                                        float si = (float)(uae_s16)comp_get_iword(m68k_pc_offset-2);
        !           177: 
        !           178:                                        //write_log (_T("converted immediate WORD constant %f to SINGLE\n"), si);
        !           179:                                        mov_l_mi((uae_u32)temp_fp,*(uae_u32 *)&si);
        !           180:                                        fmovs_rm(treg,(uae_u32)temp_fp);
        !           181:                                        return 1;
        !           182:                                }
        !           183:                                case 5:
        !           184:                                {
        !           185:                                        uae_u32 longarray[] = { comp_get_ilong(m68k_pc_offset - 4),
        !           186:                                                comp_get_ilong(m68k_pc_offset - 8) };
        !           187:                                        float si = (float)*(double *)longarray;
        !           188: 
        !           189:                                        if (*(double *)longarray == (double)si) {
        !           190:                                                //write_log (_T("SPEED GAIN: converted a DOUBLE constant to SINGLE\n"));
        !           191:                                                mov_l_mi((uae_u32)temp_fp, *(uae_u32 *)&si);
        !           192:                                                fmovs_rm(treg, (uae_u32)temp_fp);
        !           193:                                                return 1;
        !           194:                                        }
        !           195:                                        //write_log (_T("immediate DOUBLE constant\n"));
        !           196:                                        mov_l_mi((uae_u32)temp_fp, longarray[0]);
        !           197:                                        mov_l_mi(((uae_u32)temp_fp) + 4, longarray[1]);
        !           198:                                        fmov_rm(treg, (uae_u32)temp_fp);
        !           199:                                        return 2;
        !           200:                                }
        !           201:                                case 6:
        !           202:                                {
        !           203:                                        float si = (float)(uae_s8)comp_get_ibyte(m68k_pc_offset - 2);
        !           204: 
        !           205:                                        //write_log (_T("converted immediate BYTE constant to SINGLE\n"));
        !           206:                                        mov_l_mi((uae_u32)temp_fp, *(uae_u32 *)&si);
        !           207:                                        fmovs_rm(treg, (uae_u32)temp_fp);
        !           208:                                        return 1;
        !           209:                                }
        !           210:                                default: /* never reached */
        !           211:                                return -1;
        !           212:                        }
        !           213:                        default: /* never reached */
        !           214:                        return -1;
        !           215:                }
1.1       root      216:        }
                    217: 
1.1.1.2 ! root      218:        switch (size) {
        !           219:                case 0: /* Long */
        !           220:                readlong (S1, S2, S3);
        !           221:                mov_l_mr ((uae_u32) temp_fp, S2);
        !           222:                fmovi_rm (treg, (uae_u32) temp_fp);
        !           223:                return 2;
        !           224:                case 1: /* Single */
        !           225:                readlong (S1, S2, S3);
        !           226:                mov_l_mr ((uae_u32) temp_fp, S2);
        !           227:                fmovs_rm (treg, (uae_u32) temp_fp);
        !           228:                return 1;
        !           229:                case 2: /* Long Double */
        !           230:                readword (S1, S2, S3);
        !           231:                mov_w_mr (((uae_u32) temp_fp) + 8, S2);
        !           232:                add_l_ri (S1, 4);
        !           233:                readlong (S1, S2, S3);
        !           234:                mov_l_mr (((uae_u32) temp_fp) + 4, S2);
        !           235:                add_l_ri (S1, 4);
        !           236:                readlong (S1, S2, S3);
        !           237:                mov_l_mr (((uae_u32) temp_fp), S2);
        !           238:                fmov_ext_rm (treg, (uae_u32) (temp_fp));
        !           239:                return 0;
        !           240:                case 4: /* Word */
        !           241:                readword (S1, S2, S3);
        !           242:                sign_extend_16_rr (S2, S2);
        !           243:                mov_l_mr ((uae_u32) temp_fp, S2);
        !           244:                fmovi_rm (treg, (uae_u32) temp_fp);
        !           245:                return 1;
        !           246:                case 5: /* Double */
        !           247:                readlong (S1, S2, S3);
        !           248:                mov_l_mr (((uae_u32) temp_fp) + 4, S2);
        !           249:                add_l_ri (S1, 4);
        !           250:                readlong (S1, S2, S3);
        !           251:                mov_l_mr (((uae_u32) temp_fp), S2);
        !           252:                fmov_rm (treg, (uae_u32) temp_fp);
        !           253:                return 2;
        !           254:                case 6: /* Byte */
        !           255:                readbyte (S1, S2, S3);
        !           256:                sign_extend_8_rr (S2, S2);
        !           257:                mov_l_mr ((uae_u32) temp_fp, S2);
        !           258:                fmovi_rm (treg, (uae_u32) temp_fp);
        !           259:                return 1;
        !           260:                default:
        !           261:                return -1;
        !           262:        }
1.1       root      263:        return -1;
                    264: }
                    265: 
                    266: /* return of -1 means failure, >=0 means OK */
                    267: STATIC_INLINE int comp_fp_put (uae_u32 opcode, uae_u16 extra)
                    268: {
1.1.1.2 ! root      269:        int reg = opcode & 7;
        !           270:        int sreg = (extra >> 7) & 7;
        !           271:        int mode = (opcode >> 3) & 7;
        !           272:        int size = (extra >> 10) & 7;
        !           273: 
        !           274:        if (size == 3 || size == 7) /* 3 = packed decimal, 7 is not defined */
        !           275:                return -1;
        !           276:        switch (mode) {
        !           277:                case 0: /* Dn */
        !           278:                switch (size) {
        !           279:                        case 0: /* FMOVE.L FPx, Dn */
1.1       root      280: #if USE_X86_FPUCW && 0
1.1.1.2 ! root      281:                        if (!(regs.fpcr & 0xf0)) { /* if extended round to nearest */
        !           282:                                mov_l_ri(S1,0x10); /* use extended round to zero mode */
        !           283:                                fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
        !           284:                                fmovi_mrb((uae_u32)temp_fp,sreg, clamp_bounds.l);
        !           285:                                mov_l_rm(reg,(uae_u32)temp_fp);
        !           286:                                mov_l_rm(S1,(uae_u32)&regs.fpcr);
        !           287:                                and_l_ri(S1,0xf0); /* restore control word */
        !           288:                                fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
        !           289:                                return 0;
        !           290:                        }
1.1       root      291: #endif
1.1.1.2 ! root      292:                        fmovi_mrb ((uae_u32) temp_fp, sreg, clamp_bounds.l);
        !           293:                        mov_l_rm (reg, (uae_u32) temp_fp);
        !           294:                        return 0;
        !           295:                        case 1: /* FMOVE.S FPx, Dn */
        !           296:                        fmovs_mr ((uae_u32) temp_fp, sreg);
        !           297:                        mov_l_rm (reg, (uae_u32) temp_fp);
        !           298:                        return 0;
        !           299:                        case 4: /* FMOVE.W FPx, Dn */
1.1       root      300: #if USE_X86_FPUCW && 0
1.1.1.2 ! root      301:                        if (!(regs.fpcr & 0xf0)) { /* if extended round to nearest */
        !           302:                                mov_l_ri(S1,0x10); /* use extended round to zero mode */
        !           303:                                fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
        !           304:                                fmovi_mrb((uae_u32)temp_fp,sreg, clamp_bounds.w);
        !           305:                                mov_w_rm(reg,(uae_u32)temp_fp);
        !           306:                                mov_l_rm(S1,(uae_u32)&regs.fpcr);
        !           307:                                and_l_ri(S1,0xf0); /* restore control word */
        !           308:                                fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
        !           309:                                return 0;
        !           310:                        }
1.1       root      311: #endif
1.1.1.2 ! root      312:                        fmovi_mrb ((uae_u32) temp_fp, sreg, clamp_bounds.w);
        !           313:                        mov_w_rm (reg, (uae_u32) temp_fp);
        !           314:                        return 0;
        !           315:                        case 6: /* FMOVE.B FPx, Dn */
1.1       root      316: #if USE_X86_FPUCW && 0
1.1.1.2 ! root      317:                        if (!(regs.fpcr & 0xf0)) { /* if extended round to nearest */
        !           318:                                mov_l_ri(S1,0x10); /* use extended round to zero mode */
        !           319:                                fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
        !           320:                                fmovi_mrb((uae_u32)temp_fp,sreg, clamp_bounds.b);
        !           321:                                mov_b_rm(reg,(uae_u32)temp_fp);
        !           322:                                mov_l_rm(S1,(uae_u32)&regs.fpcr);
        !           323:                                and_l_ri(S1,0xf0); /* restore control word */
        !           324:                                fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
        !           325:                                return 0;
        !           326:                        }
1.1       root      327: #endif
1.1.1.2 ! root      328:                        fmovi_mrb ((uae_u32) temp_fp, sreg, clamp_bounds.b);
        !           329:                        mov_b_rm (reg, (uae_u32) temp_fp);
        !           330:                        return 0;
        !           331:                        default:
        !           332:                        return -1;
        !           333:                }
        !           334:                case 1: /* An, invalid mode */
        !           335:                return -1;
        !           336:                case 2: /* (An) */
        !           337:                mov_l_rr (S1, reg + 8);
        !           338:                break;
        !           339:                case 3: /* (An)+ */
        !           340:                mov_l_rr (S1, reg + 8);
        !           341:                lea_l_brr (reg + 8, reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
        !           342:                break;
        !           343:                case 4: /* -(An) */
        !           344:                lea_l_brr (reg + 8, reg + 8, -(reg == 7 ? sz2[size] : sz1[size]));
        !           345:                mov_l_rr (S1, reg + 8);
        !           346:                break;
        !           347:                case 5: /* (d16,An) */
        !           348:                {
        !           349:                        uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           350:                        mov_l_rr (S1, reg + 8);
        !           351:                        add_l_ri (S1, off);
        !           352:                        break;
        !           353:                }
        !           354:                case 6: /* (d8,An,Xn) or (bd,An,Xn) or ([bd,An,Xn],od) or ([bd,An],Xn,od) */
        !           355:                {
        !           356:                        uae_u32 dp = comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           357:                        calc_disp_ea_020 (reg + 8, dp, S1, S2);
        !           358:                        break;
        !           359:                }
        !           360:                case 7:
        !           361:                switch (reg) {
        !           362:                        case 0: /* (xxx).W */
        !           363:                        {
        !           364:                                uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           365:                                mov_l_ri (S1, off);
        !           366:                                break;
        !           367:                        }
        !           368:                        case 1: /* (xxx).L */
        !           369:                        {
        !           370:                                uae_u32 off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
        !           371:                                mov_l_ri (S1, off);
        !           372:                                break;
        !           373:                        }
        !           374:                        default: /* All other modes are not allowed for FPx to <EA> */
        !           375:                        write_log (_T ("JIT FMOVE FPx,<EA> Mode is not allowed %04x %04x\n"), opcode, extra);
        !           376:                        return -1;
        !           377:                }
1.1       root      378:        }
1.1.1.2 ! root      379:        switch (size) {
        !           380:                case 0: /* Long */
        !           381:                fmovi_mrb ((uae_u32) temp_fp, sreg, clamp_bounds.l);
        !           382:                mov_l_rm (S2, (uae_u32) temp_fp);
        !           383:                writelong_clobber (S1, S2, S3);
        !           384:                return 0;
        !           385:                case 1: /* Single */
        !           386:                fmovs_mr ((uae_u32) temp_fp, sreg);
        !           387:                mov_l_rm (S2, (uae_u32) temp_fp);
        !           388:                writelong_clobber (S1, S2, S3);
        !           389:                return 0;
        !           390:                case 2:/* Long Double */
        !           391:                fmov_ext_mr ((uae_u32) temp_fp, sreg);
        !           392:                mov_w_rm (S2, (uae_u32) temp_fp + 8);
        !           393:                writeword_clobber (S1, S2, S3);
        !           394:                add_l_ri (S1, 4);
        !           395:                mov_l_rm (S2, (uae_u32) temp_fp + 4);
        !           396:                writelong_clobber (S1, S2, S3);
        !           397:                add_l_ri (S1, 4);
        !           398:                mov_l_rm (S2, (uae_u32) temp_fp);
        !           399:                writelong_clobber (S1, S2, S3);
        !           400:                return 0;
        !           401:                case 4: /* Word */
        !           402:                fmovi_mrb ((uae_u32) temp_fp, sreg, clamp_bounds.w);
        !           403:                mov_l_rm (S2, (uae_u32) temp_fp);
        !           404:                writeword_clobber (S1, S2, S3);
        !           405:                return 0;
        !           406:                case 5: /* Double */
        !           407:                fmov_mr ((uae_u32) temp_fp, sreg);
        !           408:                mov_l_rm (S2, (uae_u32) temp_fp + 4);
        !           409:                writelong_clobber (S1, S2, S3);
        !           410:                add_l_ri (S1, 4);
        !           411:                mov_l_rm (S2, (uae_u32) temp_fp);
        !           412:                writelong_clobber (S1, S2, S3);
        !           413:                return 0;
        !           414:                case 6: /* Byte */
        !           415:                fmovi_mrb ((uae_u32) temp_fp, sreg, clamp_bounds.b);
        !           416:                mov_l_rm (S2, (uae_u32) temp_fp);
        !           417:                writebyte (S1, S2, S3);
        !           418:                return 0;
        !           419:                default:
        !           420:                return -1;
1.1       root      421:        }
                    422:        return -1;
                    423: }
                    424: 
                    425: /* return -1 for failure, or register number for success */
                    426: STATIC_INLINE int comp_fp_adr (uae_u32 opcode)
                    427: {
1.1.1.2 ! root      428:        uae_s32 off;
        !           429:        int mode = (opcode >> 3) & 7;
        !           430:        int reg = opcode & 7;
        !           431: 
        !           432:        switch (mode) {
        !           433:                case 2:
        !           434:                case 3:
        !           435:                case 4:
        !           436:                mov_l_rr (S1, 8 + reg);
        !           437:                return S1;
        !           438:                case 5:
        !           439:                off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           440:                mov_l_rr (S1, 8 + reg);
        !           441:                add_l_ri (S1, off);
        !           442:                return S1;
        !           443:                case 7:
        !           444:                switch (reg) {
        !           445:                        case 0:
        !           446:                        off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           447:                        mov_l_ri (S1, off);
        !           448:                        return S1;
        !           449:                        case 1:
        !           450:                        off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
        !           451:                        mov_l_ri (S1, off);
        !           452:                        return S1;
        !           453:                }
        !           454:                default:
        !           455:                return -1;
1.1       root      456:        }
                    457: }
                    458: 
                    459: void comp_fdbcc_opp (uae_u32 opcode, uae_u16 extra)
                    460: {
1.1.1.2 ! root      461:        FAIL (1);
        !           462:        return;
1.1       root      463: }
                    464: 
                    465: void comp_fscc_opp (uae_u32 opcode, uae_u16 extra)
                    466: {
1.1.1.2 ! root      467:        int reg;
1.1       root      468: 
1.1.1.2 ! root      469:        if (!currprefs.compfpu) {
        !           470:                FAIL (1);
        !           471:                return;
        !           472:        }
1.1       root      473: 
                    474: #if DEBUG_FPP
1.1.1.2 ! root      475:        write_log (_T("JIT: fscc_opp at %08lx\n"), M68K_GETPC);
1.1       root      476: #endif
                    477: 
1.1.1.2 ! root      478:        if (extra & 0x20) {  /* only cc from 00 to 1f are defined */
        !           479:                FAIL (1);
        !           480:                return;
        !           481:        }
        !           482:        if ((opcode & 0x38) != 0) { /* We can only do to integer register */
        !           483:                FAIL (1);
        !           484:                return;
        !           485:        }
1.1       root      486: 
1.1.1.2 ! root      487:        fflags_into_flags (S2);
        !           488:        reg = (opcode & 7);
1.1       root      489: 
1.1.1.2 ! root      490:        mov_l_ri (S1, 255);
        !           491:        mov_l_ri (S4, 0);
        !           492:        switch (extra & 0x0f) { /* according to fpp.c, the 0x10 bit is ignored */
        !           493:                case 0: break;  /* set never */
        !           494:                case 1: mov_l_rr (S2, S4);
        !           495:                        cmov_l_rr (S4, S1, 4);
        !           496:                        cmov_l_rr (S4, S2, 10); break;
        !           497:                case 2: cmov_l_rr (S4, S1, 7); break;
        !           498:                case 3: cmov_l_rr (S4, S1, 3); break;
        !           499:                case 4: mov_l_rr (S2, S4);
        !           500:                        cmov_l_rr (S4, S1, 2);
        !           501:                        cmov_l_rr (S4, S2, 10); break;
        !           502:                case 5: mov_l_rr (S2, S4);
        !           503:                        cmov_l_rr (S4, S1, 6);
        !           504:                        cmov_l_rr (S4, S2, 10); break;
        !           505:                case 6: cmov_l_rr (S4, S1, 5); break;
        !           506:                case 7: cmov_l_rr (S4, S1, 11); break;
        !           507:                case 8: cmov_l_rr (S4, S1, 10); break;
        !           508:                case 9: cmov_l_rr (S4, S1, 4); break;
        !           509:                case 10: cmov_l_rr (S4, S1, 10); cmov_l_rr (S4, S1, 7); break;
        !           510:                case 11: cmov_l_rr (S4, S1, 4); cmov_l_rr (S4, S1, 3); break;
        !           511:                case 12: cmov_l_rr (S4, S1, 2); break;
        !           512:                case 13: cmov_l_rr (S4, S1, 6); break;
        !           513:                case 14: cmov_l_rr (S4, S1, 5); cmov_l_rr (S4, S1, 10); break;
        !           514:                case 15: mov_l_rr (S4, S1); break;
        !           515:        }
1.1       root      516: 
1.1.1.2 ! root      517:        if (!(opcode & 0x38))
        !           518:                mov_b_rr (reg, S4);
1.1       root      519: #if 0
1.1.1.2 ! root      520:        else {
        !           521:                abort();
        !           522:                if (!comp_fp_adr (opcode)) {
        !           523:                        m68k_setpc (m68k_getpc () - 4);
        !           524:                        op_illg (opcode);
        !           525:                }
        !           526:                else
        !           527:                        put_byte (ad, cc ? 0xff : 0x00);
1.1       root      528:        }
                    529: #endif
                    530: }
                    531: 
                    532: void comp_ftrapcc_opp (uae_u32 opcode, uaecptr oldpc)
                    533: {
1.1.1.2 ! root      534:        FAIL (1);
        !           535:        return;
1.1       root      536: }
                    537: 
                    538: extern unsigned long foink3, oink;
                    539: 
                    540: void comp_fbcc_opp (uae_u32 opcode)
                    541: {
1.1.1.2 ! root      542:        uae_u32 start_68k_offset = m68k_pc_offset;
        !           543:        uae_u32 off, v1, v2;
        !           544:        int cc;
1.1       root      545: 
1.1.1.2 ! root      546:        if (!currprefs.compfpu) {
        !           547:                FAIL (1);
        !           548:                return;
        !           549:        }
1.1       root      550: 
1.1.1.2 ! root      551:        if (opcode & 0x20) {  /* only cc from 00 to 1f are defined */
        !           552:                FAIL (1);
        !           553:                return;
        !           554:        }
        !           555:        if (!(opcode & 0x40)) {
        !           556:                off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
        !           557:        }
        !           558:        else {
        !           559:                off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
        !           560:        }
        !           561:        mov_l_ri (S1, (uae_u32)
        !           562:                          (comp_pc_p + off - (m68k_pc_offset - start_68k_offset)));
        !           563:        mov_l_ri (PC_P, (uae_u32) comp_pc_p);
        !           564: 
        !           565:        /* Now they are both constant. Might as well fold in m68k_pc_offset */
        !           566:        add_l_ri (S1, m68k_pc_offset);
        !           567:        add_l_ri (PC_P, m68k_pc_offset);
        !           568:        m68k_pc_offset = 0;
        !           569: 
        !           570:        /* according to fpp.c, the 0x10 bit is ignored
        !           571:           (it handles exception handling, which we don't
        !           572:           do, anyway ;-) */
        !           573:        cc = opcode & 0x0f;
        !           574:        v1 = get_const (PC_P);
        !           575:        v2 = get_const (S1);
        !           576:        fflags_into_flags (S2);
        !           577: 
        !           578:        // mov_l_mi((uae_u32)&foink3,cc);
        !           579:        switch (cc) {
        !           580:                case 0: break;  /* jump never */
        !           581:                case 1:
        !           582:                mov_l_rr (S2, PC_P);
        !           583:                cmov_l_rr (PC_P, S1, 4);
        !           584:                cmov_l_rr (PC_P, S2, 10); break;
        !           585:                case 2: register_branch (v1, v2, 7); break;
        !           586:                case 3: register_branch (v1, v2, 3); break;
        !           587:                case 4:
        !           588:                mov_l_rr (S2, PC_P);
        !           589:                cmov_l_rr (PC_P, S1, 2);
        !           590:                cmov_l_rr (PC_P, S2, 10); break;
        !           591:                case 5:
        !           592:                mov_l_rr (S2, PC_P);
        !           593:                cmov_l_rr (PC_P, S1, 6);
        !           594:                cmov_l_rr (PC_P, S2, 10); break;
        !           595:                case 6: register_branch (v1, v2, 5); break;
        !           596:                case 7: register_branch (v1, v2, 11); break;
        !           597:                case 8: register_branch (v1, v2, 10); break;
        !           598:                case 9: register_branch (v1, v2, 4); break;
        !           599:                case 10:
        !           600:                cmov_l_rr (PC_P, S1, 10);
        !           601:                cmov_l_rr (PC_P, S1, 7); break;
        !           602:                case 11:
        !           603:                cmov_l_rr (PC_P, S1, 4);
        !           604:                cmov_l_rr (PC_P, S1, 3); break;
        !           605:                case 12: register_branch (v1, v2, 2); break;
        !           606:                case 13: register_branch (v1, v2, 6); break;
        !           607:                case 14:
        !           608:                cmov_l_rr (PC_P, S1, 5);
        !           609:                cmov_l_rr (PC_P, S1, 10); break;
        !           610:                case 15: mov_l_rr (PC_P, S1); break;
        !           611:        }
1.1       root      612: }
                    613: 
1.1.1.2 ! root      614: /* Floating point conditions
        !           615:    The "NotANumber" part could be problematic; Howver, when NaN is
        !           616:    encountered, the ftst instruction sets bot N and Z to 1 on the x87,
        !           617:    so quite often things just fall into place. This is probably not
        !           618:    accurate wrt the 68k FPU, but it is *as* accurate as this was before.
        !           619:    However, some more thought should go into fixing this stuff up so
        !           620:    it accurately emulates the 68k FPU.
        !           621:    >=<U
        !           622:    0000    0x00: 0                        ---   Never jump
        !           623:    0101    0x01: Z                        ---   jump if zero (x86: 4)
        !           624:    1000    0x02: !(NotANumber || Z || N)  --- Neither Z nor N set (x86: 7)
        !           625:    1101    0x03: Z || !(NotANumber || N); --- Z or !N (x86: 4 and 3)
        !           626:    0010    0x04: N && !(NotANumber || Z); --- N and !Z (x86: hard!)
        !           627:    0111    0x05: Z || (N && !NotANumber); --- Z or N (x86: 6)
        !           628:    1010    0x06: !(NotANumber || Z);      --- not Z (x86: 5)
        !           629:    1110    0x07: !NotANumber;             --- not NaN (x86: 11, not parity)
        !           630:    0001    0x08: NotANumber;              --- NaN (x86: 10)
        !           631:    0101    0x09: NotANumber || Z;         --- Z (x86: 4)
        !           632:    1001    0x0a: NotANumber || !(N || Z); --- NaN or neither N nor Z (x86: 10 and 7)
        !           633:    1101    0x0b: NotANumber || Z || !N;   --- Z or !N (x86: 4 and 3)
        !           634:    0011    0x0c: NotANumber || (N && !Z); --- N (x86: 2)
        !           635:    0111    0x0d: NotANumber || Z || N;    --- Z or N (x86: 6)
        !           636:    1010    0x0e: !Z;                      --- not Z (x86: 5)
        !           637:    1111    0x0f: 1;                       --- always
        !           638: 
        !           639:    This is not how the 68k handles things, though --- it sets Z to 0 and N
        !           640:    to the NaN's sign.... ('o' and 'i' denote differences from the above
        !           641:    table)
        !           642: 
        !           643:    >=<U
        !           644:    0000    0x00: 0                        ---   Never jump
        !           645:    010o    0x01: Z                        ---   jump if zero (x86: 4, not 10)
        !           646:    1000    0x02: !(NotANumber || Z || N)  --- Neither Z nor N set (x86: 7)
        !           647:    110o    0x03: Z || !(NotANumber || N); --- Z or !N (x86: 3)
        !           648:    0010    0x04: N && !(NotANumber || Z); --- N and !Z (x86: 2, not 10)
        !           649:    011o    0x05: Z || (N && !NotANumber); --- Z or N (x86: 6, not 10)
        !           650:    1010    0x06: !(NotANumber || Z);      --- not Z (x86: 5)
        !           651:    1110    0x07: !NotANumber;             --- not NaN (x86: 11, not parity)
        !           652:    0001    0x08: NotANumber;              --- NaN (x86: 10)
        !           653:    0101    0x09: NotANumber || Z;         --- Z (x86: 4)
        !           654:    1001    0x0a: NotANumber || !(N || Z); --- NaN or neither N nor Z (x86: 10 and 7)
        !           655:    1101    0x0b: NotANumber || Z || !N;   --- Z or !N (x86: 4 and 3)
        !           656:    0011    0x0c: NotANumber || (N && !Z); --- N (x86: 2)
        !           657:    0111    0x0d: NotANumber || Z || N;    --- Z or N (x86: 6)
        !           658:    101i    0x0e: !Z;                      --- not Z (x86: 5 and 10)
        !           659:    1111    0x0f: 1;                       --- always
        !           660: 
        !           661:    Of course, this *still* doesn't mean that the x86 and 68k conditions are
        !           662:    equivalent --- the handling of infinities is different, for one thing.
        !           663:    On the 68k, +infinity minus +infinity is NotANumber (as it should be). On
        !           664:    the x86, it is +infinity, and some exception is raised (which I suspect
        !           665:    is promptly ignored) STUPID!
        !           666:    The more I learn about their CPUs, the more I detest Intel....
        !           667: 
        !           668:    You can see this in action if you have "Benoit" (see Aminet) and
        !           669:    set the exponent to 16. Wait for a long time, and marvel at the extra black
        !           670:    areas outside the center one. That's where Benoit expects NaN, and the x86
        !           671:    gives +infinity. [Ooops --- that must have been some kind of bug in my code.
        !           672:    it no longer happens, and the resulting graphic looks much better, too]
        !           673: 
        !           674:    x86 conditions
        !           675:    0011    : 2
        !           676:    1100    : 3
        !           677:    0101    : 4
        !           678:    1010    : 5
        !           679:    0111    : 6
        !           680:    1000    : 7
        !           681:    0001    : 10
        !           682:    1110    : 11
        !           683:    */
1.1       root      684: void comp_fsave_opp (uae_u32 opcode)
                    685: {
1.1.1.2 ! root      686:        FAIL (1);
        !           687:        return;
1.1       root      688: }
                    689: 
                    690: void comp_frestore_opp (uae_u32 opcode)
                    691: {
1.1.1.2 ! root      692:        FAIL (1);
        !           693:        return;
1.1       root      694: }
                    695: 
                    696: extern uae_u32 xhex_pi[], xhex_exp_1[], xhex_l2_e[], xhex_ln_2[], xhex_ln_10[];
                    697: extern uae_u32 xhex_l10_2[], xhex_l10_e[], xhex_1e16[], xhex_1e32[], xhex_1e64[];
                    698: extern uae_u32 xhex_1e128[], xhex_1e256[], xhex_1e512[], xhex_1e1024[];
                    699: extern uae_u32 xhex_1e2048[], xhex_1e4096[];
                    700: extern double fp_1e8;
                    701: extern float  fp_1e1, fp_1e2, fp_1e4;
                    702: 
                    703: void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
                    704: {
1.1.1.2 ! root      705:        int reg;
        !           706:        int sreg, prec = 0;
        !           707:        int     dreg = (extra >> 7) & 7;
        !           708:        int source = (extra >> 13) & 7;
        !           709:        int     opmode = extra & 0x7f;
1.1       root      710: 
1.1.1.2 ! root      711:        if (!currprefs.compfpu) {
        !           712:                FAIL (1);
        !           713:                return;
        !           714:        }
        !           715:        switch (source) {
        !           716:                case 3: /* FMOVE FPx, <EA> */
        !           717:                if (comp_fp_put (opcode, extra) < 0)
        !           718:                        FAIL (1);
        !           719:                return;
        !           720:                case 4: /* FMOVE.L  <EA>, ControlReg */
        !           721:                if (!(opcode & 0x30)) { /* Dn or An */
        !           722:                        if (extra & 0x1000) { /* FPCR */
        !           723:                                mov_l_mr ((uae_u32) &regs.fpcr, opcode & 15);
1.1       root      724: #if USE_X86_FPUCW
1.1.1.2 ! root      725:                                mov_l_rr (S1, opcode & 15);
        !           726:                                and_l_ri (S1, 0xf0);
        !           727:                                fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
1.1       root      728: #endif
1.1.1.2 ! root      729:                                return;
        !           730:                        }
        !           731:                        if (extra & 0x0800) { /* FPSR */
        !           732:                                FAIL (1);
        !           733:                                return;
        !           734:                                // set_fpsr(m68k_dreg (regs, opcode & 15));
        !           735:                        }
        !           736:                        if (extra & 0x0400) { /* FPIAR */
        !           737:                                mov_l_mr ((uae_u32) &regs.fpiar, opcode & 15); return;
        !           738:                        }
1.1       root      739:                }
1.1.1.2 ! root      740:                else if ((opcode & 0x3f) == 0x3c) {
        !           741:                        if (extra & 0x1000) { /* FPCR */
        !           742:                                uae_u32 val = comp_get_ilong ((m68k_pc_offset += 4) - 4);
        !           743:                                mov_l_mi ((uae_u32) &regs.fpcr, val);
1.1       root      744: #if USE_X86_FPUCW
1.1.1.2 ! root      745:                                mov_l_ri (S1, val & 0xf0);
        !           746:                                fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
1.1       root      747: #endif
1.1.1.2 ! root      748:                                return;
        !           749:                        }
        !           750:                        if (extra & 0x0800) { /* FPSR */
        !           751:                                FAIL (1);
        !           752:                                return;
        !           753:                        }
        !           754:                        if (extra & 0x0400) { /* FPIAR */
        !           755:                                uae_u32 val = comp_get_ilong ((m68k_pc_offset += 4) - 4);
        !           756:                                mov_l_mi ((uae_u32) &regs.fpiar, val);
        !           757:                                return;
        !           758:                        }
1.1       root      759:                }
1.1.1.2 ! root      760:                FAIL (1);
        !           761:                return;
        !           762:                case 5: /* FMOVE.L  ControlReg, <EA> */
        !           763:                if (!(opcode & 0x30)) { /* Dn or An */
        !           764:                        if (extra & 0x1000) { /* FPCR */
        !           765:                                mov_l_rm (opcode & 15, (uae_u32) &regs.fpcr); return;
        !           766:                        }
        !           767:                        if (extra & 0x0800) { /* FPSR */
        !           768:                                FAIL (1);
        !           769:                                return;
        !           770:                        }
        !           771:                        if (extra & 0x0400) { /* FPIAR */
        !           772:                                mov_l_rm (opcode & 15, (uae_u32) &regs.fpiar); return;
        !           773:                        }
1.1       root      774:                }
1.1.1.2 ! root      775:                FAIL (1);
        !           776:                return;
        !           777:                case 6:
        !           778:                case 7:
        !           779:                {
        !           780:                        uae_u32 list = 0;
        !           781:                        int incr = 0;
        !           782:                        if (extra & 0x2000) {
        !           783:                                int ad;
        !           784: 
        !           785:                                /* FMOVEM FPP->memory */
        !           786:                                switch ((extra >> 11) & 3) { /* Get out early if failure */
        !           787:                                        case 0:
        !           788:                                        case 2:
        !           789:                                        break;
        !           790:                                        case 1:
        !           791:                                        case 3:
        !           792:                                        default:
        !           793:                                        FAIL (1); return;
        !           794:                                }
        !           795:                                ad = comp_fp_adr (opcode);
        !           796:                                if (ad < 0) {
        !           797:                                        m68k_setpc (m68k_getpc () - 4);
        !           798:                                        op_illg (opcode);
        !           799:                                        return;
        !           800:                                }
        !           801:                                switch ((extra >> 11) & 3) {
        !           802:                                        case 0: /* static pred */
        !           803:                                        list = extra & 0xff;
        !           804:                                        incr = -1;
        !           805:                                        break;
        !           806:                                        case 2: /* static postinc */
        !           807:                                        list = extra & 0xff;
        !           808:                                        incr = 1;
        !           809:                                        break;
        !           810:                                        case 1: /* dynamic pred */
        !           811:                                        case 3: /* dynamic postinc */
        !           812:                                        abort ();
        !           813:                                }
        !           814:                                if (incr < 0) { /* Predecrement */
        !           815:                                        for (reg = 7; reg >= 0; reg--) {
        !           816:                                                if (list & 0x80) {
        !           817:                                                        fmov_ext_mr ((uintptr) temp_fp, reg);
        !           818:                                                        sub_l_ri (ad, 4);
        !           819:                                                        mov_l_rm (S2, (uintptr) temp_fp);
        !           820:                                                        writelong_clobber (ad, S2, S3);
        !           821:                                                        sub_l_ri (ad, 4);
        !           822:                                                        mov_l_rm (S2, (uintptr) temp_fp + 4);
        !           823:                                                        writelong_clobber (ad, S2, S3);
        !           824:                                                        sub_l_ri (ad, 4);
        !           825:                                                        mov_w_rm (S2, (uintptr) temp_fp + 8);
        !           826:                                                        writeword_clobber (ad, S2, S3);
        !           827:                                                }
        !           828:                                                list <<= 1;
        !           829:                                        }
        !           830:                                } else { /* Postincrement */
        !           831:                                        for (reg = 0; reg <= 7; reg++) {
        !           832:                                                if (list & 0x80) {
        !           833:                                                        fmov_ext_mr ((uintptr) temp_fp, reg);
        !           834:                                                        mov_w_rm (S2, (uintptr) temp_fp + 8);
        !           835:                                                        writeword_clobber (ad, S2, S3);
        !           836:                                                        add_l_ri (ad, 4);
        !           837:                                                        mov_l_rm (S2, (uintptr) temp_fp + 4);
        !           838:                                                        writelong_clobber (ad, S2, S3);
        !           839:                                                        add_l_ri (ad, 4);
        !           840:                                                        mov_l_rm (S2, (uintptr) temp_fp);
        !           841:                                                        writelong_clobber (ad, S2, S3);
        !           842:                                                        add_l_ri (ad, 4);
        !           843:                                                }
        !           844:                                                list <<= 1;
        !           845:                                        }
        !           846:                                }
        !           847:                                if ((opcode & 0x38) == 0x18)
        !           848:                                        mov_l_rr ((opcode & 7) + 8, ad);
        !           849:                                if ((opcode & 0x38) == 0x20)
        !           850:                                        mov_l_rr ((opcode & 7) + 8, ad);
        !           851:                        } else {
        !           852:                                /* FMOVEM memory->FPP */
        !           853: 
        !           854:                                int ad;
        !           855:                                switch ((extra >> 11) & 3) { /* Get out early if failure */
        !           856:                                        case 0:
        !           857:                                        case 2:
        !           858:                                        break;
        !           859:                                        case 1:
        !           860:                                        case 3:
        !           861:                                        default:
        !           862:                                        FAIL (1); return;
        !           863:                                }
        !           864:                                ad = comp_fp_adr (opcode);
        !           865:                                if (ad < 0) {
        !           866:                                        m68k_setpc (m68k_getpc () - 4);
        !           867:                                        op_illg (opcode);
        !           868:                                        return;
        !           869:                                }
        !           870:                                switch ((extra >> 11) & 3) {
        !           871:                                        case 0: /* static pred */
        !           872:                                        list = extra & 0xff;
        !           873:                                        incr = -1;
        !           874:                                        break;
        !           875:                                        case 2: /* static postinc */
        !           876:                                        list = extra & 0xff;
        !           877:                                        incr = 1;
        !           878:                                        break;
        !           879:                                        case 1: /* dynamic pred */
        !           880:                                        case 3: /* dynamic postinc */
        !           881:                                        abort ();
1.1       root      882:                                }
1.1.1.2 ! root      883: 
        !           884:                                if (incr < 0) {
        !           885:                                        // not reached
        !           886:                                        for (reg = 7; reg >= 0; reg--) {
        !           887:                                                if (list & 0x80) {
        !           888:                                                        sub_l_ri (ad, 4);
        !           889:                                                        readlong (ad, S2, S3);
        !           890:                                                        mov_l_mr ((uintptr) (temp_fp), S2);
        !           891:                                                        sub_l_ri (ad, 4);
        !           892:                                                        readlong (ad, S2, S3);
        !           893:                                                        mov_l_mr ((uintptr) (temp_fp) +4, S2);
        !           894:                                                        sub_l_ri (ad, 4);
        !           895:                                                        readword (ad, S2, S3);
        !           896:                                                        mov_w_mr (((uintptr) temp_fp) + 8, S2);
        !           897:                                                        fmov_ext_rm (reg, (uintptr) (temp_fp));
        !           898:                                                }
        !           899:                                                list <<= 1;
        !           900:                                        }
        !           901:                                } else {
        !           902:                                        for (reg = 0; reg <= 7; reg++) {
        !           903:                                                if (list & 0x80) {
        !           904:                                                        readword (ad, S2, S3);
        !           905:                                                        mov_w_mr (((uintptr) temp_fp) + 8, S2);
        !           906:                                                        add_l_ri (ad, 4);
        !           907:                                                        readlong (ad, S2, S3);
        !           908:                                                        mov_l_mr ((uintptr) (temp_fp) +4, S2);
        !           909:                                                        add_l_ri (ad, 4);
        !           910:                                                        readlong (ad, S2, S3);
        !           911:                                                        mov_l_mr ((uintptr) (temp_fp), S2);
        !           912:                                                        add_l_ri (ad, 4);
        !           913:                                                        fmov_ext_rm (reg, (uintptr) (temp_fp));
        !           914:                                                }
        !           915:                                                list <<= 1;
        !           916:                                        }
        !           917:                                }
        !           918:                                if ((opcode & 0x38) == 0x18)
        !           919:                                        mov_l_rr ((opcode & 7) + 8, ad);
        !           920:                                if ((opcode & 0x38) == 0x20)
        !           921:                                        mov_l_rr ((opcode & 7) + 8, ad);
1.1       root      922:                        }
                    923:                }
1.1.1.2 ! root      924:                return;
        !           925: #if 0
        !           926:                case 6: /* FMOVEM  <EA>, FPx-FPz */
        !           927:                if (!(extra & 0x0800)) {
        !           928:                        uae_u32 list = extra & 0xff;
        !           929:                        int ad;
        !           930:                        if ((ad = comp_fp_adr(opcode)) < 0) {FAIL(1);return;}
        !           931:                        while (list) {
        !           932:                                if  (extra & 0x1000) { /* postincrement */
        !           933:                                        readword(ad,S2,S3);
        !           934:                                        mov_w_mr(((uae_u32)temp_fp)+8,S2);
1.1       root      935:                                        add_l_ri(ad,4);
1.1.1.2 ! root      936:                                        readlong(ad,S2,S3);
        !           937:                                        mov_l_mr((uae_u32)(temp_fp)+4,S2);
1.1       root      938:                                        add_l_ri(ad,4);
1.1.1.2 ! root      939:                                        readlong(ad,S2,S3);
        !           940:                                        mov_l_mr((uae_u32)(temp_fp),S2);
1.1       root      941:                                        add_l_ri(ad,4);
1.1.1.2 ! root      942:                                        fmov_ext_rm(fpp_movem_index1[list],(uae_u32)(temp_fp));
        !           943:                                } else { /* predecrement */
1.1       root      944:                                        sub_l_ri(ad,4);
                    945:                                        readlong(ad,S2,S3);
1.1.1.2 ! root      946:                                        mov_l_mr((uae_u32)(temp_fp),S2);
1.1       root      947:                                        sub_l_ri(ad,4);
                    948:                                        readlong(ad,S2,S3);
1.1.1.2 ! root      949:                                        mov_l_mr((uae_u32)(temp_fp)+4,S2);
1.1       root      950:                                        sub_l_ri(ad,4);
                    951:                                        readword(ad,S2,S3);
1.1.1.2 ! root      952:                                        mov_w_mr(((uae_u32)temp_fp)+8,S2);
        !           953:                                        fmov_ext_rm(fpp_movem_index2[list],(uae_u32)(temp_fp));
1.1       root      954:                                }
1.1.1.2 ! root      955:                                list = fpp_movem_next[list];
1.1       root      956:                        }
1.1.1.2 ! root      957:                        if ((opcode & 0x38) == 0x18)
        !           958:                                mov_l_rr((opcode & 7)+8,ad);
        !           959:                        return;
        !           960:                } /* no break for dynamic register list */
        !           961:                case 7: /* FMOVEM  FPx-FPz, <EA> */
        !           962:                if (!(extra & 0x0800)) {
        !           963:                        uae_u32 list = extra & 0xff;
        !           964:                        int ad;
        !           965:                        if ((ad = comp_fp_adr(opcode)) < 0) {FAIL(1);return;}
        !           966:                        while (list) {
        !           967:                                if (extra & 0x1000) { /* postincrement */
        !           968:                                        fmov_ext_mr((uae_u32)temp_fp,fpp_movem_index2[list]);
        !           969:                                        mov_w_rm(S2,(uae_u32)temp_fp+8);
        !           970:                                        writeword_clobber(ad,S2,S3);
1.1       root      971:                                        add_l_ri(ad,4);
1.1.1.2 ! root      972:                                        mov_l_rm(S2,(uae_u32)temp_fp+4);
        !           973:                                        writelong_clobber(ad,S2,S3);
1.1       root      974:                                        add_l_ri(ad,4);
1.1.1.2 ! root      975:                                        mov_l_rm(S2,(uae_u32)temp_fp);
        !           976:                                        writelong_clobber(ad,S2,S3);
1.1       root      977:                                        add_l_ri(ad,4);
1.1.1.2 ! root      978:                                } else { /* predecrement */
        !           979:                                        fmov_ext_mr((uae_u32)temp_fp,fpp_movem_index2[list]);
        !           980:                                        sub_l_ri(ad,4);
        !           981:                                        mov_l_rm(S2,(uae_u32)temp_fp);
        !           982:                                        writelong_clobber(ad,S2,S3);
        !           983:                                        sub_l_ri(ad,4);
        !           984:                                        mov_l_rm(S2,(uae_u32)temp_fp+4);
        !           985:                                        writelong_clobber(ad,S2,S3);
        !           986:                                        sub_l_ri(ad,4);
        !           987:                                        mov_w_rm(S2,(uae_u32)temp_fp+8);
        !           988:                                        writeword_clobber(ad,S2,S3);
1.1       root      989:                                }
1.1.1.2 ! root      990:                                list = fpp_movem_next[list];
1.1       root      991:                        }
1.1.1.2 ! root      992:                        if ((opcode & 0x38) == 0x20)
        !           993:                                mov_l_rr((opcode & 7)+8,ad);
        !           994:                        return;
        !           995:                } /* no break */
        !           996:                write_log (_T("fallback from JIT FMOVEM dynamic register list\n"));
        !           997:                FAIL(1);
        !           998:                return;
1.1       root      999: #endif
1.1.1.2 ! root     1000:                case 2: /* from <EA> to FPx */
        !          1001:                dont_care_fflags ();
        !          1002:                if ((extra & 0xfc00) == 0x5c00) { /* FMOVECR */
        !          1003:                        //write_log (_T("JIT FMOVECR %x\n"), opmode);
        !          1004:                        switch (opmode) {
        !          1005:                                case 0x00:
        !          1006:                                fmov_pi (dreg);
        !          1007:                                break;
        !          1008:                                case 0x0b:
        !          1009:                                fmov_ext_rm (dreg, (uae_u32) &xhex_l10_2);
        !          1010:                                break;
        !          1011:                                case 0x0c:
        !          1012:                                fmov_ext_rm (dreg, (uae_u32) &xhex_exp_1);
        !          1013:                                break;
        !          1014:                                case 0x0d:
        !          1015:                                fmov_log2_e (dreg);
        !          1016:                                break;
        !          1017:                                case 0x0e:
        !          1018:                                fmov_ext_rm (dreg, (uae_u32) &xhex_l10_e);
        !          1019:                                break;
        !          1020:                                case 0x0f:
        !          1021:                                fmov_0 (dreg);
        !          1022:                                break;
        !          1023:                                case 0x30:
        !          1024:                                fmov_loge_2 (dreg);
        !          1025:                                break;
        !          1026:                                case 0x31:
        !          1027:                                fmov_ext_rm (dreg, (uae_u32) &xhex_ln_10);
        !          1028:                                break;
        !          1029:                                case 0x32:
        !          1030:                                fmov_1 (dreg);
        !          1031:                                break;
        !          1032:                                case 0x33:
        !          1033:                                fmovs_rm (dreg, (uae_u32) &fp_1e1);
        !          1034:                                break;
        !          1035:                                case 0x34:
        !          1036:                                fmovs_rm (dreg, (uae_u32) &fp_1e2);
        !          1037:                                break;
        !          1038:                                case 0x35:
        !          1039:                                fmovs_rm (dreg, (uae_u32) &fp_1e4);
        !          1040:                                break;
        !          1041:                                case 0x36:
        !          1042:                                fmov_rm (dreg, (uae_u32) &fp_1e8);
        !          1043:                                break;
        !          1044:                                case 0x37:
        !          1045:                                fmov_ext_rm (dreg, (uae_u32) &xhex_1e16);
        !          1046:                                break;
        !          1047:                                case 0x38:
        !          1048:                                fmov_ext_rm (dreg, (uae_u32) &xhex_1e32);
        !          1049:                                break;
        !          1050:                                case 0x39:
        !          1051:                                fmov_ext_rm (dreg, (uae_u32) &xhex_1e64);
        !          1052:                                break;
        !          1053:                                case 0x3a:
        !          1054:                                fmov_ext_rm (dreg, (uae_u32) &xhex_1e128);
        !          1055:                                break;
        !          1056:                                case 0x3b:
        !          1057:                                fmov_ext_rm (dreg, (uae_u32) &xhex_1e256);
        !          1058:                                break;
        !          1059:                                case 0x3c:
        !          1060:                                fmov_ext_rm (dreg, (uae_u32) &xhex_1e512);
        !          1061:                                break;
        !          1062:                                case 0x3d:
        !          1063:                                fmov_ext_rm (dreg, (uae_u32) &xhex_1e1024);
        !          1064:                                break;
        !          1065:                                case 0x3e:
        !          1066:                                fmov_ext_rm (dreg, (uae_u32) &xhex_1e2048);
        !          1067:                                break;
        !          1068:                                case 0x3f:
        !          1069:                                fmov_ext_rm (dreg, (uae_u32) &xhex_1e4096);
        !          1070:                                break;
        !          1071:                                default:
        !          1072:                                FAIL (1);
        !          1073:                                return;
        !          1074:                        }
        !          1075:                        fmov_rr (FP_RESULT, dreg);
        !          1076:                        return;
1.1       root     1077:                }
1.1.1.2 ! root     1078:                if (opmode & 0x20) /* two operands, so we need a scratch reg */
        !          1079:                        sreg = FS1;
        !          1080:                else /* one operand only, thus we can load the argument into dreg */
        !          1081:                        sreg = dreg;
        !          1082:                if ((prec = comp_fp_get (opcode, extra, sreg)) < 0) {
        !          1083:                        FAIL (1);
        !          1084:                        return;
        !          1085:                }
        !          1086:                if (!opmode) { /* FMOVE  <EA>,FPx */
        !          1087:                        fmov_rr (FP_RESULT, dreg);
        !          1088:                        return;
        !          1089:                }
        !          1090:                /* no break here for <EA> to dreg */
        !          1091:                case 0: /* directly from sreg to dreg */
        !          1092:                if (!source) { /* no <EA> */
        !          1093:                        dont_care_fflags ();
        !          1094:                        sreg = (extra >> 10) & 7;
        !          1095:                }
        !          1096:                switch (opmode) {
        !          1097:                        case 0x00: /* FMOVE */
        !          1098:                        fmov_rr (dreg, sreg);
        !          1099:                        break;
        !          1100:                        case 0x01: /* FINT */
        !          1101:                        frndint_rr (dreg, sreg);
        !          1102:                        break;
        !          1103:                        case 0x02: /* FSINH */
        !          1104:                        fsinh_rr (dreg, sreg);
        !          1105:                        break;
        !          1106:                        case 0x03: /* FINTRZ */
        !          1107: #if USE_X86_FPUCW /* if we have control over the CW, we can do this */
        !          1108:                        if (0 && (regs.fpcr & 0xf0) == 0x10) /* maybe unsafe, because this test is done */
        !          1109:                                frndint_rr (dreg, sreg); /* during the JIT compilation and not at runtime */
        !          1110:                        else {
        !          1111:                                mov_l_ri (S1, 0x10); /* extended round to zero */
        !          1112:                                fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1113:                                frndint_rr (dreg, sreg);
        !          1114:                                mov_l_rm (S1, (uae_u32) &regs.fpcr);
        !          1115:                                and_l_ri (S1, 0xf0); /* restore control word */
        !          1116:                                fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1117:                        }
        !          1118:                        break;
1.1       root     1119: #endif
1.1.1.2 ! root     1120:                        FAIL (1);
        !          1121:                        return;
        !          1122:                        case 0x04: /* FSQRT */
        !          1123:                        fsqrt_rr (dreg, sreg);
        !          1124:                        break;
        !          1125:                        case 0x06: /* FLOGNP1 */
        !          1126:                        flogNP1_rr (dreg, sreg);
        !          1127:                        break;
        !          1128:                        case 0x08: /* FETOXM1 */
        !          1129:                        fetoxM1_rr (dreg, sreg);
        !          1130:                        break;
        !          1131:                        case 0x09: /* FTANH */
        !          1132:                        ftanh_rr (dreg, sreg);
        !          1133:                        break;
        !          1134:                        case 0x0a: /* FATAN */
        !          1135:                        fatan_rr (dreg, sreg);
        !          1136:                        break;
        !          1137:                        case 0x0c: /* FASIN */
        !          1138:                        fasin_rr (dreg, sreg);
        !          1139:                        break;
        !          1140:                        case 0x0d: /* FATANH */
        !          1141:                        fatanh_rr (dreg, sreg);
        !          1142:                        break;
        !          1143:                        case 0x0e: /* FSIN */
        !          1144:                        fsin_rr (dreg, sreg);
        !          1145:                        break;
        !          1146:                        case 0x0f: /* FTAN */
        !          1147:                        ftan_rr (dreg, sreg);
        !          1148:                        break;
        !          1149:                        case 0x10: /* FETOX */
        !          1150:                        fetox_rr (dreg, sreg);
        !          1151:                        break;
        !          1152:                        case 0x11: /* FTWOTOX */
        !          1153:                        ftwotox_rr (dreg, sreg);
        !          1154:                        break;
        !          1155:                        case 0x12: /* FTENTOX */
        !          1156:                        ftentox_rr (dreg, sreg);
        !          1157:                        break;
        !          1158:                        case 0x14: /* FLOGN */
        !          1159:                        flogN_rr (dreg, sreg);
        !          1160:                        break;
        !          1161:                        case 0x15: /* FLOG10 */
        !          1162:                        flog10_rr (dreg, sreg);
        !          1163:                        break;
        !          1164:                        case 0x16: /* FLOG2 */
        !          1165:                        flog2_rr (dreg, sreg);
        !          1166:                        break;
        !          1167:                        case 0x18: /* FABS */
        !          1168:                        fabs_rr (dreg, sreg);
        !          1169:                        break;
        !          1170:                        case 0x19: /* FCOSH */
        !          1171:                        fcosh_rr (dreg, sreg);
        !          1172:                        break;
        !          1173:                        case 0x1a: /* FNEG */
        !          1174:                        fneg_rr (dreg, sreg);
        !          1175:                        break;
        !          1176:                        case 0x1c: /* FACOS */
1.1       root     1177: #if USE_X86_FPUCW
1.1.1.2 ! root     1178:                        if ((regs.fpcr & 0x30) != 0x10) { /* use round to zero */
        !          1179:                                mov_l_ri (S1, (regs.fpcr & 0xC0) | 0x10);
        !          1180:                                fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1181:                                facos_rr (dreg, sreg);
        !          1182:                                mov_l_rm (S1, (uae_u32) &regs.fpcr);
        !          1183:                                and_l_ri (S1, 0xf0); /* restore control word */
        !          1184:                                fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1185:                                break;
        !          1186:                        }
1.1       root     1187: #endif
1.1.1.2 ! root     1188:                        facos_rr (dreg, sreg);
        !          1189:                        break;
        !          1190:                        case 0x1d: /* FCOS */
        !          1191:                        fcos_rr (dreg, sreg);
        !          1192:                        break;
        !          1193:                        case 0x1e: /* FGETEXP */
        !          1194:                        fgetexp_rr (dreg, sreg);
        !          1195:                        break;
        !          1196:                        case 0x1f: /* FGETMAN */
        !          1197:                        fgetman_rr (dreg, sreg);
        !          1198:                        break;
        !          1199:                        case 0x20: /* FDIV */
        !          1200:                        fdiv_rr (dreg, sreg);
        !          1201:                        break;
        !          1202:                        case 0x21: /* FMOD */
        !          1203:                        frem_rr (dreg, sreg);
        !          1204:                        break;
        !          1205:                        case 0x22: /* FADD */
        !          1206:                        fadd_rr (dreg, sreg);
        !          1207:                        break;
        !          1208:                        case 0x23: /* FMUL */
        !          1209:                        fmul_rr (dreg, sreg);
        !          1210:                        break;
        !          1211:                        case 0x24: /* FSGLDIV  is not exactly the same as FSDIV, */
        !          1212:                        /* because both operands should be SINGLE precision, too */
        !          1213:                        case 0x60: /* FSDIV */
        !          1214:                        fdiv_rr (dreg, sreg);
        !          1215:                        if (!currprefs.fpu_strict) /* faster, but less strict rounding */
        !          1216:                                break;
1.1       root     1217: #if USE_X86_FPUCW
1.1.1.2 ! root     1218:                        if ((regs.fpcr & 0xC0) == 0x40) /* if SINGLE precision */
        !          1219:                                break;
1.1       root     1220: #endif
1.1.1.2 ! root     1221:                        fcuts_r (dreg);
        !          1222:                        break;
        !          1223:                        case 0x25: /* FREM */
        !          1224:                        frem1_rr (dreg, sreg);
        !          1225:                        break;
        !          1226:                        case 0x26: /* FSCALE */
        !          1227:                        fscale_rr (dreg, sreg);
        !          1228:                        break;
        !          1229:                        case 0x27: /* FSGLMUL is not exactly the same as FSMUL, */
        !          1230:                        /* because both operands should be SINGLE precision, too */
        !          1231:                        case 0x63: /* FSMUL */
        !          1232:                        fmul_rr (dreg, sreg);
        !          1233:                        if (!currprefs.fpu_strict) /* faster, but less strict rounding */
        !          1234:                                break;
1.1       root     1235: #if USE_X86_FPUCW
1.1.1.2 ! root     1236:                        if ((regs.fpcr & 0xC0) == 0x40) /* if SINGLE precision */
        !          1237:                                break;
1.1       root     1238: #endif
1.1.1.2 ! root     1239:                        fcuts_r (dreg);
        !          1240:                        break;
        !          1241:                        case 0x28: /* FSUB */
        !          1242:                        fsub_rr (dreg, sreg);
        !          1243:                        break;
        !          1244:                        case 0x30: /* FSINCOS */
        !          1245:                        case 0x31:
        !          1246:                        case 0x32:
        !          1247:                        case 0x33:
        !          1248:                        case 0x34:
        !          1249:                        case 0x35:
        !          1250:                        case 0x36:
        !          1251:                        case 0x37:
        !          1252:                        if (dreg == (extra & 7))
        !          1253:                                fsin_rr (dreg, sreg);
        !          1254:                        else
        !          1255:                                fsincos_rr (dreg, extra & 7, sreg);
        !          1256:                        break;
        !          1257:                        case 0x38: /* FCMP */
        !          1258:                        fmov_rr (FP_RESULT, dreg);
        !          1259:                        fsub_rr (FP_RESULT, sreg);
        !          1260:                        return;
        !          1261:                        case 0x3a: /* FTST */
        !          1262:                        fmov_rr (FP_RESULT, sreg);
        !          1263:                        return;
        !          1264:                        case 0x40: /* FSMOVE */
        !          1265:                        if (prec == 1 || !currprefs.fpu_strict) {
        !          1266:                                if (sreg != dreg) /* no <EA> */
        !          1267:                                        fmov_rr (dreg, sreg);
        !          1268:                        }
        !          1269:                        else {
        !          1270:                                fmovs_mr ((uae_u32) temp_fp, sreg);
        !          1271:                                fmovs_rm (dreg, (uae_u32) temp_fp);
        !          1272:                        }
        !          1273:                        break;
        !          1274:                        case 0x44: /* FDMOVE */
        !          1275:                        if (prec || !currprefs.fpu_strict) {
        !          1276:                                if (sreg != dreg) /* no <EA> */
        !          1277:                                        fmov_rr (dreg, sreg);
        !          1278:                        }
        !          1279:                        else {
        !          1280:                                fmov_mr ((uae_u32) temp_fp, sreg);
        !          1281:                                fmov_rm (dreg, (uae_u32) temp_fp);
        !          1282:                        }
        !          1283:                        break;
        !          1284:                        case 0x41: /* FSSQRT */
        !          1285:                        fsqrt_rr (dreg, sreg);
        !          1286:                        if (!currprefs.fpu_strict) /* faster, but less strict rounding */
        !          1287:                                break;
1.1       root     1288: #if USE_X86_FPUCW
1.1.1.2 ! root     1289:                        if ((regs.fpcr & 0xC0) == 0x40) /* if SINGLE precision */
        !          1290:                                break;
1.1       root     1291: #endif
1.1.1.2 ! root     1292:                        fcuts_r (dreg);
        !          1293:                        break;
        !          1294:                        case 0x45: /* FDSQRT */
        !          1295:                        if (!currprefs.fpu_strict) { /* faster, but less strict rounding */
        !          1296:                                fsqrt_rr (dreg, sreg);
        !          1297:                                break;
        !          1298:                        }
1.1       root     1299: #if USE_X86_FPUCW
1.1.1.2 ! root     1300:                        if (regs.fpcr & 0xC0) { /* if we don't have EXTENDED precision */
        !          1301:                                if ((regs.fpcr & 0xC0) == 0x80) /* if we have DOUBLE */
        !          1302:                                        fsqrt_rr (dreg, sreg);
        !          1303:                                else { /* if we have SINGLE presision, force DOUBLE */
        !          1304:                                        mov_l_ri (S1, (regs.fpcr & 0x30) | 0x80);
        !          1305:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1306:                                        fsqrt_rr (dreg, sreg);
        !          1307:                                        mov_l_rm (S1, (uae_u32) &regs.fpcr);
        !          1308:                                        and_l_ri (S1, 0xf0); /* restore control word */
        !          1309:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1310:                                }
        !          1311:                                break;
        !          1312:                        }
1.1       root     1313: #endif         /* in case of EXTENDED precision, just reduce the result to DOUBLE */
1.1.1.2 ! root     1314:                        fsqrt_rr (dreg, sreg);
        !          1315:                        fcut_r (dreg);
        !          1316:                        break;
        !          1317:                        case 0x58: /* FSABS */
        !          1318:                        fabs_rr (dreg, sreg);
        !          1319:                        if (prec != 1 && currprefs.fpu_strict)
        !          1320:                                fcuts_r (dreg);
        !          1321:                        break;
        !          1322:                        case 0x5a: /* FSNEG */
        !          1323:                        fneg_rr (dreg, sreg);
        !          1324:                        if (prec != 1 && currprefs.fpu_strict)
        !          1325:                                fcuts_r (dreg);
        !          1326:                        break;
        !          1327:                        case 0x5c: /* FDABS */
        !          1328:                        fabs_rr (dreg, sreg);
        !          1329:                        if (!prec && currprefs.fpu_strict)
        !          1330:                                fcut_r (dreg);
        !          1331:                        break;
        !          1332:                        case 0x5e: /* FDNEG */
        !          1333:                        fneg_rr (dreg, sreg);
        !          1334:                        if (!prec && currprefs.fpu_strict)
        !          1335:                                fcut_r (dreg);
        !          1336:                        break;
        !          1337:                        case 0x62: /* FSADD */
        !          1338:                        fadd_rr (dreg, sreg);
        !          1339:                        if (!currprefs.fpu_strict) /* faster, but less strict rounding */
        !          1340:                                break;
1.1       root     1341: #if USE_X86_FPUCW
1.1.1.2 ! root     1342:                        if ((regs.fpcr & 0xC0) == 0x40) /* if SINGLE precision */
        !          1343:                                break;
1.1       root     1344: #endif
1.1.1.2 ! root     1345:                        fcuts_r (dreg);
        !          1346:                        break;
        !          1347:                        case 0x64: /* FDDIV */
        !          1348:                        if (!currprefs.fpu_strict) { /* faster, but less strict rounding */
        !          1349:                                fdiv_rr (dreg, sreg);
        !          1350:                                break;
        !          1351:                        }
1.1       root     1352: #if USE_X86_FPUCW
1.1.1.2 ! root     1353:                        if (regs.fpcr & 0xC0) { /* if we don't have EXTENDED precision */
        !          1354:                                if ((regs.fpcr & 0xC0) == 0x80) /* if we have DOUBLE */
        !          1355:                                        fdiv_rr (dreg, sreg);
        !          1356:                                else { /* if we have SINGLE presision, force DOUBLE */
        !          1357:                                        mov_l_ri (S1, (regs.fpcr & 0x30) | 0x80);
        !          1358:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1359:                                        fdiv_rr (dreg, sreg);
        !          1360:                                        mov_l_rm (S1, (uae_u32) &regs.fpcr);
        !          1361:                                        and_l_ri (S1, 0xf0); /* restore control word */
        !          1362:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1363:                                }
        !          1364:                                break;
        !          1365:                        }
1.1       root     1366: #endif         /* in case of EXTENDED precision, just reduce the result to DOUBLE */
1.1.1.2 ! root     1367:                        fdiv_rr (dreg, sreg);
        !          1368:                        fcut_r (dreg);
        !          1369:                        break;
        !          1370:                        case 0x66: /* FDADD */
        !          1371:                        if (!currprefs.fpu_strict) { /* faster, but less strict rounding */
        !          1372:                                fadd_rr (dreg, sreg);
        !          1373:                                break;
        !          1374:                        }
1.1       root     1375: #if USE_X86_FPUCW
1.1.1.2 ! root     1376:                        if (regs.fpcr & 0xC0) { /* if we don't have EXTENDED precision */
        !          1377:                                if ((regs.fpcr & 0xC0) == 0x80) /* if we have DOUBLE */
        !          1378:                                        fadd_rr (dreg, sreg);
        !          1379:                                else { /* if we have SINGLE presision, force DOUBLE */
        !          1380:                                        mov_l_ri (S1, (regs.fpcr & 0x30) | 0x80);
        !          1381:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1382:                                        fadd_rr (dreg, sreg);
        !          1383:                                        mov_l_rm (S1, (uae_u32) &regs.fpcr);
        !          1384:                                        and_l_ri (S1, 0xf0); /* restore control word */
        !          1385:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1386:                                }
        !          1387:                                break;
        !          1388:                        }
1.1       root     1389: #endif         /* in case of EXTENDED precision, just reduce the result to DOUBLE */
1.1.1.2 ! root     1390:                        fadd_rr (dreg, sreg);
        !          1391:                        fcut_r (dreg);
        !          1392:                        break;
        !          1393:                        case 0x67: /* FDMUL */
        !          1394:                        if (!currprefs.fpu_strict) { /* faster, but less strict rounding */
        !          1395:                                fmul_rr (dreg, sreg);
        !          1396:                                break;
        !          1397:                        }
1.1       root     1398: #if USE_X86_FPUCW
1.1.1.2 ! root     1399:                        if (regs.fpcr & 0xC0) { /* if we don't have EXTENDED precision */
        !          1400:                                if ((regs.fpcr & 0xC0) == 0x80) /* if we have DOUBLE */
        !          1401:                                        fmul_rr (dreg, sreg);
        !          1402:                                else { /* if we have SINGLE presision, force DOUBLE */
        !          1403:                                        mov_l_ri (S1, (regs.fpcr & 0x30) | 0x80);
        !          1404:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1405:                                        fmul_rr (dreg, sreg);
        !          1406:                                        mov_l_rm (S1, (uae_u32) &regs.fpcr);
        !          1407:                                        and_l_ri (S1, 0xf0); /* restore control word */
        !          1408:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1409:                                }
        !          1410:                                break;
        !          1411:                        }
1.1       root     1412: #endif         /* in case of EXTENDED precision, just reduce the result to DOUBLE */
1.1.1.2 ! root     1413:                        fmul_rr (dreg, sreg);
        !          1414:                        fcut_r (dreg);
        !          1415:                        break;
        !          1416:                        case 0x68: /* FSSUB */
        !          1417:                        fsub_rr (dreg, sreg);
        !          1418:                        if (!currprefs.fpu_strict) /* faster, but less strict rounding */
        !          1419:                                break;
1.1       root     1420: #if USE_X86_FPUCW
1.1.1.2 ! root     1421:                        if ((regs.fpcr & 0xC0) == 0x40) /* if SINGLE precision */
        !          1422:                                break;
1.1       root     1423: #endif
1.1.1.2 ! root     1424:                        fcuts_r (dreg);
        !          1425:                        break;
        !          1426:                        case 0x6c: /* FDSUB */
        !          1427:                        if (!currprefs.fpu_strict) { /* faster, but less strict rounding */
        !          1428:                                fsub_rr (dreg, sreg);
        !          1429:                                break;
        !          1430:                        }
1.1       root     1431: #if USE_X86_FPUCW
1.1.1.2 ! root     1432:                        if (regs.fpcr & 0xC0) { /* if we don't have EXTENDED precision */
        !          1433:                                if ((regs.fpcr & 0xC0) == 0x80) /* if we have DOUBLE */
        !          1434:                                        fsub_rr (dreg, sreg);
        !          1435:                                else { /* if we have SINGLE presision, force DOUBLE */
        !          1436:                                        mov_l_ri (S1, (regs.fpcr & 0x30) | 0x80);
        !          1437:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1438:                                        fsub_rr (dreg, sreg);
        !          1439:                                        mov_l_rm (S1, (uae_u32) &regs.fpcr);
        !          1440:                                        and_l_ri (S1, 0xf0); /* restore control word */
        !          1441:                                        fldcw_m_indexed (S1, (uae_u32) x86_fpucw);
        !          1442:                                }
        !          1443:                                break;
        !          1444:                        }
1.1       root     1445: #endif         /* in case of EXTENDED precision, just reduce the result to DOUBLE */
1.1.1.2 ! root     1446:                        fsub_rr (dreg, sreg);
        !          1447:                        fcut_r (dreg);
        !          1448:                        break;
        !          1449:                        default:
        !          1450:                        FAIL (1);
        !          1451:                        return;
        !          1452:                }
        !          1453:                fmov_rr (FP_RESULT, dreg);
        !          1454:                return;
        !          1455:                default:
        !          1456:                write_log (_T ("Unsupported JIT-FPU instruction: 0x%04x %04x\n"), opcode, extra);
        !          1457:                FAIL (1);
1.1       root     1458:                return;
                   1459:        }
                   1460: }
                   1461: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.