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

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

unix.superglobalmegacorp.com

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