Added group d9, Funky Ball doesn't moan anymore so let's stop for now

This commit is contained in:
Angelo Salese 2012-01-03 01:34:47 +00:00
parent 2db950e4a9
commit 54216d4dc3

View File

@ -272,34 +272,90 @@ static void I386OP(fpu_group_d9)(i386_state *cpustate) // Opcode 0xd9
// st(0) -> ea
WRITE32(cpustate,ea,FPU_SINGLE_INT32(ST(0)));
FPU_POP(cpustate);
CYCLES(cpustate,1); // TODO
CYCLES(cpustate,7);
break;
}
case 4: // FLDENV
{
if( cpustate->operand_size ) // 32-bit real/protected mode
{
cpustate->fpu_control_word = READ16(cpustate,ea);
cpustate->fpu_status_word = READ16(cpustate,ea+4);
cpustate->fpu_tag_word = READ16(cpustate,ea+8);
}
else // 16-bit real/protected mode
{
cpustate->fpu_control_word = READ16(cpustate,ea);
cpustate->fpu_status_word = READ16(cpustate,ea+2);
cpustate->fpu_tag_word = READ16(cpustate,ea+4);
}
cpustate->fpu_top = (cpustate->fpu_status_word>>11) & 7;
CYCLES(cpustate,(cpustate->cr[0] & 1) ? 34 : 44);
break;
}
case 5: // FLDCW
{
cpustate->fpu_control_word = READ16(cpustate,ea);
CYCLES(cpustate,1); // TODO
CYCLES(cpustate,4);
break;
}
case 6: // FSTENV
{ // TODO: 32-bit operand size
WRITE16(cpustate,ea, cpustate->fpu_control_word);
WRITE16(cpustate,ea+2, cpustate->fpu_status_word);
WRITE16(cpustate,ea+4, cpustate->fpu_tag_word);
WRITE16(cpustate,ea+6, cpustate->fpu_inst_ptr & 0xffff);
WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
WRITE16(cpustate,ea+10, cpustate->fpu_data_ptr & 0xffff);
WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
CYCLES(cpustate,1); // TODO
{
logerror("x87 FSTENV triggered with mode = %d %02x %02x\n",(cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1,cpustate->cr[0],cpustate->operand_size);
switch((cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1)
{
case 0: // 16-bit real mode
WRITE16(cpustate,ea, cpustate->fpu_control_word);
WRITE16(cpustate,ea+2, cpustate->fpu_status_word);
WRITE16(cpustate,ea+4, cpustate->fpu_tag_word);
WRITE16(cpustate,ea+6, cpustate->fpu_inst_ptr & 0xffff);
//WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
WRITE16(cpustate,ea+10, cpustate->fpu_data_ptr & 0xffff);
//WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
break;
case 1: // 16-bit protected mode
WRITE16(cpustate,ea, cpustate->fpu_control_word);
WRITE16(cpustate,ea+2, cpustate->fpu_status_word);
WRITE16(cpustate,ea+4, cpustate->fpu_tag_word);
WRITE16(cpustate,ea+6, cpustate->fpu_inst_ptr & 0xffff);
WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
WRITE16(cpustate,ea+10, cpustate->fpu_data_ptr & 0xffff);
WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
break;
case 2: // 32-bit real mode
WRITE16(cpustate,ea, cpustate->fpu_control_word);
WRITE16(cpustate,ea+4, cpustate->fpu_status_word);
WRITE16(cpustate,ea+8, cpustate->fpu_tag_word);
WRITE16(cpustate,ea+12, cpustate->fpu_inst_ptr & 0xffff);
//WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
WRITE16(cpustate,ea+20, cpustate->fpu_data_ptr & 0xffff);
//WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
WRITE32(cpustate,ea+24, (cpustate->fpu_data_ptr>>16)<<12);
break;
case 3: // 32-bit protected mode
WRITE16(cpustate,ea, cpustate->fpu_control_word);
WRITE16(cpustate,ea+4, cpustate->fpu_status_word);
WRITE16(cpustate,ea+8, cpustate->fpu_tag_word);
WRITE32(cpustate,ea+12, cpustate->fpu_inst_ptr);
WRITE32(cpustate,ea+16, cpustate->fpu_opcode);
WRITE32(cpustate,ea+20, cpustate->fpu_data_ptr);
WRITE32(cpustate,ea+24, cpustate->fpu_inst_ptr);
break;
}
CYCLES(cpustate,(cpustate->cr[0] & 1) ? 56 : 67);
break;
}
case 7: // FSTCW
{
WRITE16(cpustate,ea, cpustate->fpu_control_word);
CYCLES(cpustate,1); // TODO
CYCLES(cpustate,3);
break;
}
@ -316,7 +372,7 @@ static void I386OP(fpu_group_d9)(i386_state *cpustate) // Opcode 0xd9
{
X87_REG t = ST(modrm & 7);
FPU_PUSH(cpustate,t);
CYCLES(cpustate,1); // TODO
CYCLES(cpustate,4);
break;
}
@ -362,6 +418,21 @@ static void I386OP(fpu_group_d9)(i386_state *cpustate) // Opcode 0xd9
break;
}
case 0x25: // FXAM
{
cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
if(((cpustate->fpu_tag_word>>((cpustate->fpu_top&1)<<1))&3)==3)
cpustate->fpu_status_word |= FPU_C3 | FPU_C0;
else if(ST(0).f == 0.0)
cpustate->fpu_status_word |= FPU_C3;
else
cpustate->fpu_status_word |= FPU_C2;
if(ST(0).f < 0.0)
cpustate->fpu_status_word |= FPU_C1;
CYCLES(cpustate,8);
break;
}
case 0x28: // FLD1
{
X87_REG t;
@ -416,6 +487,7 @@ static void I386OP(fpu_group_d9)(i386_state *cpustate) // Opcode 0xd9
X87_REG t;
t.f = 0.0;
FPU_PUSH(cpustate,t);
/* TODO: tag moves? */
CYCLES(cpustate,4);
break;
}
@ -435,6 +507,85 @@ static void I386OP(fpu_group_d9)(i386_state *cpustate) // Opcode 0xd9
break;
}
case 0x32: // FPTAN
{
X87_REG t;
t.f = 1.0;
ST(0).f = tan(ST(0).f);
FPU_PUSH(cpustate,t);
cpustate->fpu_status_word &= ~(FPU_C2);
/* TODO: source operand out-of-range */
CYCLES(cpustate,235);
break;
}
case 0x33: // FPATAN
{
ST(1).f = atan2(ST(1).f,ST(0).f);
FPU_POP(cpustate);
CYCLES(cpustate,250);
break;
}
case 0x36: // FPDECSTP
{
cpustate->fpu_top -= 1;
cpustate->fpu_top &= 7;
CYCLES(cpustate,1); // TODO
break;
}
case 0x37: // FPINCSTP
{
cpustate->fpu_top += 1;
cpustate->fpu_top &= 7;
CYCLES(cpustate,1); // TODO
break;
}
case 0x38: // FPREM
{
X87_REG t;
if(ST(1).i == 0)
fatalerror("Divide by zero on x87 FPREM opcode");
t.i = ST(0).i / ST(1).i;
ST(0).f = ST(0).f-(ST(1).i*t.f);
cpustate->fpu_status_word &= ~(FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3);
if(t.i & 4)
cpustate->fpu_status_word |= FPU_C0;
if(t.i & 2)
cpustate->fpu_status_word |= FPU_C3;
if(t.i & 1)
cpustate->fpu_status_word |= FPU_C1;
CYCLES(cpustate,100);
break;
}
case 0x3a: // FSQRT
{
ST(0).f = sqrt(ST(0).f);
CYCLES(cpustate,83);
break;
}
case 0x3b: // FSINCOS
{
X87_REG t;
t.f = cos(ST(0).f);
ST(0).f = sin(ST(0).f);
FPU_PUSH(cpustate,t);
cpustate->fpu_status_word &= ~(FPU_C2);
/* TODO: source operand out-of-range */
CYCLES(cpustate,330);
break;
}
case 0x3c: // FRNDINT
{
ST(0) = X87_FROUND(cpustate,ST(0));
@ -442,6 +593,32 @@ static void I386OP(fpu_group_d9)(i386_state *cpustate) // Opcode 0xd9
break;
}
case 0x3d: // FSCALE
{
X87_REG t;
t = ST(1);
ST(0).f = ST(0).f*pow(2.0,t.f);
CYCLES(cpustate,30);
}
case 0x3e: // FSIN
{
ST(0).f = sin(ST(0).f);
cpustate->fpu_status_word &= ~(FPU_C2);
/* TODO: source operand out-of-range */
CYCLES(cpustate,300);
break;
}
case 0x3f: // FCOS
{
ST(0).f = cos(ST(0).f);
cpustate->fpu_status_word &= ~(FPU_C2);
/* TODO: source operand out-of-range */
CYCLES(cpustate,300);
break;
}
default:
fatalerror("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
}