1*f1cc7c28SPhilippe Mathieu-Daudé/*
2*f1cc7c28SPhilippe Mathieu-Daudé *  x86 condition code helpers
3*f1cc7c28SPhilippe Mathieu-Daudé *
4*f1cc7c28SPhilippe Mathieu-Daudé *  Copyright (c) 2008 Fabrice Bellard
5*f1cc7c28SPhilippe Mathieu-Daudé *
6*f1cc7c28SPhilippe Mathieu-Daudé * This library is free software; you can redistribute it and/or
7*f1cc7c28SPhilippe Mathieu-Daudé * modify it under the terms of the GNU Lesser General Public
8*f1cc7c28SPhilippe Mathieu-Daudé * License as published by the Free Software Foundation; either
9*f1cc7c28SPhilippe Mathieu-Daudé * version 2.1 of the License, or (at your option) any later version.
10*f1cc7c28SPhilippe Mathieu-Daudé *
11*f1cc7c28SPhilippe Mathieu-Daudé * This library is distributed in the hope that it will be useful,
12*f1cc7c28SPhilippe Mathieu-Daudé * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*f1cc7c28SPhilippe Mathieu-Daudé * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*f1cc7c28SPhilippe Mathieu-Daudé * Lesser General Public License for more details.
15*f1cc7c28SPhilippe Mathieu-Daudé *
16*f1cc7c28SPhilippe Mathieu-Daudé * You should have received a copy of the GNU Lesser General Public
17*f1cc7c28SPhilippe Mathieu-Daudé * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18*f1cc7c28SPhilippe Mathieu-Daudé */
19*f1cc7c28SPhilippe Mathieu-Daudé
20*f1cc7c28SPhilippe Mathieu-Daudé#define DATA_BITS (1 << (3 + SHIFT))
21*f1cc7c28SPhilippe Mathieu-Daudé
22*f1cc7c28SPhilippe Mathieu-Daudé#if DATA_BITS == 8
23*f1cc7c28SPhilippe Mathieu-Daudé#define SUFFIX b
24*f1cc7c28SPhilippe Mathieu-Daudé#define DATA_TYPE uint8_t
25*f1cc7c28SPhilippe Mathieu-Daudé#elif DATA_BITS == 16
26*f1cc7c28SPhilippe Mathieu-Daudé#define SUFFIX w
27*f1cc7c28SPhilippe Mathieu-Daudé#define DATA_TYPE uint16_t
28*f1cc7c28SPhilippe Mathieu-Daudé#elif DATA_BITS == 32
29*f1cc7c28SPhilippe Mathieu-Daudé#define SUFFIX l
30*f1cc7c28SPhilippe Mathieu-Daudé#define DATA_TYPE uint32_t
31*f1cc7c28SPhilippe Mathieu-Daudé#elif DATA_BITS == 64
32*f1cc7c28SPhilippe Mathieu-Daudé#define SUFFIX q
33*f1cc7c28SPhilippe Mathieu-Daudé#define DATA_TYPE uint64_t
34*f1cc7c28SPhilippe Mathieu-Daudé#else
35*f1cc7c28SPhilippe Mathieu-Daudé#error unhandled operand size
36*f1cc7c28SPhilippe Mathieu-Daudé#endif
37*f1cc7c28SPhilippe Mathieu-Daudé
38*f1cc7c28SPhilippe Mathieu-Daudé#define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1))
39*f1cc7c28SPhilippe Mathieu-Daudé
40*f1cc7c28SPhilippe Mathieu-Daudé/* dynamic flags computation */
41*f1cc7c28SPhilippe Mathieu-Daudé
42*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
43*f1cc7c28SPhilippe Mathieu-Daudé{
44*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
45*f1cc7c28SPhilippe Mathieu-Daudé    DATA_TYPE src2 = dst - src1;
46*f1cc7c28SPhilippe Mathieu-Daudé
47*f1cc7c28SPhilippe Mathieu-Daudé    cf = dst < src1;
48*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
49*f1cc7c28SPhilippe Mathieu-Daudé    af = (dst ^ src1 ^ src2) & CC_A;
50*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) * CC_Z;
51*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
52*f1cc7c28SPhilippe Mathieu-Daudé    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
53*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
54*f1cc7c28SPhilippe Mathieu-Daudé}
55*f1cc7c28SPhilippe Mathieu-Daudé
56*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
57*f1cc7c28SPhilippe Mathieu-Daudé{
58*f1cc7c28SPhilippe Mathieu-Daudé    return dst < src1;
59*f1cc7c28SPhilippe Mathieu-Daudé}
60*f1cc7c28SPhilippe Mathieu-Daudé
61*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
62*f1cc7c28SPhilippe Mathieu-Daudé                                         DATA_TYPE src3)
63*f1cc7c28SPhilippe Mathieu-Daudé{
64*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
65*f1cc7c28SPhilippe Mathieu-Daudé    DATA_TYPE src2 = dst - src1 - src3;
66*f1cc7c28SPhilippe Mathieu-Daudé
67*f1cc7c28SPhilippe Mathieu-Daudé    cf = (src3 ? dst <= src1 : dst < src1);
68*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
69*f1cc7c28SPhilippe Mathieu-Daudé    af = (dst ^ src1 ^ src2) & 0x10;
70*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) << 6;
71*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & 0x80;
72*f1cc7c28SPhilippe Mathieu-Daudé    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
73*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
74*f1cc7c28SPhilippe Mathieu-Daudé}
75*f1cc7c28SPhilippe Mathieu-Daudé
76*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
77*f1cc7c28SPhilippe Mathieu-Daudé                                       DATA_TYPE src3)
78*f1cc7c28SPhilippe Mathieu-Daudé{
79*f1cc7c28SPhilippe Mathieu-Daudé    return src3 ? dst <= src1 : dst < src1;
80*f1cc7c28SPhilippe Mathieu-Daudé}
81*f1cc7c28SPhilippe Mathieu-Daudé
82*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
83*f1cc7c28SPhilippe Mathieu-Daudé{
84*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
85*f1cc7c28SPhilippe Mathieu-Daudé    DATA_TYPE src1 = dst + src2;
86*f1cc7c28SPhilippe Mathieu-Daudé
87*f1cc7c28SPhilippe Mathieu-Daudé    cf = src1 < src2;
88*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
89*f1cc7c28SPhilippe Mathieu-Daudé    af = (dst ^ src1 ^ src2) & CC_A;
90*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) * CC_Z;
91*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
92*f1cc7c28SPhilippe Mathieu-Daudé    of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
93*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
94*f1cc7c28SPhilippe Mathieu-Daudé}
95*f1cc7c28SPhilippe Mathieu-Daudé
96*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
97*f1cc7c28SPhilippe Mathieu-Daudé{
98*f1cc7c28SPhilippe Mathieu-Daudé    DATA_TYPE src1 = dst + src2;
99*f1cc7c28SPhilippe Mathieu-Daudé
100*f1cc7c28SPhilippe Mathieu-Daudé    return src1 < src2;
101*f1cc7c28SPhilippe Mathieu-Daudé}
102*f1cc7c28SPhilippe Mathieu-Daudé
103*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
104*f1cc7c28SPhilippe Mathieu-Daudé                                         DATA_TYPE src3)
105*f1cc7c28SPhilippe Mathieu-Daudé{
106*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
107*f1cc7c28SPhilippe Mathieu-Daudé    DATA_TYPE src1 = dst + src2 + src3;
108*f1cc7c28SPhilippe Mathieu-Daudé
109*f1cc7c28SPhilippe Mathieu-Daudé    cf = (src3 ? src1 <= src2 : src1 < src2);
110*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
111*f1cc7c28SPhilippe Mathieu-Daudé    af = (dst ^ src1 ^ src2) & 0x10;
112*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) << 6;
113*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & 0x80;
114*f1cc7c28SPhilippe Mathieu-Daudé    of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
115*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
116*f1cc7c28SPhilippe Mathieu-Daudé}
117*f1cc7c28SPhilippe Mathieu-Daudé
118*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
119*f1cc7c28SPhilippe Mathieu-Daudé                                       DATA_TYPE src3)
120*f1cc7c28SPhilippe Mathieu-Daudé{
121*f1cc7c28SPhilippe Mathieu-Daudé    DATA_TYPE src1 = dst + src2 + src3;
122*f1cc7c28SPhilippe Mathieu-Daudé
123*f1cc7c28SPhilippe Mathieu-Daudé    return (src3 ? src1 <= src2 : src1 < src2);
124*f1cc7c28SPhilippe Mathieu-Daudé}
125*f1cc7c28SPhilippe Mathieu-Daudé
126*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
127*f1cc7c28SPhilippe Mathieu-Daudé{
128*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
129*f1cc7c28SPhilippe Mathieu-Daudé
130*f1cc7c28SPhilippe Mathieu-Daudé    cf = 0;
131*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
132*f1cc7c28SPhilippe Mathieu-Daudé    af = 0;
133*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) * CC_Z;
134*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
135*f1cc7c28SPhilippe Mathieu-Daudé    of = 0;
136*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
137*f1cc7c28SPhilippe Mathieu-Daudé}
138*f1cc7c28SPhilippe Mathieu-Daudé
139*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
140*f1cc7c28SPhilippe Mathieu-Daudé{
141*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
142*f1cc7c28SPhilippe Mathieu-Daudé    DATA_TYPE src2;
143*f1cc7c28SPhilippe Mathieu-Daudé
144*f1cc7c28SPhilippe Mathieu-Daudé    cf = src1;
145*f1cc7c28SPhilippe Mathieu-Daudé    src1 = dst - 1;
146*f1cc7c28SPhilippe Mathieu-Daudé    src2 = 1;
147*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
148*f1cc7c28SPhilippe Mathieu-Daudé    af = (dst ^ src1 ^ src2) & CC_A;
149*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) * CC_Z;
150*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
151*f1cc7c28SPhilippe Mathieu-Daudé    of = (dst == SIGN_MASK) * CC_O;
152*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
153*f1cc7c28SPhilippe Mathieu-Daudé}
154*f1cc7c28SPhilippe Mathieu-Daudé
155*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
156*f1cc7c28SPhilippe Mathieu-Daudé{
157*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
158*f1cc7c28SPhilippe Mathieu-Daudé    DATA_TYPE src2;
159*f1cc7c28SPhilippe Mathieu-Daudé
160*f1cc7c28SPhilippe Mathieu-Daudé    cf = src1;
161*f1cc7c28SPhilippe Mathieu-Daudé    src1 = dst + 1;
162*f1cc7c28SPhilippe Mathieu-Daudé    src2 = 1;
163*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
164*f1cc7c28SPhilippe Mathieu-Daudé    af = (dst ^ src1 ^ src2) & CC_A;
165*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) * CC_Z;
166*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
167*f1cc7c28SPhilippe Mathieu-Daudé    of = (dst == SIGN_MASK - 1) * CC_O;
168*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
169*f1cc7c28SPhilippe Mathieu-Daudé}
170*f1cc7c28SPhilippe Mathieu-Daudé
171*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
172*f1cc7c28SPhilippe Mathieu-Daudé{
173*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
174*f1cc7c28SPhilippe Mathieu-Daudé
175*f1cc7c28SPhilippe Mathieu-Daudé    cf = (src1 >> (DATA_BITS - 1)) & CC_C;
176*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
177*f1cc7c28SPhilippe Mathieu-Daudé    af = 0; /* undefined */
178*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) * CC_Z;
179*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
180*f1cc7c28SPhilippe Mathieu-Daudé    /* of is defined iff shift count == 1 */
181*f1cc7c28SPhilippe Mathieu-Daudé    of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
182*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
183*f1cc7c28SPhilippe Mathieu-Daudé}
184*f1cc7c28SPhilippe Mathieu-Daudé
185*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
186*f1cc7c28SPhilippe Mathieu-Daudé{
187*f1cc7c28SPhilippe Mathieu-Daudé    return (src1 >> (DATA_BITS - 1)) & CC_C;
188*f1cc7c28SPhilippe Mathieu-Daudé}
189*f1cc7c28SPhilippe Mathieu-Daudé
190*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
191*f1cc7c28SPhilippe Mathieu-Daudé{
192*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
193*f1cc7c28SPhilippe Mathieu-Daudé
194*f1cc7c28SPhilippe Mathieu-Daudé    cf = src1 & 1;
195*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
196*f1cc7c28SPhilippe Mathieu-Daudé    af = 0; /* undefined */
197*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) * CC_Z;
198*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
199*f1cc7c28SPhilippe Mathieu-Daudé    /* of is defined iff shift count == 1 */
200*f1cc7c28SPhilippe Mathieu-Daudé    of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
201*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
202*f1cc7c28SPhilippe Mathieu-Daudé}
203*f1cc7c28SPhilippe Mathieu-Daudé
204*f1cc7c28SPhilippe Mathieu-Daudé/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
205*f1cc7c28SPhilippe Mathieu-Daudé   CF are modified and it is slower to do that.  Note as well that we
206*f1cc7c28SPhilippe Mathieu-Daudé   don't truncate SRC1 for computing carry to DATA_TYPE.  */
207*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1)
208*f1cc7c28SPhilippe Mathieu-Daudé{
209*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
210*f1cc7c28SPhilippe Mathieu-Daudé
211*f1cc7c28SPhilippe Mathieu-Daudé    cf = (src1 != 0);
212*f1cc7c28SPhilippe Mathieu-Daudé    pf = parity_table[(uint8_t)dst];
213*f1cc7c28SPhilippe Mathieu-Daudé    af = 0; /* undefined */
214*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) * CC_Z;
215*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
216*f1cc7c28SPhilippe Mathieu-Daudé    of = cf * CC_O;
217*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
218*f1cc7c28SPhilippe Mathieu-Daudé}
219*f1cc7c28SPhilippe Mathieu-Daudé
220*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_all_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
221*f1cc7c28SPhilippe Mathieu-Daudé{
222*f1cc7c28SPhilippe Mathieu-Daudé    int cf, pf, af, zf, sf, of;
223*f1cc7c28SPhilippe Mathieu-Daudé
224*f1cc7c28SPhilippe Mathieu-Daudé    cf = (src1 == 0);
225*f1cc7c28SPhilippe Mathieu-Daudé    pf = 0; /* undefined */
226*f1cc7c28SPhilippe Mathieu-Daudé    af = 0; /* undefined */
227*f1cc7c28SPhilippe Mathieu-Daudé    zf = (dst == 0) * CC_Z;
228*f1cc7c28SPhilippe Mathieu-Daudé    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
229*f1cc7c28SPhilippe Mathieu-Daudé    of = 0;
230*f1cc7c28SPhilippe Mathieu-Daudé    return cf | pf | af | zf | sf | of;
231*f1cc7c28SPhilippe Mathieu-Daudé}
232*f1cc7c28SPhilippe Mathieu-Daudé
233*f1cc7c28SPhilippe Mathieu-Daudéstatic int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
234*f1cc7c28SPhilippe Mathieu-Daudé{
235*f1cc7c28SPhilippe Mathieu-Daudé    return src1 == 0;
236*f1cc7c28SPhilippe Mathieu-Daudé}
237*f1cc7c28SPhilippe Mathieu-Daudé
238*f1cc7c28SPhilippe Mathieu-Daudé#undef DATA_BITS
239*f1cc7c28SPhilippe Mathieu-Daudé#undef SIGN_MASK
240*f1cc7c28SPhilippe Mathieu-Daudé#undef DATA_TYPE
241*f1cc7c28SPhilippe Mathieu-Daudé#undef DATA_MASK
242*f1cc7c28SPhilippe Mathieu-Daudé#undef SUFFIX
243