Annotation of hatari/src/cpu/jit/compemu_fpp.c, revision 1.1.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.