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

unix.superglobalmegacorp.com

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