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