]>
Commit | Line | Data |
---|---|---|
b6abf97d | 1 | /* |
38de4c46 | 2 | * x86 condition code helpers |
b6abf97d FB |
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 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 | |
8167ee88 | 17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
b6abf97d | 18 | */ |
a04759f6 | 19 | |
b6abf97d | 20 | #define DATA_BITS (1 << (3 + SHIFT)) |
b6abf97d FB |
21 | |
22 | #if DATA_BITS == 8 | |
23 | #define SUFFIX b | |
24 | #define DATA_TYPE uint8_t | |
b6abf97d FB |
25 | #elif DATA_BITS == 16 |
26 | #define SUFFIX w | |
27 | #define DATA_TYPE uint16_t | |
b6abf97d FB |
28 | #elif DATA_BITS == 32 |
29 | #define SUFFIX l | |
30 | #define DATA_TYPE uint32_t | |
b6abf97d FB |
31 | #elif DATA_BITS == 64 |
32 | #define SUFFIX q | |
33 | #define DATA_TYPE uint64_t | |
b6abf97d FB |
34 | #else |
35 | #error unhandled operand size | |
36 | #endif | |
37 | ||
8601c0b6 RH |
38 | #define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1)) |
39 | ||
07d2c595 FB |
40 | /* dynamic flags computation */ |
41 | ||
8601c0b6 | 42 | static int glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
07d2c595 FB |
43 | { |
44 | int cf, pf, af, zf, sf, of; | |
8601c0b6 RH |
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; | |
07d2c595 FB |
53 | return cf | pf | af | zf | sf | of; |
54 | } | |
55 | ||
8601c0b6 | 56 | static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
07d2c595 | 57 | { |
8601c0b6 | 58 | return dst < src1; |
07d2c595 FB |
59 | } |
60 | ||
988c3eb0 RH |
61 | static int glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, |
62 | DATA_TYPE src3) | |
07d2c595 FB |
63 | { |
64 | int cf, pf, af, zf, sf, of; | |
988c3eb0 | 65 | DATA_TYPE src2 = dst - src1 - src3; |
8601c0b6 | 66 | |
988c3eb0 | 67 | cf = (src3 ? dst <= src1 : dst < src1); |
8601c0b6 RH |
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; | |
07d2c595 FB |
73 | return cf | pf | af | zf | sf | of; |
74 | } | |
75 | ||
988c3eb0 RH |
76 | static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, |
77 | DATA_TYPE src3) | |
07d2c595 | 78 | { |
988c3eb0 | 79 | return src3 ? dst <= src1 : dst < src1; |
07d2c595 FB |
80 | } |
81 | ||
8601c0b6 | 82 | static int glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) |
07d2c595 FB |
83 | { |
84 | int cf, pf, af, zf, sf, of; | |
8601c0b6 RH |
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; | |
07d2c595 FB |
93 | return cf | pf | af | zf | sf | of; |
94 | } | |
95 | ||
8601c0b6 | 96 | static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) |
07d2c595 | 97 | { |
8601c0b6 | 98 | DATA_TYPE src1 = dst + src2; |
a04759f6 | 99 | |
8601c0b6 | 100 | return src1 < src2; |
07d2c595 FB |
101 | } |
102 | ||
988c3eb0 RH |
103 | static int glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, |
104 | DATA_TYPE src3) | |
07d2c595 FB |
105 | { |
106 | int cf, pf, af, zf, sf, of; | |
988c3eb0 | 107 | DATA_TYPE src1 = dst + src2 + src3; |
8601c0b6 | 108 | |
988c3eb0 | 109 | cf = (src3 ? src1 <= src2 : src1 < src2); |
8601c0b6 RH |
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; | |
07d2c595 FB |
115 | return cf | pf | af | zf | sf | of; |
116 | } | |
117 | ||
988c3eb0 RH |
118 | static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, |
119 | DATA_TYPE src3) | |
07d2c595 | 120 | { |
988c3eb0 | 121 | DATA_TYPE src1 = dst + src2 + src3; |
a04759f6 | 122 | |
988c3eb0 | 123 | return (src3 ? src1 <= src2 : src1 < src2); |
07d2c595 FB |
124 | } |
125 | ||
8601c0b6 | 126 | static int glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
07d2c595 FB |
127 | { |
128 | int cf, pf, af, zf, sf, of; | |
a04759f6 | 129 | |
07d2c595 | 130 | cf = 0; |
8601c0b6 | 131 | pf = parity_table[(uint8_t)dst]; |
07d2c595 | 132 | af = 0; |
8601c0b6 RH |
133 | zf = (dst == 0) * CC_Z; |
134 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; | |
07d2c595 FB |
135 | of = 0; |
136 | return cf | pf | af | zf | sf | of; | |
137 | } | |
138 | ||
8601c0b6 | 139 | static int glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
07d2c595 FB |
140 | { |
141 | int cf, pf, af, zf, sf, of; | |
8601c0b6 | 142 | DATA_TYPE src2; |
a04759f6 | 143 | |
8601c0b6 RH |
144 | cf = src1; |
145 | src1 = dst - 1; | |
07d2c595 | 146 | src2 = 1; |
8601c0b6 RH |
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; | |
07d2c595 FB |
152 | return cf | pf | af | zf | sf | of; |
153 | } | |
154 | ||
8601c0b6 | 155 | static int glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
07d2c595 FB |
156 | { |
157 | int cf, pf, af, zf, sf, of; | |
8601c0b6 | 158 | DATA_TYPE src2; |
a04759f6 | 159 | |
8601c0b6 RH |
160 | cf = src1; |
161 | src1 = dst + 1; | |
07d2c595 | 162 | src2 = 1; |
8601c0b6 RH |
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; | |
07d2c595 FB |
168 | return cf | pf | af | zf | sf | of; |
169 | } | |
170 | ||
8601c0b6 | 171 | static int glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
07d2c595 FB |
172 | { |
173 | int cf, pf, af, zf, sf, of; | |
a04759f6 | 174 | |
8601c0b6 RH |
175 | cf = (src1 >> (DATA_BITS - 1)) & CC_C; |
176 | pf = parity_table[(uint8_t)dst]; | |
07d2c595 | 177 | af = 0; /* undefined */ |
8601c0b6 RH |
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; | |
07d2c595 FB |
182 | return cf | pf | af | zf | sf | of; |
183 | } | |
184 | ||
8601c0b6 | 185 | static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
07d2c595 | 186 | { |
8601c0b6 | 187 | return (src1 >> (DATA_BITS - 1)) & CC_C; |
07d2c595 FB |
188 | } |
189 | ||
8601c0b6 | 190 | static int glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
07d2c595 FB |
191 | { |
192 | int cf, pf, af, zf, sf, of; | |
a04759f6 | 193 | |
8601c0b6 RH |
194 | cf = src1 & 1; |
195 | pf = parity_table[(uint8_t)dst]; | |
07d2c595 | 196 | af = 0; /* undefined */ |
8601c0b6 RH |
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; | |
07d2c595 FB |
201 | return cf | pf | af | zf | sf | of; |
202 | } | |
203 | ||
07d2c595 | 204 | /* NOTE: we compute the flags like the P4. On olders CPUs, only OF and |
8601c0b6 RH |
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. */ | |
207 | static int glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1) | |
07d2c595 FB |
208 | { |
209 | int cf, pf, af, zf, sf, of; | |
a04759f6 | 210 | |
8601c0b6 RH |
211 | cf = (src1 != 0); |
212 | pf = parity_table[(uint8_t)dst]; | |
07d2c595 | 213 | af = 0; /* undefined */ |
8601c0b6 RH |
214 | zf = (dst == 0) * CC_Z; |
215 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; | |
216 | of = cf * CC_O; | |
07d2c595 FB |
217 | return cf | pf | af | zf | sf | of; |
218 | } | |
219 | ||
bc4b43dc RH |
220 | static 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 | ||
233 | static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) | |
234 | { | |
235 | return src1 == 0; | |
236 | } | |
237 | ||
b6abf97d | 238 | #undef DATA_BITS |
b6abf97d FB |
239 | #undef SIGN_MASK |
240 | #undef DATA_TYPE | |
b6abf97d FB |
241 | #undef DATA_MASK |
242 | #undef SUFFIX |