blob: 607311f1951391655ebbdbc80f1393f5c699b0e7 [file] [log] [blame]
bellardb6abf972008-05-17 12:44:31 +00001/*
Blue Swirl38de4c42012-05-12 20:39:26 +00002 * x86 condition code helpers
bellardb6abf972008-05-17 12:44:31 +00003 *
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 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
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellardb6abf972008-05-17 12:44:31 +000018 */
Blue Swirla04759f2012-04-29 12:27:33 +000019
bellardb6abf972008-05-17 12:44:31 +000020#define DATA_BITS (1 << (3 + SHIFT))
bellardb6abf972008-05-17 12:44:31 +000021
22#if DATA_BITS == 8
23#define SUFFIX b
24#define DATA_TYPE uint8_t
bellardb6abf972008-05-17 12:44:31 +000025#elif DATA_BITS == 16
26#define SUFFIX w
27#define DATA_TYPE uint16_t
bellardb6abf972008-05-17 12:44:31 +000028#elif DATA_BITS == 32
29#define SUFFIX l
30#define DATA_TYPE uint32_t
bellardb6abf972008-05-17 12:44:31 +000031#elif DATA_BITS == 64
32#define SUFFIX q
33#define DATA_TYPE uint64_t
bellardb6abf972008-05-17 12:44:31 +000034#else
35#error unhandled operand size
36#endif
37
Richard Henderson8601c0b2013-01-23 16:06:38 -080038#define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1))
39
bellard07d2c592008-05-17 13:57:33 +000040/* dynamic flags computation */
41
Richard Henderson8601c0b2013-01-23 16:06:38 -080042static int glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
bellard07d2c592008-05-17 13:57:33 +000043{
44 int cf, pf, af, zf, sf, of;
Richard Henderson8601c0b2013-01-23 16:06:38 -080045 DATA_TYPE src2 = dst - src1;
Blue Swirla04759f2012-04-29 12:27:33 +000046
Richard Henderson8601c0b2013-01-23 16:06:38 -080047 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;
bellard07d2c592008-05-17 13:57:33 +000053 return cf | pf | af | zf | sf | of;
54}
55
Richard Henderson8601c0b2013-01-23 16:06:38 -080056static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
bellard07d2c592008-05-17 13:57:33 +000057{
Richard Henderson8601c0b2013-01-23 16:06:38 -080058 return dst < src1;
bellard07d2c592008-05-17 13:57:33 +000059}
60
Richard Henderson988c3eb2013-01-23 16:03:16 -080061static int glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
62 DATA_TYPE src3)
bellard07d2c592008-05-17 13:57:33 +000063{
64 int cf, pf, af, zf, sf, of;
Richard Henderson988c3eb2013-01-23 16:03:16 -080065 DATA_TYPE src2 = dst - src1 - src3;
Blue Swirla04759f2012-04-29 12:27:33 +000066
Richard Henderson988c3eb2013-01-23 16:03:16 -080067 cf = (src3 ? dst <= src1 : dst < src1);
Richard Henderson8601c0b2013-01-23 16:06:38 -080068 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;
bellard07d2c592008-05-17 13:57:33 +000073 return cf | pf | af | zf | sf | of;
74}
75
Richard Henderson988c3eb2013-01-23 16:03:16 -080076static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
77 DATA_TYPE src3)
bellard07d2c592008-05-17 13:57:33 +000078{
Richard Henderson988c3eb2013-01-23 16:03:16 -080079 return src3 ? dst <= src1 : dst < src1;
bellard07d2c592008-05-17 13:57:33 +000080}
81
Richard Henderson8601c0b2013-01-23 16:06:38 -080082static int glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
bellard07d2c592008-05-17 13:57:33 +000083{
84 int cf, pf, af, zf, sf, of;
Richard Henderson8601c0b2013-01-23 16:06:38 -080085 DATA_TYPE src1 = dst + src2;
Blue Swirla04759f2012-04-29 12:27:33 +000086
Richard Henderson8601c0b2013-01-23 16:06:38 -080087 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;
bellard07d2c592008-05-17 13:57:33 +000093 return cf | pf | af | zf | sf | of;
94}
95
Richard Henderson8601c0b2013-01-23 16:06:38 -080096static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
bellard07d2c592008-05-17 13:57:33 +000097{
Richard Henderson8601c0b2013-01-23 16:06:38 -080098 DATA_TYPE src1 = dst + src2;
Blue Swirla04759f2012-04-29 12:27:33 +000099
Richard Henderson8601c0b2013-01-23 16:06:38 -0800100 return src1 < src2;
bellard07d2c592008-05-17 13:57:33 +0000101}
102
Richard Henderson988c3eb2013-01-23 16:03:16 -0800103static int glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
104 DATA_TYPE src3)
bellard07d2c592008-05-17 13:57:33 +0000105{
106 int cf, pf, af, zf, sf, of;
Richard Henderson988c3eb2013-01-23 16:03:16 -0800107 DATA_TYPE src1 = dst + src2 + src3;
Blue Swirla04759f2012-04-29 12:27:33 +0000108
Richard Henderson988c3eb2013-01-23 16:03:16 -0800109 cf = (src3 ? src1 <= src2 : src1 < src2);
Richard Henderson8601c0b2013-01-23 16:06:38 -0800110 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;
bellard07d2c592008-05-17 13:57:33 +0000115 return cf | pf | af | zf | sf | of;
116}
117
Richard Henderson988c3eb2013-01-23 16:03:16 -0800118static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
119 DATA_TYPE src3)
bellard07d2c592008-05-17 13:57:33 +0000120{
Richard Henderson988c3eb2013-01-23 16:03:16 -0800121 DATA_TYPE src1 = dst + src2 + src3;
Blue Swirla04759f2012-04-29 12:27:33 +0000122
Richard Henderson988c3eb2013-01-23 16:03:16 -0800123 return (src3 ? src1 <= src2 : src1 < src2);
bellard07d2c592008-05-17 13:57:33 +0000124}
125
Richard Henderson8601c0b2013-01-23 16:06:38 -0800126static int glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
bellard07d2c592008-05-17 13:57:33 +0000127{
128 int cf, pf, af, zf, sf, of;
Blue Swirla04759f2012-04-29 12:27:33 +0000129
bellard07d2c592008-05-17 13:57:33 +0000130 cf = 0;
Richard Henderson8601c0b2013-01-23 16:06:38 -0800131 pf = parity_table[(uint8_t)dst];
bellard07d2c592008-05-17 13:57:33 +0000132 af = 0;
Richard Henderson8601c0b2013-01-23 16:06:38 -0800133 zf = (dst == 0) * CC_Z;
134 sf = lshift(dst, 8 - DATA_BITS) & CC_S;
bellard07d2c592008-05-17 13:57:33 +0000135 of = 0;
136 return cf | pf | af | zf | sf | of;
137}
138
Richard Henderson8601c0b2013-01-23 16:06:38 -0800139static int glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
bellard07d2c592008-05-17 13:57:33 +0000140{
141 int cf, pf, af, zf, sf, of;
Richard Henderson8601c0b2013-01-23 16:06:38 -0800142 DATA_TYPE src2;
Blue Swirla04759f2012-04-29 12:27:33 +0000143
Richard Henderson8601c0b2013-01-23 16:06:38 -0800144 cf = src1;
145 src1 = dst - 1;
bellard07d2c592008-05-17 13:57:33 +0000146 src2 = 1;
Richard Henderson8601c0b2013-01-23 16:06:38 -0800147 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;
bellard07d2c592008-05-17 13:57:33 +0000152 return cf | pf | af | zf | sf | of;
153}
154
Richard Henderson8601c0b2013-01-23 16:06:38 -0800155static int glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
bellard07d2c592008-05-17 13:57:33 +0000156{
157 int cf, pf, af, zf, sf, of;
Richard Henderson8601c0b2013-01-23 16:06:38 -0800158 DATA_TYPE src2;
Blue Swirla04759f2012-04-29 12:27:33 +0000159
Richard Henderson8601c0b2013-01-23 16:06:38 -0800160 cf = src1;
161 src1 = dst + 1;
bellard07d2c592008-05-17 13:57:33 +0000162 src2 = 1;
Richard Henderson8601c0b2013-01-23 16:06:38 -0800163 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;
bellard07d2c592008-05-17 13:57:33 +0000168 return cf | pf | af | zf | sf | of;
169}
170
Richard Henderson8601c0b2013-01-23 16:06:38 -0800171static int glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
bellard07d2c592008-05-17 13:57:33 +0000172{
173 int cf, pf, af, zf, sf, of;
Blue Swirla04759f2012-04-29 12:27:33 +0000174
Richard Henderson8601c0b2013-01-23 16:06:38 -0800175 cf = (src1 >> (DATA_BITS - 1)) & CC_C;
176 pf = parity_table[(uint8_t)dst];
bellard07d2c592008-05-17 13:57:33 +0000177 af = 0; /* undefined */
Richard Henderson8601c0b2013-01-23 16:06:38 -0800178 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;
bellard07d2c592008-05-17 13:57:33 +0000182 return cf | pf | af | zf | sf | of;
183}
184
Richard Henderson8601c0b2013-01-23 16:06:38 -0800185static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
bellard07d2c592008-05-17 13:57:33 +0000186{
Richard Henderson8601c0b2013-01-23 16:06:38 -0800187 return (src1 >> (DATA_BITS - 1)) & CC_C;
bellard07d2c592008-05-17 13:57:33 +0000188}
189
Richard Henderson8601c0b2013-01-23 16:06:38 -0800190static int glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
bellard07d2c592008-05-17 13:57:33 +0000191{
192 int cf, pf, af, zf, sf, of;
Blue Swirla04759f2012-04-29 12:27:33 +0000193
Richard Henderson8601c0b2013-01-23 16:06:38 -0800194 cf = src1 & 1;
195 pf = parity_table[(uint8_t)dst];
bellard07d2c592008-05-17 13:57:33 +0000196 af = 0; /* undefined */
Richard Henderson8601c0b2013-01-23 16:06:38 -0800197 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;
bellard07d2c592008-05-17 13:57:33 +0000201 return cf | pf | af | zf | sf | of;
202}
203
bellard07d2c592008-05-17 13:57:33 +0000204/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
Richard Henderson8601c0b2013-01-23 16:06:38 -0800205 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)
bellard07d2c592008-05-17 13:57:33 +0000208{
209 int cf, pf, af, zf, sf, of;
Blue Swirla04759f2012-04-29 12:27:33 +0000210
Richard Henderson8601c0b2013-01-23 16:06:38 -0800211 cf = (src1 != 0);
212 pf = parity_table[(uint8_t)dst];
bellard07d2c592008-05-17 13:57:33 +0000213 af = 0; /* undefined */
Richard Henderson8601c0b2013-01-23 16:06:38 -0800214 zf = (dst == 0) * CC_Z;
215 sf = lshift(dst, 8 - DATA_BITS) & CC_S;
216 of = cf * CC_O;
bellard07d2c592008-05-17 13:57:33 +0000217 return cf | pf | af | zf | sf | of;
218}
219
Richard Hendersonbc4b43d2013-01-23 16:44:37 -0800220static 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
bellardb6abf972008-05-17 12:44:31 +0000238#undef DATA_BITS
bellardb6abf972008-05-17 12:44:31 +0000239#undef SIGN_MASK
240#undef DATA_TYPE
bellardb6abf972008-05-17 12:44:31 +0000241#undef DATA_MASK
242#undef SUFFIX