Skip to content

Commit e224ec5

Browse files
committed
simx86, Gen_sim; cleanup use of FlagSync* functions
Mostly to reduce duplication of expressions to convert lazy flags to CPU flags. LAHF now computes directly from lazy flags.
1 parent 36f718a commit e224ec5

File tree

1 file changed

+41
-59
lines changed

1 file changed

+41
-59
lines changed

src/base/emu-i386/simx86/codegen-sim.c

Lines changed: 41 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
121116
static 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

131126
static 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

142131
static 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

234215
static 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

286267
void 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)
295275
static 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

Comments
 (0)