diff --git a/src/cpu/core_dynrec/operators.h b/src/cpu/core_dynrec/operators.h index 221f8b89..2ae94390 100644 --- a/src/cpu/core_dynrec/operators.h +++ b/src/cpu/core_dynrec/operators.h @@ -730,13 +730,13 @@ static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) DRC_FC; static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) { if (!(op2&0x7)) { if (op2&0x18) { - FillFlags(); + FillFlagsNoCFOF(); SETFLAGBIT(CF,op1 & 1); SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7)); } return op1; } - FillFlags(); + FillFlagsNoCFOF(); lf_var1b=op1; lf_var2b=op2&0x07; lf_resb=(lf_var1b << lf_var2b) | (lf_var1b >> (8-lf_var2b)); @@ -755,18 +755,18 @@ static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) DRC_FC; static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) { if (!(op2&0x7)) { if (op2&0x10) { - FillFlags(); + FillFlagsNoCFOF(); SETFLAGBIT(CF,op1>>7); SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1)); } return op1; } - FillFlags(); + FillFlagsNoCFOF(); lf_var1b=op1; lf_var2b=op2&0x07; lf_resb=(lf_var1b >> lf_var2b) | (lf_var1b << (8-lf_var2b)); SETFLAGBIT(CF,lf_resb & 0x80); - if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80); + SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); return lf_resb; } @@ -797,7 +797,7 @@ static Bit8u DRC_CALL_CONV dynrec_rcr_byte(Bit8u op1,Bit8u op2) { lf_var2b=op2%9; lf_resb=(lf_var1b >> lf_var2b) | (cf << (8-lf_var2b)) | (lf_var1b << (9-lf_var2b)); \ SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1); - SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80); + SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); return lf_resb; } else return op1; } @@ -861,12 +861,13 @@ static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) DRC_FC; static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) { if (!(op2&0xf)) { if (op2&0x10) { - FillFlags(); + FillFlagsNoCFOF(); SETFLAGBIT(CF,op1 & 1); + SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15)); } return op1; } - FillFlags(); + FillFlagsNoCFOF(); lf_var1w=op1; lf_var2b=op2&0xf; lf_resw=(lf_var1w << lf_var2b) | (lf_var1w >> (16-lf_var2b)); @@ -885,17 +886,18 @@ static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) DRC_FC; static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) { if (!(op2&0xf)) { if (op2&0x10) { - FillFlags(); + FillFlagsNoCFOF(); SETFLAGBIT(CF,op1>>15); + SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1)); } return op1; } - FillFlags(); + FillFlagsNoCFOF(); lf_var1w=op1; lf_var2b=op2&0xf; lf_resw=(lf_var1w >> lf_var2b) | (lf_var1w << (16-lf_var2b)); SETFLAGBIT(CF,lf_resw & 0x8000); - if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000); + SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); return lf_resw; } @@ -926,7 +928,7 @@ static Bit16u DRC_CALL_CONV dynrec_rcr_word(Bit16u op1,Bit8u op2) { lf_var2b=op2%17; lf_resw=(lf_var1w >> lf_var2b) | (cf << (16-lf_var2b)) | (lf_var1w << (17-lf_var2b)); SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1); - SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000); + SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); return lf_resw; } else return op1; } @@ -989,7 +991,7 @@ static Bit16u DRC_CALL_CONV dynrec_sar_word_simple(Bit16u op1,Bit8u op2) { static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) DRC_FC; static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) { if (!op2) return op1; - FillFlags(); + FillFlagsNoCFOF(); lf_var1d=op1; lf_var2b=op2; lf_resd=(lf_var1d << lf_var2b) | (lf_var1d >> (32-lf_var2b)); @@ -1007,12 +1009,12 @@ static Bit32u DRC_CALL_CONV dynrec_rol_dword_simple(Bit32u op1,Bit8u op2) { static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) DRC_FC; static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) { if (!op2) return op1; - FillFlags(); + FillFlagsNoCFOF(); lf_var1d=op1; lf_var2b=op2; lf_resd=(lf_var1d >> lf_var2b) | (lf_var1d << (32-lf_var2b)); SETFLAGBIT(CF,lf_resd & 0x80000000); - if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000); + SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); return lf_resd; } @@ -1050,7 +1052,7 @@ static Bit32u DRC_CALL_CONV dynrec_rcr_dword(Bit32u op1,Bit8u op2) { lf_resd=(lf_var1d >> lf_var2b) | (cf << (32-lf_var2b)) | (lf_var1d << (33-lf_var2b)); } SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1); - SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000); + SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); return lf_resd; } else return op1; } @@ -1375,7 +1377,7 @@ static void dyn_branchflag_to_reg(BranchTypes btype) { static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) DRC_FC; static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) { - FillFlags(); + FillFlagsNoCFOF(); reg_ax=reg_al*op; SETFLAGBIT(ZF,reg_al == 0); if (reg_ax & 0xff00) { @@ -1389,7 +1391,7 @@ static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) { static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) DRC_FC; static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) { - FillFlags(); + FillFlagsNoCFOF(); reg_ax=((Bit8s)reg_al) * ((Bit8s)op); if ((reg_ax & 0xff80)==0xff80 || (reg_ax & 0xff80)==0x0000) { SETFLAGBIT(CF,false); @@ -1402,7 +1404,7 @@ static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) { static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) DRC_FC; static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) { - FillFlags(); + FillFlagsNoCFOF(); Bitu tempu=(Bitu)reg_ax*(Bitu)op; reg_ax=(Bit16u)(tempu); reg_dx=(Bit16u)(tempu >> 16); @@ -1418,7 +1420,7 @@ static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) { static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) DRC_FC; static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) { - FillFlags(); + FillFlagsNoCFOF(); Bits temps=((Bit16s)reg_ax)*((Bit16s)op); reg_ax=(Bit16s)(temps); reg_dx=(Bit16s)(temps >> 16); @@ -1433,7 +1435,7 @@ static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) { static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) DRC_FC; static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) { - FillFlags(); + FillFlagsNoCFOF(); Bit64u tempu=(Bit64u)reg_eax*(Bit64u)op; reg_eax=(Bit32u)(tempu); reg_edx=(Bit32u)(tempu >> 32); @@ -1449,7 +1451,7 @@ static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) { static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) DRC_FC; static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) { - FillFlags(); + FillFlagsNoCFOF(); Bit64s temps=((Bit64s)((Bit32s)reg_eax))*((Bit64s)((Bit32s)op)); reg_eax=(Bit32u)(temps); reg_edx=(Bit32u)(temps >> 32); @@ -1551,7 +1553,7 @@ static bool DRC_CALL_CONV dynrec_idiv_dword(Bit32u op) { static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) DRC_FC; static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) { - FillFlags(); + FillFlagsNoCFOF(); Bits res=((Bit16s)op1) * ((Bit16s)op2); if ((res>-32768) && (res<32767)) { SETFLAGBIT(CF,false); @@ -1565,7 +1567,7 @@ static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) { static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) DRC_FC; static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) { - FillFlags(); + FillFlagsNoCFOF(); Bit64s res=((Bit64s)((Bit32s)op1))*((Bit64s)((Bit32s)op2)); if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) { SETFLAGBIT(CF,false); diff --git a/src/cpu/flags.cpp b/src/cpu/flags.cpp index f56b876e..d475dfeb 100644 --- a/src/cpu/flags.cpp +++ b/src/cpu/flags.cpp @@ -169,6 +169,18 @@ Bit32u get_AF(void) { return lf_var1w & 0x0f; case t_NEGd: return lf_var1d & 0x0f; + case t_SHLb: + case t_SHRb: + case t_SARb: + return lf_var2b & 0x1f; + case t_SHLw: + case t_SHRw: + case t_SARw: + return lf_var2w & 0x1f; + case t_SHLd: + case t_SHRd: + case t_SARd: + return lf_var2d & 0x1f; case t_ORb: case t_ORw: case t_ORd: @@ -181,15 +193,6 @@ Bit32u get_AF(void) { case t_TESTb: case t_TESTw: case t_TESTd: - case t_SHLb: - case t_SHLw: - case t_SHLd: - case t_SHRb: - case t_SHRw: - case t_SHRd: - case t_SARb: - case t_SARw: - case t_SARd: case t_DSHLw: case t_DSHLd: case t_DSHRw: @@ -386,18 +389,24 @@ Bit32u get_OF(void) { case t_NEGd: return (lf_var1d == 0x80000000); case t_SHLb: - case t_SHRb: return (lf_resb ^ lf_var1b) & 0x80; case t_SHLw: - case t_SHRw: case t_DSHRw: case t_DSHLw: return (lf_resw ^ lf_var1w) & 0x8000; case t_SHLd: - case t_SHRd: case t_DSHRd: case t_DSHLd: return (lf_resd ^ lf_var1d) & 0x80000000; + case t_SHRb: + if ((lf_var2b&0x1f)==1) return (lf_var1b > 0x80); + else return false; + case t_SHRw: + if ((lf_var2b&0x1f)==1) return (lf_var1w > 0x8000); + else return false; + case t_SHRd: + if ((lf_var2b&0x1f)==1) return (lf_var1d > 0x80000000); + else return false; case t_ORb: case t_ORw: case t_ORd: @@ -485,6 +494,7 @@ Bitu FillFlags(void) { #define SETCF(NEWBIT) reg_flags=(reg_flags & ~FLAG_CF)|(NEWBIT); #define SET_FLAG SETFLAGBIT + Bitu FillFlags(void) { switch (lflags.type) { case t_UNKNOWN: @@ -682,6 +692,7 @@ Bitu FillFlags(void) { DOFLAG_SFb; SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); break; case t_SHLw: if (lf_var2b>16) SET_FLAG(CF,false); @@ -690,6 +701,7 @@ Bitu FillFlags(void) { DOFLAG_SFw; SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); break; case t_SHLd: SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1); @@ -697,6 +709,7 @@ Bitu FillFlags(void) { DOFLAG_SFd; SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); break; @@ -720,22 +733,28 @@ Bitu FillFlags(void) { SET_FLAG(CF,(lf_var1b >> (lf_var2b - 1)) & 1); DOFLAG_ZFb; DOFLAG_SFb; - SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); + if ((lf_var2b&0x1f)==1) SET_FLAG(OF,(lf_var1b >= 0x80)); + else SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); break; case t_SHRw: SET_FLAG(CF,(lf_var1w >> (lf_var2b - 1)) & 1); DOFLAG_ZFw; DOFLAG_SFw; - SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); + if ((lf_var2w&0x1f)==1) SET_FLAG(OF,(lf_var1w >= 0x8000)); + else SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); break; case t_SHRd: SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1); DOFLAG_ZFd; DOFLAG_SFd; - SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); + if ((lf_var2d&0x1f)==1) SET_FLAG(OF,(lf_var1d >= 0x80000000)); + else SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); break; @@ -761,6 +780,7 @@ Bitu FillFlags(void) { DOFLAG_SFb; SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); break; case t_SARw: SET_FLAG(CF,(((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1); @@ -768,6 +788,7 @@ Bitu FillFlags(void) { DOFLAG_SFw; SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); break; case t_SARd: SET_FLAG(CF,(((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1); @@ -775,6 +796,7 @@ Bitu FillFlags(void) { DOFLAG_SFd; SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); break; case t_INCb: @@ -859,6 +881,306 @@ Bitu FillFlags(void) { return reg_flags; } +void FillFlagsNoCFOF(void) { + switch (lflags.type) { + case t_UNKNOWN: + return; + case t_ADDb: + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_ADDw: + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_ADDd: + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + case t_ADCb: + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_ADCw: + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_ADCd: + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SBBb: + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_SBBw: + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_SBBd: + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SUBb: + case t_CMPb: + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_SUBw: + case t_CMPw: + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_SUBd: + case t_CMPd: + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_ORb: + SET_FLAG(AF,false); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_ORw: + SET_FLAG(AF,false); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_ORd: + SET_FLAG(AF,false); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_TESTb: + case t_ANDb: + SET_FLAG(AF,false); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_TESTw: + case t_ANDw: + SET_FLAG(AF,false); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_TESTd: + case t_ANDd: + SET_FLAG(AF,false); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_XORb: + SET_FLAG(AF,false); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_XORw: + SET_FLAG(AF,false); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_XORd: + SET_FLAG(AF,false); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SHLb: + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); + break; + case t_SHLw: + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); + break; + case t_SHLd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); + break; + + + case t_DSHLw: + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_DSHLd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SHRb: + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); + break; + case t_SHRw: + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); + break; + case t_SHRd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); + break; + + + case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */ + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_DSHRd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SARb: + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); + break; + case t_SARw: + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); + break; + case t_SARd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); + break; + + case t_INCb: + SET_FLAG(AF,(lf_resb & 0x0f) == 0); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_INCw: + SET_FLAG(AF,(lf_resw & 0x0f) == 0); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_INCd: + SET_FLAG(AF,(lf_resd & 0x0f) == 0); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + case t_DECb: + SET_FLAG(AF,(lf_resb & 0x0f) == 0x0f); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_DECw: + SET_FLAG(AF,(lf_resw & 0x0f) == 0x0f); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_DECd: + SET_FLAG(AF,(lf_resd & 0x0f) == 0x0f); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + case t_NEGb: + SET_FLAG(AF,(lf_resb & 0x0f) != 0); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_NEGw: + SET_FLAG(AF,(lf_resw & 0x0f) != 0); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_NEGd: + SET_FLAG(AF,(lf_resd & 0x0f) != 0); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_DIV: + case t_MUL: + break; + + default: + LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",lflags.type); + break; + } + lflags.type=t_UNKNOWN; +} + void DestroyConditionFlags(void) { lflags.type=t_UNKNOWN; } diff --git a/src/cpu/instructions.h b/src/cpu/instructions.h index 5f3505b4..45b2c795 100644 --- a/src/cpu/instructions.h +++ b/src/cpu/instructions.h @@ -230,13 +230,13 @@ #define ROLB(op1,op2,load,save) \ if (!(op2&0x7)) { \ if (op2&0x18) { \ - FillFlags(); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(CF,op1 & 1); \ SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7)); \ } \ break; \ } \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1b=load(op1); \ lf_var2b=op2&0x07; \ lf_resb=(lf_var1b << lf_var2b) | \ @@ -248,12 +248,13 @@ #define ROLW(op1,op2,load,save) \ if (!(op2&0xf)) { \ if (op2&0x10) { \ - FillFlags(); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(CF,op1 & 1); \ + SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15)); \ } \ break; \ } \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1w=load(op1); \ lf_var2b=op2&0xf; \ lf_resw=(lf_var1w << lf_var2b) | \ @@ -264,7 +265,7 @@ #define ROLD(op1,op2,load,save) \ if (!op2) break; \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1d=load(op1); \ lf_var2b=op2; \ lf_resd=(lf_var1d << lf_var2b) | \ @@ -277,48 +278,49 @@ #define RORB(op1,op2,load,save) \ if (!(op2&0x7)) { \ if (op2&0x10) { \ - FillFlags(); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(CF,op1>>7); \ SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1)); \ } \ break; \ } \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1b=load(op1); \ lf_var2b=op2&0x07; \ lf_resb=(lf_var1b >> lf_var2b) | \ (lf_var1b << (8-lf_var2b)); \ save(op1,lf_resb); \ SETFLAGBIT(CF,lf_resb & 0x80); \ - if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80); + SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); #define RORW(op1,op2,load,save) \ if (!(op2&0xf)) { \ if (op2&0x10) { \ - FillFlags(); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(CF,op1>>15); \ + SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1)); \ } \ break; \ } \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1w=load(op1); \ lf_var2b=op2&0xf; \ lf_resw=(lf_var1w >> lf_var2b) | \ (lf_var1w << (16-lf_var2b)); \ save(op1,lf_resw); \ SETFLAGBIT(CF,lf_resw & 0x8000); \ - if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000); + SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); #define RORD(op1,op2,load,save) \ if (!op2) break; \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1d=load(op1); \ lf_var2b=op2; \ lf_resd=(lf_var1d >> lf_var2b) | \ (lf_var1d << (32-lf_var2b)); \ save(op1,lf_resd); \ SETFLAGBIT(CF,lf_resd & 0x80000000); \ - if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000); + SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); #define RCLB(op1,op2,load,save) \ @@ -376,7 +378,7 @@ (lf_var1b << (9-lf_var2b)); \ save(op1,lf_resb); \ SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1); \ - SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80); \ + SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); \ } #define RCRW(op1,op2,load,save) \ @@ -389,7 +391,7 @@ (lf_var1w << (17-lf_var2b)); \ save(op1,lf_resw); \ SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1); \ - SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000); \ + SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); \ } #define RCRD(op1,op2,load,save) \ @@ -406,7 +408,7 @@ } \ save(op1,lf_resd); \ SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1); \ - SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000); \ + SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); \ } @@ -520,12 +522,14 @@ #define DAS() \ +{ \ + Bit8u osigned=reg_al & 0x80; \ if (((reg_al & 0x0f) > 9) || get_AF()) { \ if ((reg_al>0x99) || get_CF()) { \ reg_al-=0x60; \ SETFLAGBIT(CF,true); \ } else { \ - SETFLAGBIT(CF,false); \ + SETFLAGBIT(CF,(reg_al<=0x05)); \ } \ reg_al-=6; \ SETFLAGBIT(AF,true); \ @@ -538,44 +542,61 @@ } \ SETFLAGBIT(AF,false); \ } \ + SETFLAGBIT(OF,osigned && ((reg_al&0x80)==0)); \ SETFLAGBIT(SF,(reg_al&0x80)); \ SETFLAGBIT(ZF,(reg_al==0)); \ SETFLAGBIT(PF,parity_lookup[reg_al]); \ - lflags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; \ +} #define AAA() \ - if (get_AF() || ((reg_al & 0xf) > 9)) \ - { \ + SETFLAGBIT(SF,((reg_al>=0x7a) && (reg_al<=0xf9))); \ + if ((reg_al & 0xf) > 9) { \ + SETFLAGBIT(OF,(reg_al&0xf0)==0x70); \ reg_ax += 0x106; \ - SETFLAGBIT(AF,true); \ SETFLAGBIT(CF,true); \ + SETFLAGBIT(ZF,(reg_al == 0)); \ + SETFLAGBIT(AF,true); \ + } else if (get_AF()) { \ + reg_ax += 0x106; \ + SETFLAGBIT(OF,false); \ + SETFLAGBIT(CF,true); \ + SETFLAGBIT(ZF,false); \ + SETFLAGBIT(AF,true); \ } else { \ - SETFLAGBIT(AF,false); \ + SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,false); \ + SETFLAGBIT(ZF,(reg_al == 0)); \ + SETFLAGBIT(AF,false); \ } \ + SETFLAGBIT(PF,parity_lookup[reg_al]); \ reg_al &= 0x0F; \ - lflags.type=t_UNKNOWN; \ - SETFLAGBIT(SF,0); \ - SETFLAGBIT(OF,0); \ - SETFLAGBIT(ZF,(reg_al == 0)); \ - SETFLAGBIT(PF,parity_lookup[reg_al]); + lflags.type=t_UNKNOWN; #define AAS() \ - if (((reg_al & 0x0f)>9) || get_AF()) { \ + if ((reg_al & 0x0f)>9) { \ + SETFLAGBIT(SF,(reg_al>0x85)); \ reg_ax -= 0x106; \ - SETFLAGBIT(AF,true); \ + SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,true); \ + SETFLAGBIT(AF,true); \ + } else if (get_AF()) { \ + SETFLAGBIT(OF,((reg_al>=0x80) && (reg_al<=0x85))); \ + SETFLAGBIT(SF,(reg_al<0x06) || (reg_al>0x85)); \ + reg_ax -= 0x106; \ + SETFLAGBIT(CF,true); \ + SETFLAGBIT(AF,true); \ } else { \ - SETFLAGBIT(AF,false); \ + SETFLAGBIT(SF,(reg_al>=0x80)); \ + SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,false); \ + SETFLAGBIT(AF,false); \ } \ - reg_al &= 0x0F; \ - lflags.type=t_UNKNOWN; \ - SETFLAGBIT(SF,0); \ - SETFLAGBIT(OF,0); \ SETFLAGBIT(ZF,(reg_al == 0)); \ - SETFLAGBIT(PF,parity_lookup[reg_al]); + SETFLAGBIT(PF,parity_lookup[reg_al]); \ + reg_al &= 0x0F; \ + lflags.type=t_UNKNOWN; #define AAM(op1) \ { \ @@ -586,9 +607,9 @@ SETFLAGBIT(SF,(reg_al & 0x80)); \ SETFLAGBIT(ZF,(reg_al == 0)); \ SETFLAGBIT(PF,parity_lookup[reg_al]); \ - SETFLAGBIT(CF,0); \ - SETFLAGBIT(OF,0); \ - SETFLAGBIT(AF,0); \ + SETFLAGBIT(CF,false); \ + SETFLAGBIT(OF,false); \ + SETFLAGBIT(AF,false); \ lflags.type=t_UNKNOWN; \ } else EXCEPTION(0); \ } @@ -601,9 +622,9 @@ Bit16u ax2 = ax1 + reg_al; \ reg_al = (Bit8u) ax2; \ reg_ah = 0; \ - SETFLAGBIT(CF,0); \ - SETFLAGBIT(OF,0); \ - SETFLAGBIT(AF,0); \ + SETFLAGBIT(CF,false); \ + SETFLAGBIT(OF,false); \ + SETFLAGBIT(AF,false); \ SETFLAGBIT(SF,reg_al >= 0x80); \ SETFLAGBIT(ZF,reg_al == 0); \ SETFLAGBIT(PF,parity_lookup[reg_al]); \ @@ -611,8 +632,8 @@ } #define MULB(op1,load,save) \ - FillFlags(); \ reg_ax=reg_al*load(op1); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(ZF,reg_al == 0); \ if (reg_ax & 0xff00) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ @@ -622,10 +643,10 @@ #define MULW(op1,load,save) \ { \ - FillFlags(); \ Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \ reg_ax=(Bit16u)(tempu); \ reg_dx=(Bit16u)(tempu >> 16); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(ZF,reg_ax == 0); \ if (reg_dx) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ @@ -636,10 +657,10 @@ #define MULD(op1,load,save) \ { \ - FillFlags(); \ Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \ reg_eax=(Bit32u)(tempu); \ reg_edx=(Bit32u)(tempu >> 32); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(ZF,reg_eax == 0); \ if (reg_edx) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ @@ -729,8 +750,8 @@ #define IMULB(op1,load,save) \ { \ - FillFlags(); \ reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \ + FillFlagsNoCFOF(); \ if ((reg_ax & 0xff80)==0xff80 || \ (reg_ax & 0xff80)==0x0000) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -742,10 +763,10 @@ #define IMULW(op1,load,save) \ { \ - FillFlags(); \ Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \ reg_ax=(Bit16s)(temps); \ reg_dx=(Bit16s)(temps >> 16); \ + FillFlagsNoCFOF(); \ if (((temps & 0xffff8000)==0xffff8000 || \ (temps & 0xffff8000)==0x0000)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -756,11 +777,11 @@ #define IMULD(op1,load,save) \ { \ - FillFlags(); \ Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \ ((Bit64s)((Bit32s)(load(op1)))); \ reg_eax=(Bit32u)(temps); \ reg_edx=(Bit32u)(temps >> 32); \ + FillFlagsNoCFOF(); \ if ((reg_edx==0xffffffff) && \ (reg_eax & 0x80000000) ) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -774,10 +795,9 @@ #define DIMULW(op1,op2,op3,load,save) \ { \ - FillFlags(); \ - Bits res; \ - res=((Bit16s)op2) * ((Bit16s)op3); \ + Bits res=((Bit16s)op2) * ((Bit16s)op3); \ save(op1,res & 0xffff); \ + FillFlagsNoCFOF(); \ if ((res> -32768) && (res<32767)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ } else { \ @@ -787,9 +807,9 @@ #define DIMULD(op1,op2,op3,load,save) \ { \ - FillFlags(); \ Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \ save(op1,(Bit32s)res); \ + FillFlagsNoCFOF(); \ if ((res>-((Bit64s)(2147483647)+1)) && \ (res<(Bit64s)2147483647)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ diff --git a/src/cpu/lazyflags.h b/src/cpu/lazyflags.h index b710db09..2f088ec0 100644 --- a/src/cpu/lazyflags.h +++ b/src/cpu/lazyflags.h @@ -28,6 +28,7 @@ Bit32u get_OF(void); Bit32u get_PF(void); Bitu FillFlags(void); +void FillFlagsNoCFOF(void); void DestroyConditionFlags(void); #include "regs.h"