@@ -113,11 +113,6 @@ static inline int is_zf_set(void)
113113 return RFL .res == 0 ;
114114}
115115
116- static inline int is_sf_set (void )
117- {
118- return (RFL .res >> LF_BIT_RES_SF ) ^ ((RFL .cout >> LF_BIT_SD ) & 1 );
119- }
120-
121116static inline int is_cf_set (void )
122117{
123118 return RFL .cout >> LF_BIT_CF ;
@@ -130,13 +125,7 @@ static inline int is_of_set(void)
130125
131126static inline int is_af_set (void )
132127{
133- return (RFL .cout >> LF_BIT_AF ) & 1 ;
134- }
135-
136- static unsigned char parity [256 ];
137- static inline int is_pf_set (void )
138- {
139- return (parity [RFL .res & 0xff ] ^ (RFL .cout & LF_MASK_PD )) >> LF_BIT_PD ;
128+ return (RFL .cout & LF_MASK_AF ) != 0 ;
140129}
141130
142131static inline void SET_CF (unsigned int c )
@@ -145,14 +134,6 @@ static inline void SET_CF(unsigned int c)
145134 RFL .cout ^= (c != is_cf_set ()) * (LF_MASK_PO | LF_MASK_CF );
146135}
147136
148- static inline void SET_ZF (unsigned int c )
149- {
150- // to set ZF in RFL.res we must transfer SF/PF to RFL.cout
151- RFL .cout = (RFL .cout & ~(LF_MASK_PD | LF_MASK_SD )) |
152- (((is_sf_set () << LF_BIT_SD ) | (is_pf_set () << LF_BIT_PD )) ^ LF_MASK_PD );
153- RFL .res = (!c ) << 8 ;
154- }
155-
156137/* add/sub rule for carry using MSB:
157138 * the carry-out expressions from Bochs 2.6 are used here.
158139 * RFL.cout is a cheap-to-compute 32-bit word that encodes the following flags:
@@ -220,35 +201,20 @@ static inline void FlagHandleShift(int sh, int cy, uint32_t cout, int wordsize,
220201 RFL .cout &= ~(LF_MASK_SD |LF_MASK_PD );
221202}
222203
223- static inline int FlagSync_NZ (void )
204+ static inline int FlagSync_S (void )
224205{
225- int zr ,pl ,nf ;
226- zr = (RFL .res == 0 ) << X86_EFLAGS_ZF_BIT ;
227- pl = ((RFL .res >>(LF_BIT_RES_SF - X86_EFLAGS_SF_BIT )) ^ RFL .cout ) &
206+ return ((RFL .res >>(LF_BIT_RES_SF - X86_EFLAGS_SF_BIT )) ^ RFL .cout ) &
228207 EFLAGS_SF ;
229- nf = zr | pl ;
230- if (debug_level ('e' )> 2 ) e_printf ("Sync NZ flags = %02x\n" , nf );
231- return nf ;
208+ }
209+
210+ static inline int is_sf_set (void )
211+ {
212+ return FlagSync_S () != 0 ;
232213}
233214
234215static inline int FlagSync_O (void )
235216{
236- int nf ;
237- // OF
238- /* overflow rule using MSB:
239- * src1 src2 res OF ad/sub
240- * 0 0 0 0 0
241- * 0 0 1 1 0
242- * 0 1 0 0 0
243- * 0 1 1 0 1
244- * 1 0 0 0 1
245- * 1 0 1 0 0
246- * 1 1 0 1 0
247- * 1 1 1 0 0
248- */
249- // 80000000->0800 ^ 40000000->0800
250- nf = ((RFL .cout >> (LF_BIT_CF - X86_EFLAGS_OF_BIT )) ^
251- (RFL .cout >> (LF_BIT_PO - X86_EFLAGS_OF_BIT ))) & EFLAGS_OF ;
217+ int nf = is_of_set () << X86_EFLAGS_OF_BIT ;
252218 if (debug_level ('e' )> 1 ) e_printf ("Sync O flag = %04x\n" , nf );
253219 return nf ;
254220}
@@ -272,21 +238,35 @@ static unsigned char parity[256] =
272238 4 , 0 , 0 , 4 , 0 , 4 , 4 , 0 , 0 , 4 , 4 , 0 , 4 , 0 , 0 , 4 };
273239
274240
275- static inline int FlagSync_AP (void )
241+ static inline int FlagSync_P (void )
276242{
277- int af ,pf ,nf ;
278- af = (RFL .cout & LF_MASK_AF ) << (X86_EFLAGS_AF_BIT - LF_BIT_AF );
279- pf = parity [RFL .res & 0xff ] ^ (RFL .cout & LF_MASK_PD );
280- nf = af | pf ;
281- if (debug_level ('e' )> 2 ) e_printf ("Sync AP flags = %02x\n" , nf );
282- return nf ;
243+ return parity [RFL .res & 0xff ] ^ (RFL .cout & LF_MASK_PD );
283244}
284245
246+ static inline int is_pf_set (void )
247+ {
248+ return FlagSync_P () != 0 ;
249+ }
250+
251+ static inline void SET_ZF (unsigned int c )
252+ {
253+ // to set ZF in RFL.res we must transfer SF/PF to RFL.cout
254+ RFL .cout = (RFL .cout & ~(LF_MASK_PD | LF_MASK_SD )) |
255+ ((FlagSync_S () | FlagSync_P ()) ^ LF_MASK_PD );
256+ RFL .res = (!c ) << 8 ;
257+ }
258+
259+ static inline int FlagSync_SZAPC (void )
260+ {
261+ /* AF/CF can be can be quickly obtained using a rotation */
262+ return (((RFL .cout << 1 ) | (RFL .cout >> 31 )) & (EFLAGS_AF | EFLAGS_CF )) |
263+ (is_zf_set () << X86_EFLAGS_ZF_BIT ) |
264+ FlagSync_S () | FlagSync_P ();
265+ }
285266
286267void FlagSync_All (void )
287268{
288- int nf ;
289- nf = FlagSync_AP () | FlagSync_NZ () | FlagSync_O () | is_cf_set ();
269+ int nf = FlagSync_SZAPC () | FlagSync_O ();
290270 if (debug_level ('e' )> 1 ) e_printf ("Sync ALL flags = %04x\n" , nf );
291271 CPUWORD (Ofs_FLAGS ) = (CPUWORD (Ofs_FLAGS ) & ~EFLAGS_CC ) | nf ;
292272}
@@ -295,11 +275,14 @@ void FlagSync_All (void)
295275static void FlagSync_RFL (void )
296276{
297277 /* encode all CC flags into RFL */
298- RFL .res = IS_ZF_SET ? 0x0 : 0x100 ;
299- RFL .cout = ((unsigned )IS_CF_SET << LF_BIT_CF ) |
300- ((IS_CF_SET ^ IS_OF_SET ) << LF_BIT_PO ) |
301- (IS_AF_SET << LF_BIT_AF ) |
302- ((CPUBYTE (Ofs_FLAGS ) & (EFLAGS_SF |EFLAGS_PF )) ^ EFLAGS_PF );
278+ uint32_t flg = CPULONG (Ofs_FLAGS );
279+ /* AF/CF via rotation */
280+ uint32_t cout = ((flg << 31 ) | (flg >> 1 )) & (LF_MASK_AF | LF_MASK_CF );
281+ /* PO derived from CF^OF */
282+ cout |= ((cout >> 1 ) ^ (flg << (LF_BIT_PO - X86_EFLAGS_OF_BIT ))) & LF_MASK_PO ;
283+ /* PF/SF in PD/SD; since parity of RFL.res is even, must flip PD */
284+ RFL .cout = cout | ((flg & (EFLAGS_SF |EFLAGS_PF )) ^ EFLAGS_PF );
285+ RFL .res = (!IS_ZF_SET ) << 8 ;
303286}
304287
305288/////////////////////////////////////////////////////////////////////////////
@@ -2465,8 +2448,7 @@ unsigned int Gen_sim(const IGen *IG)
24652448 int rcod = IG -> p0 & 1 ; // 0=LAHF 1=SAHF
24662449 if (rcod == 0 ) { /* LAHF */
24672450 GTRACE0 ("O_LAHF" );
2468- FlagSync_All ();
2469- CPUBYTE (Ofs_AH ) = CPUBYTE (Ofs_FLAGS );
2451+ CPUBYTE (Ofs_AH ) = FlagSync_SZAPC ();
24702452 }
24712453 else { /* SAHF */
24722454 GTRACE0 ("O_SAHF" );
0 commit comments