xref: /openbmc/qemu/target/i386/tcg/cc_helper_template.h.inc (revision eebba0536a6302f5c55faa5286e5e59cb21036c3)
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#define WIDER_TYPE uint32_t
26#elif DATA_BITS == 16
27#define SUFFIX w
28#define DATA_TYPE uint16_t
29#define WIDER_TYPE uint32_t
30#elif DATA_BITS == 32
31#define SUFFIX l
32#define DATA_TYPE uint32_t
33#if HOST_LONG_BITS >= 64
34#define WIDER_TYPE uint64_t
35#endif
36#elif DATA_BITS == 64
37#define SUFFIX q
38#define DATA_TYPE uint64_t
39#else
40#error unhandled operand size
41#endif
42
43#define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1))
44
45/* dynamic flags computation */
46
47static uint32_t glue(compute_all_cout, SUFFIX)(DATA_TYPE dst, DATA_TYPE carries)
48{
49    uint32_t af_cf, pf, zf, sf, of;
50
51    /* PF, ZF, SF computed from result.  */
52    pf = compute_pf(dst);
53    zf = (dst == 0) * CC_Z;
54    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
55
56    /*
57     * AF, CF, OF computed from carry out vector.  To compute AF and CF, rotate it
58     * left by one so cout(DATA_BITS - 1) is in bit 0 and cout(3) in bit 4.
59     *
60     * To compute OF, place the highest two carry bits into OF and the bit
61     * immediately to the right of it; then, adding CC_O / 2 XORs them.
62     */
63    af_cf = ((carries << 1) | (carries >> (DATA_BITS - 1))) & (CC_A | CC_C);
64    of = (lshift(carries, 12 - DATA_BITS) + CC_O / 2) & CC_O;
65    return pf + zf + sf + af_cf + of;
66}
67
68static uint32_t glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
69{
70    DATA_TYPE src2 = dst - src1;
71    DATA_TYPE carries = ADD_COUT_VEC(src1, src2, dst);
72    return glue(compute_all_cout, SUFFIX)(dst, carries);
73}
74
75static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
76{
77    return dst < src1;
78}
79
80static uint32_t glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
81                                         DATA_TYPE src3)
82{
83    DATA_TYPE src2 = dst - src1 - src3;
84    DATA_TYPE carries = ADD_COUT_VEC(src1, src2, dst);
85    return glue(compute_all_cout, SUFFIX)(dst, carries);
86}
87
88static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
89                                       DATA_TYPE src3)
90{
91#ifdef WIDER_TYPE
92    WIDER_TYPE src13 = (WIDER_TYPE) src1 + (WIDER_TYPE) src3;
93
94    return dst < src13;
95#else
96    return src3 ? dst <= src1 : dst < src1;
97#endif
98}
99
100static uint32_t glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
101{
102    DATA_TYPE src1 = dst + src2;
103    DATA_TYPE carries = SUB_COUT_VEC(src1, src2, dst);
104    return glue(compute_all_cout, SUFFIX)(dst, carries);
105}
106
107static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
108{
109    DATA_TYPE src1 = dst + src2;
110
111    return src1 < src2;
112}
113
114static uint32_t glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
115                                         DATA_TYPE src3)
116{
117    DATA_TYPE src1 = dst + src2 + src3;
118    DATA_TYPE carries = SUB_COUT_VEC(src1, src2, dst);
119    return glue(compute_all_cout, SUFFIX)(dst, carries);
120}
121
122static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
123                                       DATA_TYPE src3)
124{
125#ifdef WIDER_TYPE
126    WIDER_TYPE src23 = (WIDER_TYPE) src2 + (WIDER_TYPE) src3;
127    DATA_TYPE src1 = dst + src23;
128
129    return src1 < src23;
130#else
131    DATA_TYPE src1 = dst + src2 + src3;
132
133    return (src3 ? src1 <= src2 : src1 < src2);
134#endif
135}
136
137static uint32_t glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
138{
139    uint32_t cf, pf, af, zf, sf, of;
140
141    cf = 0;
142    pf = compute_pf(dst);
143    af = 0;
144    zf = (dst == 0) * CC_Z;
145    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
146    of = 0;
147    return cf + pf + af + zf + sf + of;
148}
149
150static uint32_t glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
151{
152    uint32_t cf, pf, af, zf, sf, of;
153
154    cf = src1;
155    pf = compute_pf(dst);
156    af = (dst ^ (dst - 1)) & CC_A; /* bits 0..3 are all clear */
157    zf = (dst == 0) * CC_Z;
158    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
159    of = (dst == SIGN_MASK) * CC_O;
160    return cf + pf + af + zf + sf + of;
161}
162
163static uint32_t glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
164{
165    uint32_t cf, pf, af, zf, sf, of;
166
167    cf = src1;
168    pf = compute_pf(dst);
169    af = (dst ^ (dst + 1)) & CC_A; /* bits 0..3 are all set */
170    zf = (dst == 0) * CC_Z;
171    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
172    of = (dst == SIGN_MASK - 1) * CC_O;
173    return cf + pf + af + zf + sf + of;
174}
175
176static uint32_t glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
177{
178    uint32_t cf, pf, af, zf, sf, of;
179
180    cf = (src1 >> (DATA_BITS - 1)) & CC_C;
181    pf = compute_pf(dst);
182    af = 0; /* undefined */
183    zf = (dst == 0) * CC_Z;
184    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
185    /* of is defined iff shift count == 1 */
186    of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
187    return cf + pf + af + zf + sf + of;
188}
189
190static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
191{
192    return (src1 >> (DATA_BITS - 1)) & CC_C;
193}
194
195static uint32_t glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
196{
197    uint32_t cf, pf, af, zf, sf, of;
198
199    cf = src1 & 1;
200    pf = compute_pf(dst);
201    af = 0; /* undefined */
202    zf = (dst == 0) * CC_Z;
203    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
204    /* of is defined iff shift count == 1 */
205    of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
206    return cf + pf + af + zf + sf + of;
207}
208
209/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
210   CF are modified and it is slower to do that.  Note as well that we
211   don't truncate SRC1 for computing carry to DATA_TYPE.  */
212static uint32_t glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1)
213{
214    uint32_t cf, pf, af, zf, sf, of;
215
216    cf = (src1 != 0);
217    pf = compute_pf(dst);
218    af = 0; /* undefined */
219    zf = (dst == 0) * CC_Z;
220    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
221    of = cf * CC_O;
222    return cf + pf + af + zf + sf + of;
223}
224
225static uint32_t glue(compute_all_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
226{
227    uint32_t cf, pf, af, zf, sf, of;
228
229    cf = (src1 == 0);
230    pf = 0; /* undefined */
231    af = 0; /* undefined */
232    zf = (dst == 0) * CC_Z;
233    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
234    of = 0;
235    return cf + pf + af + zf + sf + of;
236}
237
238static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
239{
240    return src1 == 0;
241}
242
243static int glue(compute_all_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
244{
245    uint32_t cf, pf, af, zf, sf, of;
246
247    cf = (src1 != 0);
248    pf = 0; /* undefined */
249    af = 0; /* undefined */
250    zf = (dst == 0) * CC_Z;
251    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
252    of = 0;
253    return cf + pf + af + zf + sf + of;
254}
255
256static int glue(compute_c_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
257{
258    return src1 != 0;
259}
260
261#undef DATA_BITS
262#undef SIGN_MASK
263#undef DATA_TYPE
264#undef SUFFIX
265#undef WIDER_TYPE
266