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 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 | |
42 | static 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 | |
56 | static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
57 | { |
58 | return dst < src1; |
59 | } |
60 | |
61 | static 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 | |
76 | static 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 | |
82 | static 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 | |
96 | static 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 | |
103 | static 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 | |
118 | static 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 | |
126 | static 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 | |
139 | static 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 | |
155 | static 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 | |
171 | static 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 | |
185 | static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
186 | { |
187 | return (src1 >> (DATA_BITS - 1)) & CC_C; |
188 | } |
189 | |
190 | static 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. */ |
207 | static 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 | |
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 | |
238 | #undef DATA_BITS |
239 | #undef SIGN_MASK |
240 | #undef DATA_TYPE |
241 | #undef DATA_MASK |
242 | #undef SUFFIX |
243 | |