First post, by superfury
Anyone can see what's going wrong, when calculating the BCD instruction flags?
//BCD opcodes!
byte CPU8086_internal_DAA()
{
word ALVAL, oldCF;
CPUPROT1
oldCF = FLAG_CF; //Save old Carry!
ALVAL = (word)REG_AL;
if (((ALVAL&0xF)>9) || FLAG_AF)
{
oper1 = ALVAL+6;
ALVAL = (oper1&0xFF);
FLAGW_CF((((oper1&0xFF00)>0)?1:0)|FLAG_CF);
FLAGW_AF(1);
}
else FLAGW_AF(0);
if (((REG_AL)>0x99) || oldCF)
{
ALVAL += 0x60;
FLAGW_CF(1);
}
else
{
FLAGW_CF(0);
}
REG_AL = (byte)(ALVAL&0xFF); //Write the value back to AL!
flag_szp8(REG_AL);
//if (ALVAL&0xFF00) FLAGW_OF(1); else FLAGW_OF(0); //Undocumented: Overflow flag!
CPUPROT2
if (CPU_apply286cycles()==0) //No 80286+ cycles instead?
{
CPU[activeCPU].cycles_OP += 4; //Timings!
}
return 0;
}
byte CPU8086_internal_DAS()
{
INLINEREGISTER byte tempCF, tempAL;
INLINEREGISTER word bigAL;
bigAL = (word)(tempAL = REG_AL);
tempCF = FLAG_CF; //Save old values!
CPUPROT1
if (((bigAL&0xF)>9) || FLAG_AF)
{
oper1 = bigAL = REG_AL-6;
REG_AL = oper1&255;
FLAGW_CF(tempCF|((oper1&0xFF00)>0));
FLAGW_AF(1);
}
else FLAGW_AF(0);
if ((tempAL>0x99) || tempCF)
{
bigAL -= 0x60;
REG_AL = (byte)(bigAL&0xFF);
FLAGW_CF(1);
}
else
{
FLAGW_CF(0);
}
flag_szp8(REG_AL);
//if (bigAL&0xFF00) FLAGW_OF(1); else FLAGW_OF(0); //Undocumented: Overflow flag!
CPUPROT2
if (CPU_apply286cycles()==0) //No 80286+ cycles instead?
{
CPU[activeCPU].cycles_OP += 4; //Timings!
}
return 0;
}
byte CPU8086_internal_AAA()
{
CPUPROT1
if (EMULATED_CPU<CPU_80286) //Before new CPU?
{
if (((REG_AL&0xF)>9) || FLAG_AF)
{
REG_AL += 6;
++REG_AH;
FLAGW_AF(1);
FLAGW_CF(1);
}
else
{
FLAGW_AF(0);
FLAGW_CF(0);
}
REG_AL &= 0xF;
}
else //Newer CPUs?
{
if (((REG_AL&0xF)>9) || FLAG_AF)
{
REG_AX += 0x0106;
FLAGW_AF(1);
FLAGW_CF(1);
}
else
{
FLAGW_AF(0);
FLAGW_CF(0);
}
REG_AL &= 0xF;
}
//flag_szp8(REG_AL); //Basic flags!
flag_p8(REG_AL); //Parity is affected!
if (EMULATED_CPU<CPU_80286) //Before new CPU?
{
FLAGW_ZF((REG_AL==0)?1:0); //Zero is affected!
}
else
{
FLAGW_ZF((REG_AL==0)?1:0); //Zero is affected!
FLAGW_SF(0); //Clear Sign!
}
//z=s=p=o=?
CPUPROT2
if (CPU_apply286cycles()==0) //No 80286+ cycles instead?
{
CPU[activeCPU].cycles_OP += 4; //Timings!
}
return 0;
}
byte CPU8086_internal_AAS()
{
CPUPROT1
if (EMULATED_CPU<CPU_80286) //Before new CPU?
{
if (((REG_AL&0xF)>9) || FLAG_AF)
{
REG_AL -= 6;
--REG_AH;
FLAGW_AF(1);
FLAGW_CF(1);
}
else
{
FLAGW_AF(0);
FLAGW_CF(0);
}
REG_AL &= 0xF;
}
else //Newer CPUs?
{
if (((REG_AL&0xF)>9) || FLAG_AF)
{
REG_AX -= 0x0106;
FLAGW_AF(1);
FLAGW_CF(1);
}
else
{
FLAGW_AF(0);
FLAGW_CF(0);
}
REG_AL &= 0xF;
}
//flag_szp8(REG_AL); //Basic flags!
flag_p8(REG_AL); //Parity is affected!
if (EMULATED_CPU<CPU_80286) //Before new CPU?
{
FLAGW_ZF((REG_AL==0)?1:0); //Zero is affected!
}
else
{
FLAGW_ZF((REG_AL==0)?1:0); //Zero is affected!
FLAGW_SF(0); //Sign is cleared!
}
//z=s=o=p=?
CPUPROT2
if (CPU_apply286cycles()==0) //No 80286+ cycles instead?
{
CPU[activeCPU].cycles_OP += 4; //Timings!
}
return 0;
}
OPTINLINE byte CPU8086_internal_AAM(byte data)
{
CPUPROT1
if ((!data) && (CPU[activeCPU].instructionstep==0)) //First step?
{
CPU[activeCPU].cycles_OP += 1; //Timings always!
++CPU[activeCPU].instructionstep; //Next step after we're done!
CPU[activeCPU].executed = 0; //Not executed yet!
return 1;
}
word quotient, remainder;
byte error, applycycles;
CPU8086_internal_DIV(REG_AL,data,"ient,&remainder,&error,8,2,6,&applycycles);
if (error) //Error occurred?
{
CPU_exDIV0(); //Raise error that's requested!
return 1;
}
else //Valid result?
{
REG_AH = (byte)(quotient&0xFF);
REG_AL = (byte)(remainder&0xFF);
//Flags are set on newer CPUs according to the MOD operation: Sign, Zero and Parity are set according to the mod operation(AL) and Overflow, Carry and Auxiliary carry are cleared.
flag_szp8(REG_AL); //Result of MOD instead!
FLAGW_OF(0); FLAGW_CF(0); FLAGW_AF(0); //Clear these!
//C=O=A=?
}
CPUPROT2
return 0;
}
OPTINLINE byte CPU8086_internal_AAD(byte data)
{
CPUPROT1
oper2 = (word)REG_AL; //What to add!
REG_AX = (REG_AH*data); //AAD
oper1 = REG_AX; //Load for addition!
op_add16(); //Add, 16-bit, including flags!
REG_AX = res16; //The result to load!
REG_AH = 0; //AH is cleared!
//C=O=A=?
CPUPROT2
if (CPU_apply286cycles()==0) //No 80286+ cycles instead?
{
CPU[activeCPU].cycles_OP += 60; //Timings!
}
return 0;
}
The 80186 test suite fails on these, expecting the Overflow flag(???) to be set in some of these cases, as well as the auxiliary flag not to be set?
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io