📄 virtual8086modeublock.java
字号:
case STORE0_FPUCW: fpu.setControl(reg0); break;
case LOAD0_FPUCW: reg0 = fpu.getControl(); break;
case STORE0_FPUSW: fpu.setStatus(reg0); break;
case LOAD0_FPUSW: reg0 = fpu.getStatus(); break;
case FCOM: {
int newcode = 0xd;
if (Double.isNaN(freg0) || Double.isNaN(freg1))
fpu.setInvalidOperation();
else {
if (freg0 > freg1) newcode = 0;
else if (freg0 < freg1) newcode = 1;
else newcode = 8;
}
fpu.conditionCode &= 2;
fpu.conditionCode |= newcode;
} break;
case FUCOM: {
int newcode = 0xd;
if (!(Double.isNaN(freg0) || Double.isNaN(freg1)))
{
if (freg0 > freg1) newcode = 0;
else if (freg0 < freg1) newcode = 1;
else newcode = 8;
}
fpu.conditionCode &= 2;
fpu.conditionCode |= newcode;
} break;
case FPOP: fpu.pop(); break;
case FPUSH: fpu.push(freg0); break;
case FCHS: freg0 = -freg0; break;
case FABS: freg0 = Math.abs(freg0); break;
case FADD: {
if ((freg0 == Double.NEGATIVE_INFINITY && freg1 == Double.POSITIVE_INFINITY) || (freg0 == Double.POSITIVE_INFINITY && freg1 == Double.NEGATIVE_INFINITY))
fpu.setInvalidOperation();
freg0 = freg0 + freg1;
} break;
case FMUL: {
if ((Double.isInfinite(freg0) && (freg1 == 0.0)) || (Double.isInfinite(freg1) && (freg0 == 0.0)))
fpu.setInvalidOperation();
freg0 = freg0 * freg1;
} break;
case FSUB: {
if ((freg0 == Double.NEGATIVE_INFINITY && freg1 == Double.NEGATIVE_INFINITY) || (freg0 == Double.POSITIVE_INFINITY && freg1 == Double.POSITIVE_INFINITY))
fpu.setInvalidOperation();
freg0 = freg0 - freg1;
} break;
case FDIV: {
if (((freg0 == 0.0) && (freg1 == 0.0)) || (Double.isInfinite(freg0) && Double.isInfinite(freg1)))
fpu.setInvalidOperation();
if ((freg1 == 0.0) && !Double.isNaN(freg0) && !Double.isInfinite(freg0))
fpu.setZeroDivide();
freg0 = freg0 / freg1;
} break;
case FSQRT: {
if (freg0 < 0)
fpu.setInvalidOperation();
freg0 = Math.sqrt(freg0);
} break;
case FSIN: {
if (Double.isInfinite(freg0))
fpu.setInvalidOperation();
if ((freg0 > Long.MAX_VALUE) || (freg0 < Long.MIN_VALUE))
fpu.conditionCode |= 4; // set C2
else
freg0 = Math.sin(freg0);
} break;
case FCOS: {
if (Double.isInfinite(freg0))
fpu.setInvalidOperation();
if ((freg0 > Long.MAX_VALUE) || (freg0 < Long.MIN_VALUE))
fpu.conditionCode |= 4; // set C2
else
freg0 = Math.cos(freg0);
} break;
case FBCD2F: {
long n = 0;
long decade = 1;
for (int i = 0; i < 9; i++)
{
byte b = seg0.getByte(addr0 + i);
n += (b & 0xf) * decade;
decade *= 10;
n += ((b >> 4) & 0xf) * decade;
decade *= 10;
}
byte sign = seg0.getByte(addr0 + 9);
double m = (double)n;
if (sign < 0)
m *= -1.0;
freg0 = m;
} break;
case FF2BCD: {
long n = (long)Math.abs(freg0);
long decade = 1;
for (int i = 0; i < 9; i++)
{
int val = (int) ((n % (decade * 10)) / decade);
byte b = (byte) val;
decade *= 10;
val = (int) ((n % (decade * 10)) / decade);
b |= (val << 4);
seg0.setByte(addr0 + i, b);
}
seg0.setByte(addr0 + 9, (freg0 < 0) ? (byte)0x80 : (byte)0x00);
} break;
case FPATAN: freg0 = Math.atan2(freg1, freg0); break;
case FPREM: {
int d = Math.getExponent(freg0) - Math.getExponent(freg1);
if (d < 64)
{
// full remainder
fpu.conditionCode &= ~4; // clear C2
freg0 = freg0 % freg1;
// compute least significant bits -> C0 C3 C1
long i = (long)Math.rint(freg0 / freg1);
fpu.conditionCode &= 4;
if ((i & 1) != 0) fpu.conditionCode |= 2;
if ((i & 2) != 0) fpu.conditionCode |= 8;
if ((i & 4) != 0) fpu.conditionCode |= 1;
}
else
{
// partial remainder
fpu.conditionCode |= 4; // set C2
int n = 63; // implementation dependent in manual
double f = Math.pow(2.0, (double)(d - n));
double z = (freg0 / freg1) / f;
double qq = (z < 0) ? Math.ceil(z) : Math.floor(z);
freg0 = freg0 - (freg1 * qq * f);
}
} break;
case FPREM1: {
int d = Math.getExponent(freg0) - Math.getExponent(freg1);
if (d < 64)
{
// full remainder
fpu.conditionCode &= ~4; // clear C2
double z = Math.IEEEremainder(freg0, freg1);
// compute least significant bits -> C0 C3 C1
long i = (long)Math.rint(freg0 / freg1);
fpu.conditionCode &= 4;
if ((i & 1) != 0) fpu.conditionCode |= 2;
if ((i & 2) != 0) fpu.conditionCode |= 8;
if ((i & 4) != 0) fpu.conditionCode |= 1;
fpu.setST(0, z);
}
else
{
// partial remainder
fpu.conditionCode |= 4; // set C2
int n = 63; // implementation dependent in manual
double f = Math.pow(2.0, (double)(d - n));
double z = (freg0 / freg1) / f;
double qq = (z < 0) ? Math.ceil(z) : Math.floor(z);
freg0 = freg0 - (freg1 * qq * f);
}
} break;
case FPTAN: {
if ((freg0 > Math.pow(2.0, 63.0)) || (freg0 < -1.0*Math.pow(2.0, 63.0))) {
if (Double.isInfinite(freg0))
fpu.setInvalidOperation();
fpu.conditionCode |= 4;
} else
{
fpu.conditionCode &= ~4;
freg0 = Math.tan(freg0);
}
} break;
case FSCALE: freg0 = Math.scalb(freg0, (int) freg1); break;
// case FSINCOS: {
// freg1 = sin(freg0);
// freg0 = cos(freg0);
// } break;
case FXTRACT: {
int e = Math.getExponent(freg0);
freg1 = (double) e;
freg0 = Math.scalb(freg0, -e);
} break;
// case FYL2X: {
// freg0 = freg1 * Math.log(freg0)/Math.log(2);
// } break;
// case FYL2XP1: {
// freg0 = freg1 * Math.log1p(freg0)/Math.log(2);
// } break;
case FRNDINT: {
if (Double.isInfinite(freg0))
break; // preserve infinities
switch(fpu.getRoundingControl())
{
case FpuState.FPU_ROUNDING_CONTROL_EVEN:
freg0 = Math.rint(freg0);
break;
case FpuState.FPU_ROUNDING_CONTROL_DOWN:
freg0 = Math.floor(freg0);
break;
case FpuState.FPU_ROUNDING_CONTROL_UP:
freg0 = Math.ceil(freg0);
break;
case FpuState.FPU_ROUNDING_CONTROL_TRUNCATE:
freg0 = Math.signum(freg0) * Math.floor(Math.abs(freg0));
break;
default:
throw new IllegalStateException("Invalid rounding control value");
}
reg0 = (int)freg0;
reg0l = (long)freg0;
} break;
case FCHECK0: checkResult(freg0); break;
case FCHECK1: checkResult(freg1); break;
case FINIT: fpu.init(); break;
// case FSAVE_108: {
// seg0.setDoubleWord(addr0, fpu.getControl() & 0xffff);
// seg0.setDoubleWord(addr0 + 4, fpu.getStatus() & 0xffff);
// seg0.setDoubleWord(addr0 + 8, fpu.getTagWord() & 0xffff);
// seg0.setDoubleWord(addr0 + 12, 0 /* fpu.getIP() */);
// seg0.setDoubleWord(addr0 + 16, 0 /* opcode + selector*/);
// seg0.setDoubleWord(addr0 + 20, 0 /* operand pntr */);
// seg0.setDoubleWord(addr0 + 24, 0 /* more operand pntr */);
// for (int i = 0; i < 8; i++) {
// byte[] extended = FpuState64.doubleToExtended(fpu.ST(i), false /* this is WRONG!!!!!!! */);
// for (int j = 0; j < 10; j++)
// seg0.setByte(addr0 + 28 + j + (10 * i), extended[j]);
// }
// fpu.init();
// } break;
default: throw new IllegalStateException("Unknown uCode " + microcodes[position - 1]);
}
} catch (ProcessorException e) {
throw e;
} finally {
//copy local variables back to instance storage
transferSeg0 = seg0;
transferAddr0 = addr0;
transferReg0 = reg0;
transferReg1 = reg1;
transferReg2 = reg2;
transferReg0l = reg0l;
transferFReg0 = freg0;
transferFReg1 = freg1;
transferEipUpdated = eipUpdated;
transferPosition = position;
}
}
public int execute(Processor cpu)
{
this.fpu = cpu.fpu;
this.cpu = cpu;
Segment seg0 = null;
int addr0 = 0;
int reg0 = 0, reg1 = 0, reg2 = 0;
long reg0l = 0;
double freg0 = 0, freg1 = 0;
executeCount = this.getX86Count();
boolean eipUpdated = false;
int position = 0;
try
{
while (position < microcodes.length) {
if (uCodeXferLoaded)
{
uCodeXferLoaded = false;
reg0 = uCodeXferReg0;
reg1 = uCodeXferReg1;
reg2 = uCodeXferReg2;
}
switch (microcodes[position++]) {
case MEM_RESET: addr0 = 0; seg0 = null; break; //4653406
case ADDR_MASK16: addr0 &= 0xffff; break; //4653406
case EIP_UPDATE: if (!eipUpdated) { //4253320
eipUpdated = true;
cpu.eip += cumulativeX86Length[position - 1];
} break;
case ADDR_IB: addr0 += ((byte)microcodes[position++]); break; //3832219
case PUSH_O16_A16: push_o16_a16((short)reg0); break; //3221577
case LOAD_SEG_SS: seg0 = cpu.ss; break; //2739696
case LOAD0_AX: reg0 = cpu.eax & 0xffff; break; //2718333
case ADDR_BP: addr0 += ((short)cpu.ebp); break; //2701629
case LOAD0_IB: reg0 = microcodes[position++] & 0xff; break; //2567113
case LOAD0_MEM_WORD: reg0 = 0xffff & seg0.getWord(addr0); break; //2352051
case STORE1_ESP: cpu.esp = reg1; break; //2252894
case POP_O16_A16: //2251454
reg1 = (cpu.esp & ~0xffff) | ((cpu.esp + 2) & 0xffff);
if ((microcodes[position] == STORE0_SS))
cpu.eflagsInterruptEnable = false;
reg0 = cpu.ss.getWord(cpu.esp & 0xffff);
break;
case STORE0_AX: cpu.eax = (cpu.eax & ~0xffff) | (reg0 & 0xffff); break; //2211780
case LOAD0_IW: reg0 = microcodes[position++] & 0xffff; break; //1748064
case LOAD_SEG_DS: seg0 = cpu.ds; break; //1556141
case STORE0_BX: cpu.ebx = (cpu.ebx & ~0xffff) | (reg0 & 0xffff); break; //1295862
case SUB: reg2 = reg0; reg0 = reg2 - reg1; break; //1166414
case STORE0_BP: cpu.ebp = (cpu.ebp & ~0xffff) | (reg0 & 0xffff); break; //1077742
case ADDR_BX: addr0 += ((short)cpu.ebx); break; //1018423
case LOAD0_SP: reg0 = cpu.esp & 0xffff; break; //1017910
case ADD: reg2 = reg0; reg0 = reg2 + reg1; break; //1004121
case STORE0_MEM_WORD: seg0.setWord(addr0, (short)reg0); break; //896323
case LOAD0_MEM_BYTE: reg0 = 0xff & seg0.getByte(addr0); break; //839821
case JNZ_O8: jnz_o8((byte)reg0); break; //837018
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -