]>
git.proxmox.com Git - mirror_qemu.git/blob - target/i386/hvf/x86_flags.c
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"
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_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_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_lflags.result = (target_ulong)(int##size##_t)(lf_result); \
104 target_ulong delta_c = (env->hvf_lflags.auxbits ^ temp) & LF_MASK_CF; \
105 delta_c ^= (delta_c >> 1); \
106 env->hvf_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_lflags
.auxbits
&= ~(LF_MASK_PO
| LF_MASK_CF
);
121 env
->hvf_lflags
.auxbits
|= (temp_po
<< LF_BIT_PO
) | (new_cf
<< LF_BIT_CF
);
124 void SET_FLAGS_OSZAPC_SUB32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
127 SET_FLAGS_OSZAPC_32(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
130 void SET_FLAGS_OSZAPC_SUB16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
133 SET_FLAGS_OSZAPC_16(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
136 void SET_FLAGS_OSZAPC_SUB8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
139 SET_FLAGS_OSZAPC_8(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
142 void SET_FLAGS_OSZAPC_ADD32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
145 SET_FLAGS_OSZAPC_32(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
148 void SET_FLAGS_OSZAPC_ADD16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
151 SET_FLAGS_OSZAPC_16(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
154 void SET_FLAGS_OSZAPC_ADD8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
157 SET_FLAGS_OSZAPC_8(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
160 void SET_FLAGS_OSZAP_SUB32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
163 SET_FLAGS_OSZAP_32(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
166 void SET_FLAGS_OSZAP_SUB16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
169 SET_FLAGS_OSZAP_16(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
172 void SET_FLAGS_OSZAP_SUB8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
175 SET_FLAGS_OSZAP_8(SUB_COUT_VEC(v1
, v2
, diff
), diff
);
178 void SET_FLAGS_OSZAP_ADD32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
181 SET_FLAGS_OSZAP_32(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
184 void SET_FLAGS_OSZAP_ADD16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
187 SET_FLAGS_OSZAP_16(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
190 void SET_FLAGS_OSZAP_ADD8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
193 SET_FLAGS_OSZAP_8(ADD_COUT_VEC(v1
, v2
, diff
), diff
);
197 void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State
*env
, uint32_t v1
, uint32_t v2
,
200 SET_FLAGS_OSZAPC_32(0, diff
);
203 void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State
*env
, uint16_t v1
, uint16_t v2
,
206 SET_FLAGS_OSZAPC_16(0, diff
);
209 void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State
*env
, uint8_t v1
, uint8_t v2
,
212 SET_FLAGS_OSZAPC_8(0, diff
);
215 bool get_PF(CPUX86State
*env
)
217 uint32_t temp
= (255 & env
->hvf_lflags
.result
);
218 temp
= temp
^ (255 & (env
->hvf_lflags
.auxbits
>> LF_BIT_PDB
));
219 temp
= (temp
^ (temp
>> 4)) & 0x0F;
220 return (0x9669U
>> temp
) & 1;
223 void set_PF(CPUX86State
*env
, bool val
)
225 uint32_t temp
= (255 & env
->hvf_lflags
.result
) ^ (!val
);
226 env
->hvf_lflags
.auxbits
&= ~(LF_MASK_PDB
);
227 env
->hvf_lflags
.auxbits
|= (temp
<< LF_BIT_PDB
);
230 bool get_OF(CPUX86State
*env
)
232 return ((env
->hvf_lflags
.auxbits
+ (1U << LF_BIT_PO
)) >> LF_BIT_CF
) & 1;
235 bool get_CF(CPUX86State
*env
)
237 return (env
->hvf_lflags
.auxbits
>> LF_BIT_CF
) & 1;
240 void set_OF(CPUX86State
*env
, bool val
)
242 bool old_cf
= get_CF(env
);
243 SET_FLAGS_OxxxxC(env
, val
, old_cf
);
246 void set_CF(CPUX86State
*env
, bool val
)
248 bool old_of
= get_OF(env
);
249 SET_FLAGS_OxxxxC(env
, old_of
, val
);
252 bool get_AF(CPUX86State
*env
)
254 return (env
->hvf_lflags
.auxbits
>> LF_BIT_AF
) & 1;
257 void set_AF(CPUX86State
*env
, bool val
)
259 env
->hvf_lflags
.auxbits
&= ~(LF_MASK_AF
);
260 env
->hvf_lflags
.auxbits
|= val
<< LF_BIT_AF
;
263 bool get_ZF(CPUX86State
*env
)
265 return !env
->hvf_lflags
.result
;
268 void set_ZF(CPUX86State
*env
, bool val
)
271 env
->hvf_lflags
.auxbits
^=
272 (((env
->hvf_lflags
.result
>> LF_SIGN_BIT
) & 1) << LF_BIT_SD
);
273 /* merge the parity bits into the Parity Delta Byte */
274 uint32_t temp_pdb
= (255 & env
->hvf_lflags
.result
);
275 env
->hvf_lflags
.auxbits
^= (temp_pdb
<< LF_BIT_PDB
);
276 /* now zero the .result value */
277 env
->hvf_lflags
.result
= 0;
279 env
->hvf_lflags
.result
|= (1 << 8);
283 bool get_SF(CPUX86State
*env
)
285 return ((env
->hvf_lflags
.result
>> LF_SIGN_BIT
) ^
286 (env
->hvf_lflags
.auxbits
>> LF_BIT_SD
)) & 1;
289 void set_SF(CPUX86State
*env
, bool val
)
291 bool temp_sf
= get_SF(env
);
292 env
->hvf_lflags
.auxbits
^= (temp_sf
^ val
) << LF_BIT_SD
;
295 void lflags_to_rflags(CPUX86State
*env
)
297 env
->eflags
|= get_CF(env
) ? CC_C
: 0;
298 env
->eflags
|= get_PF(env
) ? CC_P
: 0;
299 env
->eflags
|= get_AF(env
) ? CC_A
: 0;
300 env
->eflags
|= get_ZF(env
) ? CC_Z
: 0;
301 env
->eflags
|= get_SF(env
) ? CC_S
: 0;
302 env
->eflags
|= get_OF(env
) ? CC_O
: 0;
305 void rflags_to_lflags(CPUX86State
*env
)
307 env
->hvf_lflags
.auxbits
= env
->hvf_lflags
.result
= 0;
308 set_OF(env
, env
->eflags
& CC_O
);
309 set_SF(env
, env
->eflags
& CC_S
);
310 set_ZF(env
, env
->eflags
& CC_Z
);
311 set_AF(env
, env
->eflags
& CC_A
);
312 set_PF(env
, env
->eflags
& CC_P
);
313 set_CF(env
, env
->eflags
& CC_C
);