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 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"
26 #include "qemu-common.h"
29 #include "x86_flags.h"
33 /* this is basically bocsh code */
35 #define LF_SIGN_BIT 31
37 #define LF_BIT_SD (0) /* lazy Sign Flag Delta */
38 #define LF_BIT_AF (3) /* lazy Adjust flag */
39 #define LF_BIT_PDB (8) /* lazy Parity Delta Byte (8 bits) */
40 #define LF_BIT_CF (31) /* lazy Carry Flag */
41 #define LF_BIT_PO (30) /* lazy Partial Overflow = CF ^ OF */
43 #define LF_MASK_SD (0x01 << LF_BIT_SD)
44 #define LF_MASK_AF (0x01 << LF_BIT_AF)
45 #define LF_MASK_PDB (0xFF << LF_BIT_PDB)
46 #define LF_MASK_CF (0x01 << LF_BIT_CF)
47 #define LF_MASK_PO (0x01 << LF_BIT_PO)
49 #define ADD_COUT_VEC(op1, op2, result) \
50 (((op1) & (op2)) | (((op1) | (op2)) & (~(result))))
52 #define SUB_COUT_VEC(op1, op2, result) \
53 (((~(op1)) & (op2)) | (((~(op1)) ^ (op2)) & (result)))
55 #define GET_ADD_OVERFLOW(op1, op2, result, mask) \
56 ((((op1) ^ (result)) & ((op2) ^ (result))) & (mask))
58 /* ******************* */
60 /* ******************* */
62 /* size, carries, result */
63 #define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \
64 target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
65 (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
66 env->hvf_emul->lflags.result = (target_ulong)(int##size##_t)(lf_result); \
68 temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
69 } else if ((size) == 16) { \
70 temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
71 } else if ((size) == 8) { \
72 temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
74 VM_PANIC("unimplemented"); \
76 env->hvf_emul->lflags.auxbits = (target_ulong)(uint32_t)temp; \
80 #define SET_FLAGS_OSZAPC_8(carries, result) \
81 SET_FLAGS_OSZAPC_SIZE(8, carries, result)
82 #define SET_FLAGS_OSZAPC_16(carries, result) \
83 SET_FLAGS_OSZAPC_SIZE(16, carries, result)
84 #define SET_FLAGS_OSZAPC_32(carries, result) \
85 SET_FLAGS_OSZAPC_SIZE(32, carries, result)
87 /* ******************* */
89 /* ******************* */
90 /* size, carries, result */
91 #define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \
92 target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
93 (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
95 temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
96 } else if ((size) == 16) { \
97 temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
98 } else if ((size) == 8) { \
99 temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
101 VM_PANIC("unimplemented"); \
103 env->hvf_emul->lflags.result = (target_ulong)(int##size##_t)(lf_result); \
104 target_ulong delta_c = (env->hvf_emul->lflags.auxbits ^ temp) & LF_MASK_CF; \
105 delta_c ^= (delta_c >> 1); \
106 env->hvf_emul->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \
109 /* carries, result */
110 #define SET_FLAGS_OSZAP_8(carries, result) \
111 SET_FLAGS_OSZAP_SIZE(8, carries, result)
112 #define SET_FLAGS_OSZAP_16(carries, result) \
113 SET_FLAGS_OSZAP_SIZE(16, carries, result)
114 #define SET_FLAGS_OSZAP_32(carries, result) \
115 SET_FLAGS_OSZAP_SIZE(32, carries, result)
117 void SET_FLAGS_OxxxxC(CPUX86State
*env
, uint32_t new_of
, uint32_t new_cf
)
119 uint32_t temp_po
= new_of
^ new_cf
;
120 env
->hvf_emul
->lflags
.auxbits
&= ~(LF_MASK_PO
| LF_MASK_CF
);
121 env
->hvf_emul
->lflags
.auxbits
|= (temp_po
<< LF_BIT_PO
) |
122 (new_cf
<< LF_BIT_CF
);
125 void SET_FLAGS_OSZAPC_SUB32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
128 SET_FLAGS_OSZAPC_32(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
131 void SET_FLAGS_OSZAPC_SUB16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
134 SET_FLAGS_OSZAPC_16(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
137 void SET_FLAGS_OSZAPC_SUB8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
140 SET_FLAGS_OSZAPC_8(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
143 void SET_FLAGS_OSZAPC_ADD32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
146 SET_FLAGS_OSZAPC_32(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
149 void SET_FLAGS_OSZAPC_ADD16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
152 SET_FLAGS_OSZAPC_16(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
155 void SET_FLAGS_OSZAPC_ADD8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
158 SET_FLAGS_OSZAPC_8(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
161 void SET_FLAGS_OSZAP_SUB32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
164 SET_FLAGS_OSZAP_32(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
167 void SET_FLAGS_OSZAP_SUB16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
170 SET_FLAGS_OSZAP_16(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
173 void SET_FLAGS_OSZAP_SUB8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
176 SET_FLAGS_OSZAP_8(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
179 void SET_FLAGS_OSZAP_ADD32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
182 SET_FLAGS_OSZAP_32(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
185 void SET_FLAGS_OSZAP_ADD16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
188 SET_FLAGS_OSZAP_16(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
191 void SET_FLAGS_OSZAP_ADD8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
194 SET_FLAGS_OSZAP_8(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
198 void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
201 SET_FLAGS_OSZAPC_32(0, diff
);
204 void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
207 SET_FLAGS_OSZAPC_16(0, diff
);
210 void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
213 SET_FLAGS_OSZAPC_8(0, diff
);
216 bool get_PF(CPUX86State
*env
)
218 uint32_t temp
= (255 & env
->hvf_emul
->lflags
.result
);
219 temp
= temp
^ (255 & (env
->hvf_emul
->lflags
.auxbits
>> LF_BIT_PDB
));
220 temp
= (temp
^ (temp
>> 4)) & 0x0F;
221 return (0x9669U
>> temp
) & 1;
224 void set_PF(CPUX86State
*env
, bool val
)
226 uint32_t temp
= (255 & env
->hvf_emul
->lflags
.result
) ^ (!val
);
227 env
->hvf_emul
->lflags
.auxbits
&= ~(LF_MASK_PDB
);
228 env
->hvf_emul
->lflags
.auxbits
|= (temp
<< LF_BIT_PDB
);
231 bool get_OF(CPUX86State
*env
)
233 return ((env
->hvf_emul
->lflags
.auxbits
+ (1U << LF_BIT_PO
)) >> LF_BIT_CF
) & 1;
236 bool get_CF(CPUX86State
*env
)
238 return (env
->hvf_emul
->lflags
.auxbits
>> LF_BIT_CF
) & 1;
241 void set_OF(CPUX86State
*env
, bool val
)
243 bool old_cf
= get_CF(env
);
244 SET_FLAGS_OxxxxC(env
, val
, old_cf
);
247 void set_CF(CPUX86State
*env
, bool val
)
249 bool old_of
= get_OF(env
);
250 SET_FLAGS_OxxxxC(env
, old_of
, val
);
253 bool get_AF(CPUX86State
*env
)
255 return (env
->hvf_emul
->lflags
.auxbits
>> LF_BIT_AF
) & 1;
258 void set_AF(CPUX86State
*env
, bool val
)
260 env
->hvf_emul
->lflags
.auxbits
&= ~(LF_MASK_AF
);
261 env
->hvf_emul
->lflags
.auxbits
|= val
<< LF_BIT_AF
;
264 bool get_ZF(CPUX86State
*env
)
266 return !env
->hvf_emul
->lflags
.result
;
269 void set_ZF(CPUX86State
*env
, bool val
)
272 env
->hvf_emul
->lflags
.auxbits
^=
273 (((env
->hvf_emul
->lflags
.result
>> LF_SIGN_BIT
) & 1) << LF_BIT_SD
);
274 /* merge the parity bits into the Parity Delta Byte */
275 uint32_t temp_pdb
= (255 & env
->hvf_emul
->lflags
.result
);
276 env
->hvf_emul
->lflags
.auxbits
^= (temp_pdb
<< LF_BIT_PDB
);
277 /* now zero the .result value */
278 env
->hvf_emul
->lflags
.result
= 0;
280 env
->hvf_emul
->lflags
.result
|= (1 << 8);
284 bool get_SF(CPUX86State
*env
)
286 return ((env
->hvf_emul
->lflags
.result
>> LF_SIGN_BIT
) ^
287 (env
->hvf_emul
->lflags
.auxbits
>> LF_BIT_SD
)) & 1;
290 void set_SF(CPUX86State
*env
, bool val
)
292 bool temp_sf
= get_SF(env
);
293 env
->hvf_emul
->lflags
.auxbits
^= (temp_sf
^ val
) << LF_BIT_SD
;
296 void lflags_to_rflags(CPUX86State
*env
)
298 env
->hvf_emul
->rflags
.cf
= get_CF(env
);
299 env
->hvf_emul
->rflags
.pf
= get_PF(env
);
300 env
->hvf_emul
->rflags
.af
= get_AF(env
);
301 env
->hvf_emul
->rflags
.zf
= get_ZF(env
);
302 env
->hvf_emul
->rflags
.sf
= get_SF(env
);
303 env
->hvf_emul
->rflags
.of
= get_OF(env
);
306 void rflags_to_lflags(CPUX86State
*env
)
308 env
->hvf_emul
->lflags
.auxbits
= env
->hvf_emul
->lflags
.result
= 0;
309 set_OF(env
, env
->hvf_emul
->rflags
.of
);
310 set_SF(env
, env
->hvf_emul
->rflags
.sf
);
311 set_ZF(env
, env
->hvf_emul
->rflags
.zf
);
312 set_AF(env
, env
->hvf_emul
->rflags
.af
);
313 set_PF(env
, env
->hvf_emul
->rflags
.pf
);
314 set_CF(env
, env
->hvf_emul
->rflags
.cf
);