30
31
32
/*
33
- * The algorithms here are similar to those in Bochs. After an ALU
34
- * operation, CC_DST can be used to compute ZF, SF and PF, whereas
35
- * CC_SRC is used to compute AF, CF and OF. In reality, SF and PF are the
36
- * XOR of the value computed from CC_DST and the value found in bits 7 and 2
37
- * of CC_SRC; this way the same logic can be used to compute the flags
38
- * both before and after an ALU operation.
33
+ * The emulator always encodes flags in the same way as CC_OP_CCMPB + MO_TL.
34
+ * While for arithmetic operations ZF/SF/PF are computed from the same value,
35
+ * ZF=1 may be inconsistent with PF/SF for arbitrary RFLAGS values so CC_SRC2
36
+ * is used for SF and PF. CC_SRC holds a carry-out vector that is used to
37
+ * compute AF, CF and OF.
38
*
39
* Compared to the TCG CC_OP codes, this avoids conditionals when converting
40
* to and from the RFLAGS representation.
41
+ *
42
+ * The underlying ideas ultimately descend from Bochs, but with significant
43
+ * simplifications obtained by storing flags in three words rather than two.
44
*/
45
46
#define LF_SIGN_BIT (TARGET_LONG_BITS - 1)
47
46
-#define LF_BIT_PD (2) /* lazy Parity Delta, same bit as PF */
47
-#define LF_BIT_AF (3) /* lazy Adjust flag */
48
-#define LF_BIT_SD (7) /* lazy Sign Flag Delta, same bit as SF */
48
#define LF_BIT_CF (TARGET_LONG_BITS - 1) /* lazy Carry Flag */
49
#define LF_BIT_PO (TARGET_LONG_BITS - 2) /* lazy Partial Overflow = CF ^ OF */
50
52
-#define LF_MASK_PD ((target_ulong)0x01 << LF_BIT_PD)
53
-#define LF_MASK_AF ((target_ulong)0x01 << LF_BIT_AF)
54
-#define LF_MASK_SD ((target_ulong)0x01 << LF_BIT_SD)
51
#define LF_MASK_CF ((target_ulong)0x01 << LF_BIT_CF)
52
#define LF_MASK_PO ((target_ulong)0x01 << LF_BIT_PO)
53
55
/* OSZAPC */
56
/* ******************* */
57
62
-/* use carries to fill in AF, PO and CF, while ensuring PD and SD are clear.
63
- * for full-word operations just clear PD and SD; for smaller operand
64
- * sizes only keep AF in the low byte and shift the carries left to
65
- * place PO and CF in the top two bits.
58
+/*
59
+ * For arithmetic operations ZF/SF/PF are consistent so DST == SRC2.
60
+ * For operations that are not full-word, keep AF in the low byte and shift
61
+ * the carries left to place PO and CF in the top two bits.
62
*/
63
#define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \
68
- env->cc_dst = (target_ulong)(int##size##_t)(lf_result); \
69
- target_ulong temp = (lf_carries); \
70
- if ((size) == TARGET_LONG_BITS) { \
71
- temp = temp & ~(LF_MASK_PD | LF_MASK_SD); \
72
- } else { \
73
- temp = (temp & LF_MASK_AF) | (temp << (TARGET_LONG_BITS - (size))); \
74
- } \
64
+ env->cc_dst = env->cc_src2 = (target_ulong)(int##size##_t)(lf_result); \
65
+ target_ulong temp = (lf_carries) & MAKE_64BIT_MASK(0, size); \
66
+ temp |= temp << (TARGET_LONG_BITS - (size)); \
67
env->cc_src = temp; \
68
}
69
85
/* same as setting OSZAPC, but preserve CF and flip PO if the old value of CF
86
* did not match the high bit of lf_carries. */
87
#define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \
96
- env->cc_dst = (target_ulong)(int##size##_t)(lf_result); \
97
- target_ulong temp = (lf_carries); \
98
- if ((size) == TARGET_LONG_BITS) { \
99
- temp = (temp & ~(LF_MASK_PD | LF_MASK_SD)); \
100
- } else { \
101
- temp = (temp & LF_MASK_AF) | (temp << (TARGET_LONG_BITS - (size))); \
102
- } \
88
+ env->cc_dst = env->cc_src2 = (target_ulong)(int##size##_t)(lf_result); \
89
+ target_ulong temp = (lf_carries) & MAKE_64BIT_MASK(0, size); \
90
+ temp |= temp << (TARGET_LONG_BITS - (size)); \
91
target_ulong cf_changed = ((target_long)(env->cc_src ^ temp)) < 0; \
92
env->cc_src = temp ^ (cf_changed * (LF_MASK_PO | LF_MASK_CF)); \
93
}
243
244
static inline uint32_t get_PF(CPUX86State *env)
245
{
258
- return ((parity8(env->cc_dst) - 1) ^ env->cc_src) & CC_P;
246
+ return (parity8(env->cc_src2) - 1) & CC_P;
247
}
248
249
static inline uint32_t get_OF(CPUX86State *env)
271
272
static inline uint32_t get_SF(CPUX86State *env)
273
{
286
- return ((env->cc_dst >> (LF_SIGN_BIT - LF_BIT_SD)) ^
287
- env->cc_src) & CC_S;
274
+ return (target_long)env->cc_src2 < 0 ? CC_S : 0;
275
}
276
277
void lflags_to_rflags(CPUX86State *env)
291
{
292
target_ulong cf_af, cf_xor_of;
293
307
- /* Leave the low byte zero so that parity is always even... */
308
- env->cc_dst = !(env->eflags & CC_Z) << 8;
309
-
310
- /* ... and therefore cc_src always uses opposite polarity. */
311
- env->cc_src = CC_P;
312
- env->cc_src ^= env->eflags & (CC_S | CC_P);
294
+ /* compute DST and SRC2 that reconstruct ZF/SF/PF. */
295
+ env->cc_dst = ~env->eflags & CC_Z; /* DST = 0 if ZF=1 */
296
+ env->cc_src2 = ~env->eflags & CC_P; /* odd parity if PF=0 */
297
+ env->cc_src2 ^= -!!(env->eflags & CC_S);
298
299
/* rotate right by one to move CF and AF into the carry-out positions */
300
cf_af = env->eflags & (CC_C | CC_A);
316
- env->cc_src |= ((cf_af >> 1) | (cf_af << (TARGET_LONG_BITS - 1)));
301
+ env->cc_src = ((cf_af >> 1) | (cf_af << (TARGET_LONG_BITS - 1)));
302
303
cf_xor_of = ((env->eflags & (CC_C | CC_O)) + (CC_O - CC_C)) & CC_O;
304
env->cc_src |= -cf_xor_of & LF_MASK_PO;