First post, by superfury
I'm trying to get the (I)MUL test to pass it's flags test, but for some reason it won't give the correct results.
Different MUL instructions:
80186+ IMUL:
void CPU186_OP69()
{
if (modrm_check16(¶ms,1,1)) return; //Abort on fault!
temp1.val32 = modrm_read16(¶ms,1);
temp2.val32 = immw;
modrm_decode16(¶ms,&info,0);
debugger_setcommand("IMUL %s,%04X",info.text,temp2);
if ((temp1.val32 &0x8000)==0x8000) temp1.val32 |= 0xFFFF0000;
if ((temp2.val32 &0x8000)==0x8000) temp2.val32 |= 0xFFFF0000;
temp3.val32 = ((temp1.val32*temp2.val32)&0xFFFFFFFF);
REG_AX = temp3.val16;
REG_DX = temp3.val16high;
if (((temp1.val32>>15)==0) || ((temp1.val32>>15)==0x1FFFF)) FLAGW_OF(0);
else FLAGW_OF(1);
FLAGW_CF(FLAG_OF); //OF=CF!
}
8086 MULB:
case 4: //MULB
tempAL = REG_AL; //Save a backup for calculating cycles!
temp1.val32 = (uint32_t)oper1b * (uint32_t)REG_AL;
REG_AX = temp1.val16 & 0xFFFF;
if (((temp1.val16&0xFF80)==0) || ((temp1.val16&0xFF80)==0xFF80))
{
FLAGW_OF(0); //Both zeroed!
}
else FLAGW_OF(1); //Set due to overflow!
FLAGW_CF(FLAG_OF); //Same!
tempAL = FLAG_ZF; //Backup!
flag_szp8(REG_AL);
if (EMULATED_CPU==CPU_8086) //8086 only?
{
FLAGW_ZF(tempAL); //Restore Zero flag!
if (REG_AX) FLAGW_ZF(0); //8086/8088 clears the Zero flag when not zero only. Undocumented bug!
}
if (MODRM_EA(params)) //Memory?
{
CPU[activeCPU].cycles_OP = 76+MODRM_EA(params); //Mem max!
}
else //Register?
{
CPU[activeCPU].cycles_OP = 70; //Reg!
}
if (NumberOfSetBits(tempAL)>1) //More than 1 bit set?
{
CPU[activeCPU].cycles_OP += NumberOfSetBits(tempAL) - 1; //1 cycle for all bits more than 1 bit set!
}
break;
8086 IMULB:
case 5: //IMULB
oper1 = oper1b;
temp1.val32 = REG_AL;
temp2.val32 = oper1b;
//Sign extend!
if ((temp1.val8 & 0x80) == 0x80) temp1.val32 |= 0xFFFFFF00;
if ((temp2.val8 & 0x80) == 0x80) temp2.val32 |= 0xFFFFFF00;
//Multiply and convert to 16-bit!
temp3.val32s = temp1.val32s; //Load and...
temp3.val32s *= temp2.val32s; //Multiply!
REG_AX = temp3.val16; //Load into AX!
if (((temp1.val16&0xFF80)==0) || ((temp1.val16&0xFF80)==0xFF80))
{
FLAGW_OF(0); //Both zeroed!
}
else FLAGW_OF(1); //Set due to overflow!
FLAGW_CF(FLAG_OF); //Same!
if (EMULATED_CPU==CPU_8086)
{
FLAGW_ZF(0); //Clear ZF!
}
if (MODRM_EA(params)) //Memory?
{
CPU[activeCPU].cycles_OP = 86 + MODRM_EA(params); //Mem max!
}
else //Register?
{
CPU[activeCPU].cycles_OP = 80; //Reg!
}
break;
8086 MULW:
case 4: //MULW
tempAX = REG_AX; //Save a backup for calculating cycles!
temp1.val32 = (uint32_t)oper1 * (uint32_t)REG_AX;
REG_AX = temp1.val16;
REG_DX = temp1.val16high;
if (((temp1.val32>>15)==0) || ((temp1.val32>>15)==0x1FFFF)) FLAGW_OF(0);
else FLAGW_OF(1);
FLAGW_CF(FLAG_OF); //OF=CF!
tempAL = FLAG_ZF; //Backup!
flag_szp16(REG_AX);
if (EMULATED_CPU==CPU_8086)
{
FLAGW_ZF(tempAL); //Restore!
if ((EMULATED_CPU==CPU_8086) && temp1.val32) FLAGW_ZF(0); //8086/8088 clears the Zero flag when not zero only.
}
if (MODRM_EA(params)) //Memory?
{
CPU[activeCPU].cycles_OP = 124 + MODRM_EA(params); //Mem max!
}
else //Register?
{
CPU[activeCPU].cycles_OP = 118; //Reg!
}
if (NumberOfSetBits(tempAX)>1) //More than 1 bit set?
{
CPU[activeCPU].cycles_OP += NumberOfSetBits(tempAX) - 1; //1 cycle for all bits more than 1 bit set!
}
break;
8086 IMULW:
case 5: //IMULW
temp1.val32 = REG_AX;
temp2.val32 = oper1;
//Sign extend!
if (temp1.val16 & 0x8000) temp1.val32 |= 0xFFFF0000;
if (temp2.val16 & 0x8000) temp2.val32 |= 0xFFFF0000;
temp3.val32s = temp1.val32s; //Load and...
temp3.val32s *= temp2.val32s; //Signed multiplication!
REG_AX = temp3.val16; //into register ax
REG_DX = temp3.val16high; //into register dx
if (((temp1.val32>>15)==0) || ((temp1.val32>>15)==0x1FFFF)) FLAGW_OF(0);
else FLAGW_OF(1);
FLAGW_CF(FLAG_OF); //OF=CF!
if (EMULATED_CPU==CPU_8086)
{
FLAGW_ZF(0); //Clear ZF!
}
if (MODRM_EA(params)) //Memory?
{
CPU[activeCPU].cycles_OP = 128 + MODRM_EA(params); //Mem max!
}
else //Register?
{
CPU[activeCPU].cycles_OP = 134; //Reg max!
}
break;
I'm getting the strangest flag errors, as can be seen in the log within the ZIP file(there's two files: debugger.log contains the disassembly, ROM_log.log contains the surrounding wrapper test results).
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io