xref: /openbmc/qemu/target/i386/hvf/x86_flags.h (revision 69e0a03c3f28f5bd35f54a47cd4996cc14e135ba)
1*69e0a03cSPaolo Bonzini /////////////////////////////////////////////////////////////////////////
2*69e0a03cSPaolo Bonzini //
3*69e0a03cSPaolo Bonzini //  Copyright (C) 2001-2012  The Bochs Project
4*69e0a03cSPaolo Bonzini //  Copyright (C) 2017 Google Inc.
5*69e0a03cSPaolo Bonzini //
6*69e0a03cSPaolo Bonzini //  This library is free software; you can redistribute it and/or
7*69e0a03cSPaolo Bonzini //  modify it under the terms of the GNU Lesser General Public
8*69e0a03cSPaolo Bonzini //  License as published by the Free Software Foundation; either
9*69e0a03cSPaolo Bonzini //  version 2 of the License, or (at your option) any later version.
10*69e0a03cSPaolo Bonzini //
11*69e0a03cSPaolo Bonzini //  This library is distributed in the hope that it will be useful,
12*69e0a03cSPaolo Bonzini //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13*69e0a03cSPaolo Bonzini //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*69e0a03cSPaolo Bonzini //  Lesser General Public License for more details.
15*69e0a03cSPaolo Bonzini //
16*69e0a03cSPaolo Bonzini //  You should have received a copy of the GNU Lesser General Public
17*69e0a03cSPaolo Bonzini //  License along with this library; if not, write to the Free Software
18*69e0a03cSPaolo Bonzini //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
19*69e0a03cSPaolo Bonzini /////////////////////////////////////////////////////////////////////////
20*69e0a03cSPaolo Bonzini /*
21*69e0a03cSPaolo Bonzini  * x86 eflags functions
22*69e0a03cSPaolo Bonzini  */
23*69e0a03cSPaolo Bonzini #ifndef __X86_FLAGS_H__
24*69e0a03cSPaolo Bonzini #define __X86_FLAGS_H__
25*69e0a03cSPaolo Bonzini 
26*69e0a03cSPaolo Bonzini #include "x86_gen.h"
27*69e0a03cSPaolo Bonzini #include "cpu.h"
28*69e0a03cSPaolo Bonzini 
29*69e0a03cSPaolo Bonzini /* this is basically bocsh code */
30*69e0a03cSPaolo Bonzini 
31*69e0a03cSPaolo Bonzini #define LF_SIGN_BIT     31
32*69e0a03cSPaolo Bonzini 
33*69e0a03cSPaolo Bonzini #define LF_BIT_SD      (0)          /* lazy Sign Flag Delta            */
34*69e0a03cSPaolo Bonzini #define LF_BIT_AF      (3)          /* lazy Adjust flag                */
35*69e0a03cSPaolo Bonzini #define LF_BIT_PDB     (8)          /* lazy Parity Delta Byte (8 bits) */
36*69e0a03cSPaolo Bonzini #define LF_BIT_CF      (31)         /* lazy Carry Flag                 */
37*69e0a03cSPaolo Bonzini #define LF_BIT_PO      (30)         /* lazy Partial Overflow = CF ^ OF */
38*69e0a03cSPaolo Bonzini 
39*69e0a03cSPaolo Bonzini #define LF_MASK_SD     (0x01 << LF_BIT_SD)
40*69e0a03cSPaolo Bonzini #define LF_MASK_AF     (0x01 << LF_BIT_AF)
41*69e0a03cSPaolo Bonzini #define LF_MASK_PDB    (0xFF << LF_BIT_PDB)
42*69e0a03cSPaolo Bonzini #define LF_MASK_CF     (0x01 << LF_BIT_CF)
43*69e0a03cSPaolo Bonzini #define LF_MASK_PO     (0x01 << LF_BIT_PO)
44*69e0a03cSPaolo Bonzini 
45*69e0a03cSPaolo Bonzini #define ADD_COUT_VEC(op1, op2, result) \
46*69e0a03cSPaolo Bonzini    (((op1) & (op2)) | (((op1) | (op2)) & (~(result))))
47*69e0a03cSPaolo Bonzini 
48*69e0a03cSPaolo Bonzini #define SUB_COUT_VEC(op1, op2, result) \
49*69e0a03cSPaolo Bonzini    (((~(op1)) & (op2)) | (((~(op1)) ^ (op2)) & (result)))
50*69e0a03cSPaolo Bonzini 
51*69e0a03cSPaolo Bonzini #define GET_ADD_OVERFLOW(op1, op2, result, mask) \
52*69e0a03cSPaolo Bonzini    ((((op1) ^ (result)) & ((op2) ^ (result))) & (mask))
53*69e0a03cSPaolo Bonzini 
54*69e0a03cSPaolo Bonzini /* ******************* */
55*69e0a03cSPaolo Bonzini /* OSZAPC */
56*69e0a03cSPaolo Bonzini /* ******************* */
57*69e0a03cSPaolo Bonzini 
58*69e0a03cSPaolo Bonzini /* size, carries, result */
59*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \
60*69e0a03cSPaolo Bonzini     addr_t temp = ((lf_carries) & (LF_MASK_AF)) | \
61*69e0a03cSPaolo Bonzini     (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
62*69e0a03cSPaolo Bonzini     env->hvf_emul->lflags.result = (addr_t)(int##size##_t)(lf_result); \
63*69e0a03cSPaolo Bonzini     if ((size) == 32) { \
64*69e0a03cSPaolo Bonzini         temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
65*69e0a03cSPaolo Bonzini     } else if ((size) == 16) { \
66*69e0a03cSPaolo Bonzini         temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
67*69e0a03cSPaolo Bonzini     } else if ((size) == 8)  { \
68*69e0a03cSPaolo Bonzini         temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
69*69e0a03cSPaolo Bonzini     } else { \
70*69e0a03cSPaolo Bonzini         VM_PANIC("unimplemented");  \
71*69e0a03cSPaolo Bonzini     } \
72*69e0a03cSPaolo Bonzini     env->hvf_emul->lflags.auxbits = (addr_t)(uint32_t)temp; \
73*69e0a03cSPaolo Bonzini }
74*69e0a03cSPaolo Bonzini 
75*69e0a03cSPaolo Bonzini /* carries, result */
76*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_8(carries, result) \
77*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_SIZE(8, carries, result)
78*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_16(carries, result) \
79*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_SIZE(16, carries, result)
80*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_32(carries, result) \
81*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_SIZE(32, carries, result)
82*69e0a03cSPaolo Bonzini 
83*69e0a03cSPaolo Bonzini /* result */
84*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_LOGIC_8(result_8) \
85*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_8(0, (result_8))
86*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_LOGIC_16(result_16) \
87*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_16(0, (result_16))
88*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_LOGIC_32(result_32) \
89*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_32(0, (result_32))
90*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_LOGIC_SIZE(size, result) {             \
91*69e0a03cSPaolo Bonzini     if (32 == size) { \
92*69e0a03cSPaolo Bonzini         SET_FLAGS_OSZAPC_LOGIC_32(result); \
93*69e0a03cSPaolo Bonzini     } else if (16 == size) { \
94*69e0a03cSPaolo Bonzini         SET_FLAGS_OSZAPC_LOGIC_16(result); \
95*69e0a03cSPaolo Bonzini     } else if (8 == size) { \
96*69e0a03cSPaolo Bonzini         SET_FLAGS_OSZAPC_LOGIC_8(result); \
97*69e0a03cSPaolo Bonzini     } else { \
98*69e0a03cSPaolo Bonzini         VM_PANIC("unimplemented");                            \
99*69e0a03cSPaolo Bonzini     } \
100*69e0a03cSPaolo Bonzini }
101*69e0a03cSPaolo Bonzini 
102*69e0a03cSPaolo Bonzini /* op1, op2, result */
103*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_ADD_8(op1_8, op2_8, sum_8) \
104*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_8(ADD_COUT_VEC((op1_8), (op2_8), (sum_8)), (sum_8))
105*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16) \
106*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_16(ADD_COUT_VEC((op1_16), (op2_16), (sum_16)), (sum_16))
107*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32) \
108*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_32(ADD_COUT_VEC((op1_32), (op2_32), (sum_32)), (sum_32))
109*69e0a03cSPaolo Bonzini 
110*69e0a03cSPaolo Bonzini /* op1, op2, result */
111*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8) \
112*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_8(SUB_COUT_VEC((op1_8), (op2_8), (diff_8)), (diff_8))
113*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16) \
114*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_16(SUB_COUT_VEC((op1_16), (op2_16), (diff_16)), (diff_16))
115*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32) \
116*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_32(SUB_COUT_VEC((op1_32), (op2_32), (diff_32)), (diff_32))
117*69e0a03cSPaolo Bonzini 
118*69e0a03cSPaolo Bonzini /* ******************* */
119*69e0a03cSPaolo Bonzini /* OSZAP */
120*69e0a03cSPaolo Bonzini /* ******************* */
121*69e0a03cSPaolo Bonzini /* size, carries, result */
122*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \
123*69e0a03cSPaolo Bonzini     addr_t temp = ((lf_carries) & (LF_MASK_AF)) | \
124*69e0a03cSPaolo Bonzini     (((lf_carries) >> (size - 2)) << LF_BIT_PO); \
125*69e0a03cSPaolo Bonzini     if ((size) == 32) { \
126*69e0a03cSPaolo Bonzini         temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
127*69e0a03cSPaolo Bonzini     } else if ((size) == 16) { \
128*69e0a03cSPaolo Bonzini         temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
129*69e0a03cSPaolo Bonzini     } else if ((size) == 8) { \
130*69e0a03cSPaolo Bonzini         temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \
131*69e0a03cSPaolo Bonzini     } else { \
132*69e0a03cSPaolo Bonzini         VM_PANIC("unimplemented");      \
133*69e0a03cSPaolo Bonzini     } \
134*69e0a03cSPaolo Bonzini     env->hvf_emul->lflags.result = (addr_t)(int##size##_t)(lf_result); \
135*69e0a03cSPaolo Bonzini     addr_t delta_c = (env->hvf_emul->lflags.auxbits ^ temp) & LF_MASK_CF; \
136*69e0a03cSPaolo Bonzini     delta_c ^= (delta_c >> 1); \
137*69e0a03cSPaolo Bonzini     env->hvf_emul->lflags.auxbits = (addr_t)(uint32_t)(temp ^ delta_c); \
138*69e0a03cSPaolo Bonzini }
139*69e0a03cSPaolo Bonzini 
140*69e0a03cSPaolo Bonzini /* carries, result */
141*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_8(carries, result) \
142*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAP_SIZE(8, carries, result)
143*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_16(carries, result) \
144*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAP_SIZE(16, carries, result)
145*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_32(carries, result) \
146*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAP_SIZE(32, carries, result)
147*69e0a03cSPaolo Bonzini 
148*69e0a03cSPaolo Bonzini /* op1, op2, result */
149*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_ADD_8(op1_8, op2_8, sum_8) \
150*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAP_8(ADD_COUT_VEC((op1_8), (op2_8), (sum_8)), (sum_8))
151*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_ADD_16(op1_16, op2_16, sum_16) \
152*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAP_16(ADD_COUT_VEC((op1_16), (op2_16), (sum_16)), (sum_16))
153*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_ADD_32(op1_32, op2_32, sum_32) \
154*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAP_32(ADD_COUT_VEC((op1_32), (op2_32), (sum_32)), (sum_32))
155*69e0a03cSPaolo Bonzini 
156*69e0a03cSPaolo Bonzini /* op1, op2, result */
157*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_SUB_8(op1_8, op2_8, diff_8) \
158*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAP_8(SUB_COUT_VEC((op1_8), (op2_8), (diff_8)), (diff_8))
159*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_SUB_16(op1_16, op2_16, diff_16) \
160*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAP_16(SUB_COUT_VEC((op1_16), (op2_16), (diff_16)), (diff_16))
161*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAP_SUB_32(op1_32, op2_32, diff_32) \
162*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAP_32(SUB_COUT_VEC((op1_32), (op2_32), (diff_32)), (diff_32))
163*69e0a03cSPaolo Bonzini 
164*69e0a03cSPaolo Bonzini /* ******************* */
165*69e0a03cSPaolo Bonzini /* OSZAxC */
166*69e0a03cSPaolo Bonzini /* ******************* */
167*69e0a03cSPaolo Bonzini /* size, carries, result */
168*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAxC_LOGIC_SIZE(size, lf_result) { \
169*69e0a03cSPaolo Bonzini     bool saved_PF = getB_PF(); \
170*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAPC_SIZE(size, (int##size##_t)(0), lf_result); \
171*69e0a03cSPaolo Bonzini     set_PF(saved_PF); \
172*69e0a03cSPaolo Bonzini }
173*69e0a03cSPaolo Bonzini 
174*69e0a03cSPaolo Bonzini /* result */
175*69e0a03cSPaolo Bonzini #define SET_FLAGS_OSZAxC_LOGIC_32(result_32) \
176*69e0a03cSPaolo Bonzini     SET_FLAGS_OSZAxC_LOGIC_SIZE(32, (result_32))
177*69e0a03cSPaolo Bonzini 
178*69e0a03cSPaolo Bonzini void lflags_to_rflags(CPUX86State *env);
179*69e0a03cSPaolo Bonzini void rflags_to_lflags(CPUX86State *env);
180*69e0a03cSPaolo Bonzini 
181*69e0a03cSPaolo Bonzini bool get_PF(CPUX86State *env);
182*69e0a03cSPaolo Bonzini void set_PF(CPUX86State *env, bool val);
183*69e0a03cSPaolo Bonzini bool get_CF(CPUX86State *env);
184*69e0a03cSPaolo Bonzini void set_CF(CPUX86State *env, bool val);
185*69e0a03cSPaolo Bonzini bool get_AF(CPUX86State *env);
186*69e0a03cSPaolo Bonzini void set_AF(CPUX86State *env, bool val);
187*69e0a03cSPaolo Bonzini bool get_ZF(CPUX86State *env);
188*69e0a03cSPaolo Bonzini void set_ZF(CPUX86State *env, bool val);
189*69e0a03cSPaolo Bonzini bool get_SF(CPUX86State *env);
190*69e0a03cSPaolo Bonzini void set_SF(CPUX86State *env, bool val);
191*69e0a03cSPaolo Bonzini bool get_OF(CPUX86State *env);
192*69e0a03cSPaolo Bonzini void set_OF(CPUX86State *env, bool val);
193*69e0a03cSPaolo Bonzini void set_OSZAPC(CPUX86State *env, uint32_t flags32);
194*69e0a03cSPaolo Bonzini 
195*69e0a03cSPaolo Bonzini void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf);
196*69e0a03cSPaolo Bonzini 
197*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
198*69e0a03cSPaolo Bonzini                             uint32_t diff);
199*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
200*69e0a03cSPaolo Bonzini                             uint16_t diff);
201*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
202*69e0a03cSPaolo Bonzini                            uint8_t diff);
203*69e0a03cSPaolo Bonzini 
204*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
205*69e0a03cSPaolo Bonzini                             uint32_t diff);
206*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
207*69e0a03cSPaolo Bonzini                             uint16_t diff);
208*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
209*69e0a03cSPaolo Bonzini                            uint8_t diff);
210*69e0a03cSPaolo Bonzini 
211*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
212*69e0a03cSPaolo Bonzini                            uint32_t diff);
213*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
214*69e0a03cSPaolo Bonzini                            uint16_t diff);
215*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
216*69e0a03cSPaolo Bonzini                           uint8_t diff);
217*69e0a03cSPaolo Bonzini 
218*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
219*69e0a03cSPaolo Bonzini                            uint32_t diff);
220*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
221*69e0a03cSPaolo Bonzini                            uint16_t diff);
222*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
223*69e0a03cSPaolo Bonzini                           uint8_t diff);
224*69e0a03cSPaolo Bonzini 
225*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t diff);
226*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t diff);
227*69e0a03cSPaolo Bonzini void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t diff);
228*69e0a03cSPaolo Bonzini 
229*69e0a03cSPaolo Bonzini void SET_FLAGS_SHR32(CPUX86State *env, uint32_t v, int count, uint32_t res);
230*69e0a03cSPaolo Bonzini void SET_FLAGS_SHR16(CPUX86State *env, uint16_t v, int count, uint16_t res);
231*69e0a03cSPaolo Bonzini void SET_FLAGS_SHR8(CPUX86State *env, uint8_t v, int count, uint8_t res);
232*69e0a03cSPaolo Bonzini 
233*69e0a03cSPaolo Bonzini void SET_FLAGS_SAR32(CPUX86State *env, int32_t v, int count, uint32_t res);
234*69e0a03cSPaolo Bonzini void SET_FLAGS_SAR16(CPUX86State *env, int16_t v, int count, uint16_t res);
235*69e0a03cSPaolo Bonzini void SET_FLAGS_SAR8(CPUX86State *env, int8_t v, int count, uint8_t res);
236*69e0a03cSPaolo Bonzini 
237*69e0a03cSPaolo Bonzini void SET_FLAGS_SHL32(CPUX86State *env, uint32_t v, int count, uint32_t res);
238*69e0a03cSPaolo Bonzini void SET_FLAGS_SHL16(CPUX86State *env, uint16_t v, int count, uint16_t res);
239*69e0a03cSPaolo Bonzini void SET_FLAGS_SHL8(CPUX86State *env, uint8_t v, int count, uint8_t res);
240*69e0a03cSPaolo Bonzini 
241*69e0a03cSPaolo Bonzini bool _get_OF(CPUX86State *env);
242*69e0a03cSPaolo Bonzini bool _get_CF(CPUX86State *env);
243*69e0a03cSPaolo Bonzini #endif /* __X86_FLAGS_H__ */
244