1 /////////////////////////////////////////////////////////////////////////
3 // Copyright (C) 2001-2012 The Bochs Project
4 // Copyright (C) 2017 Google Inc.
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
19 /////////////////////////////////////////////////////////////////////////
24 #include "qemu/osdep.h"
28 #include "x86_flags.h"
32 /* this is basically bocsh code */
34 #define LF_SIGN_BIT 31
36 #define LF_BIT_SD (0) /* lazy Sign Flag Delta */
37 #define LF_BIT_AF (3) /* lazy Adjust flag */
38 #define LF_BIT_PDB (8) /* lazy Parity Delta Byte (8 bits) */
39 #define LF_BIT_CF (31) /* lazy Carry Flag */
40 #define LF_BIT_PO (30) /* lazy Partial Overflow = CF ^ OF */
42 #define LF_MASK_SD (0x01 << LF_BIT_SD)
43 #define LF_MASK_AF (0x01 << LF_BIT_AF)
44 #define LF_MASK_PDB (0xFF << LF_BIT_PDB)
45 #define LF_MASK_CF (0x01 << LF_BIT_CF)
46 #define LF_MASK_PO (0x01 << LF_BIT_PO)
48 #define ADD_COUT_VEC(op1, op2, result) \
49 (((op1) & (op2)) | (((op1) | (op2)) & (~(result))))
51 #define SUB_COUT_VEC(op1, op2, result) \
52 (((~(op1)) & (op2)) | (((~(op1)) ^ (op2)) & (result)))
54 #define GET_ADD_OVERFLOW(op1, op2, result, mask) \
55 ((((op1) ^ (result)) & ((op2) ^ (result))) & (mask))
57 /* ******************* */
59 /* ******************* */
61 /* size, carries, result */
62 #define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \
63 target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
64 (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
65 env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \
67 temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
68 } else if ((size) == 16) { \
69 temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
70 } else if ((size) == 8) { \
71 temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
73 VM_PANIC("unimplemented"); \
75 env->hvf_lflags.auxbits = (target_ulong)(uint32_t)temp; \
79 #define SET_FLAGS_OSZAPC_8(carries, result) \
80 SET_FLAGS_OSZAPC_SIZE(8, carries, result)
81 #define SET_FLAGS_OSZAPC_16(carries, result) \
82 SET_FLAGS_OSZAPC_SIZE(16, carries, result)
83 #define SET_FLAGS_OSZAPC_32(carries, result) \
84 SET_FLAGS_OSZAPC_SIZE(32, carries, result)
86 /* ******************* */
88 /* ******************* */
89 /* size, carries, result */
90 #define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \
91 target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
92 (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
94 temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
95 } else if ((size) == 16) { \
96 temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
97 } else if ((size) == 8) { \
98 temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
100 VM_PANIC("unimplemented"); \
102 env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \
103 target_ulong delta_c = (env->hvf_lflags.auxbits ^ temp) & LF_MASK_CF; \
104 delta_c ^= (delta_c >> 1); \
105 env->hvf_lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \
108 /* carries, result */
109 #define SET_FLAGS_OSZAP_8(carries, result) \
110 SET_FLAGS_OSZAP_SIZE(8, carries, result)
111 #define SET_FLAGS_OSZAP_16(carries, result) \
112 SET_FLAGS_OSZAP_SIZE(16, carries, result)
113 #define SET_FLAGS_OSZAP_32(carries, result) \
114 SET_FLAGS_OSZAP_SIZE(32, carries, result)
116 void SET_FLAGS_OxxxxC(CPUX86State
*env
, uint32_t new_of
, uint32_t new_cf
)
118 uint32_t temp_po
= new_of
^ new_cf
;
119 env
->hvf_lflags
.auxbits
&= ~(LF_MASK_PO
| LF_MASK_CF
);
120 env
->hvf_lflags
.auxbits
|= (temp_po
<< LF_BIT_PO
) | (new_cf
<< LF_BIT_CF
);
123 void SET_FLAGS_OSZAPC_SUB32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
126 SET_FLAGS_OSZAPC_32(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
129 void SET_FLAGS_OSZAPC_SUB16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
132 SET_FLAGS_OSZAPC_16(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
135 void SET_FLAGS_OSZAPC_SUB8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
138 SET_FLAGS_OSZAPC_8(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
141 void SET_FLAGS_OSZAPC_ADD32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
144 SET_FLAGS_OSZAPC_32(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
147 void SET_FLAGS_OSZAPC_ADD16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
150 SET_FLAGS_OSZAPC_16(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
153 void SET_FLAGS_OSZAPC_ADD8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
156 SET_FLAGS_OSZAPC_8(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
159 void SET_FLAGS_OSZAP_SUB32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
162 SET_FLAGS_OSZAP_32(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
165 void SET_FLAGS_OSZAP_SUB16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
168 SET_FLAGS_OSZAP_16(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
171 void SET_FLAGS_OSZAP_SUB8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
174 SET_FLAGS_OSZAP_8(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
177 void SET_FLAGS_OSZAP_ADD32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
180 SET_FLAGS_OSZAP_32(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
183 void SET_FLAGS_OSZAP_ADD16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
186 SET_FLAGS_OSZAP_16(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
189 void SET_FLAGS_OSZAP_ADD8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
192 SET_FLAGS_OSZAP_8(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
196 void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
199 SET_FLAGS_OSZAPC_32(0, diff
);
202 void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
205 SET_FLAGS_OSZAPC_16(0, diff
);
208 void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
211 SET_FLAGS_OSZAPC_8(0, diff
);
214 bool get_PF(CPUX86State
*env
)
216 uint32_t temp
= (255 & env
->hvf_lflags
.result
);
217 temp
= temp
^ (255 & (env
->hvf_lflags
.auxbits
>> LF_BIT_PDB
));
218 temp
= (temp
^ (temp
>> 4)) & 0x0F;
219 return (0x9669U
>> temp
) & 1;
222 void set_PF(CPUX86State
*env
, bool val
)
224 uint32_t temp
= (255 & env
->hvf_lflags
.result
) ^ (!val
);
225 env
->hvf_lflags
.auxbits
&= ~(LF_MASK_PDB
);
226 env
->hvf_lflags
.auxbits
|= (temp
<< LF_BIT_PDB
);
229 bool get_OF(CPUX86State
*env
)
231 return ((env
->hvf_lflags
.auxbits
+ (1U << LF_BIT_PO
)) >> LF_BIT_CF
) & 1;
234 bool get_CF(CPUX86State
*env
)
236 return (env
->hvf_lflags
.auxbits
>> LF_BIT_CF
) & 1;
239 void set_OF(CPUX86State
*env
, bool val
)
241 bool old_cf
= get_CF(env
);
242 SET_FLAGS_OxxxxC(env
, val
, old_cf
);
245 void set_CF(CPUX86State
*env
, bool val
)
247 bool old_of
= get_OF(env
);
248 SET_FLAGS_OxxxxC(env
, old_of
, val
);
251 bool get_AF(CPUX86State
*env
)
253 return (env
->hvf_lflags
.auxbits
>> LF_BIT_AF
) & 1;
256 void set_AF(CPUX86State
*env
, bool val
)
258 env
->hvf_lflags
.auxbits
&= ~(LF_MASK_AF
);
259 env
->hvf_lflags
.auxbits
|= val
<< LF_BIT_AF
;
262 bool get_ZF(CPUX86State
*env
)
264 return !env
->hvf_lflags
.result
;
267 void set_ZF(CPUX86State
*env
, bool val
)
270 env
->hvf_lflags
.auxbits
^=
271 (((env
->hvf_lflags
.result
>> LF_SIGN_BIT
) & 1) << LF_BIT_SD
);
272 /* merge the parity bits into the Parity Delta Byte */
273 uint32_t temp_pdb
= (255 & env
->hvf_lflags
.result
);
274 env
->hvf_lflags
.auxbits
^= (temp_pdb
<< LF_BIT_PDB
);
275 /* now zero the .result value */
276 env
->hvf_lflags
.result
= 0;
278 env
->hvf_lflags
.result
|= (1 << 8);
282 bool get_SF(CPUX86State
*env
)
284 return ((env
->hvf_lflags
.result
>> LF_SIGN_BIT
) ^
285 (env
->hvf_lflags
.auxbits
>> LF_BIT_SD
)) & 1;
288 void set_SF(CPUX86State
*env
, bool val
)
290 bool temp_sf
= get_SF(env
);
291 env
->hvf_lflags
.auxbits
^= (temp_sf
^ val
) << LF_BIT_SD
;
294 void lflags_to_rflags(CPUX86State
*env
)
296 env
->eflags
|= get_CF(env
) ? CC_C
: 0;
297 env
->eflags
|= get_PF(env
) ? CC_P
: 0;
298 env
->eflags
|= get_AF(env
) ? CC_A
: 0;
299 env
->eflags
|= get_ZF(env
) ? CC_Z
: 0;
300 env
->eflags
|= get_SF(env
) ? CC_S
: 0;
301 env
->eflags
|= get_OF(env
) ? CC_O
: 0;
304 void rflags_to_lflags(CPUX86State
*env
)
306 env
->hvf_lflags
.auxbits
= env
->hvf_lflags
.result
= 0;
307 set_OF(env
, env
->eflags
& CC_O
);
308 set_SF(env
, env
->eflags
& CC_S
);
309 set_ZF(env
, env
->eflags
& CC_Z
);
310 set_AF(env
, env
->eflags
& CC_A
);
311 set_PF(env
, env
->eflags
& CC_P
);
312 set_CF(env
, env
->eflags
& CC_C
);