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

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

unix.superglobalmegacorp.com

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