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_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 48{ 49 uint32_t cf, pf, af, zf, sf, of; 50 DATA_TYPE src2 = dst - src1; 51 52 cf = dst < src1; 53 pf = compute_pf(dst); 54 af = (dst ^ src1 ^ src2) & CC_A; 55 zf = (dst == 0) * CC_Z; 56 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 57 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; 58 return cf + pf + af + zf + sf + of; 59} 60 61static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 62{ 63 return dst < src1; 64} 65 66static uint32_t glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, 67 DATA_TYPE src3) 68{ 69 uint32_t cf, pf, af, zf, sf, of; 70 71#ifdef WIDER_TYPE 72 WIDER_TYPE src13 = (WIDER_TYPE) src1 + (WIDER_TYPE) src3; 73 DATA_TYPE src2 = dst - src13; 74 75 cf = dst < src13; 76#else 77 DATA_TYPE src2 = dst - src1 - src3; 78 79 cf = (src3 ? dst <= src1 : dst < src1); 80#endif 81 82 pf = compute_pf(dst); 83 af = (dst ^ src1 ^ src2) & 0x10; 84 zf = (dst == 0) << 6; 85 sf = lshift(dst, 8 - DATA_BITS) & 0x80; 86 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; 87 return cf + pf + af + zf + sf + of; 88} 89 90static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, 91 DATA_TYPE src3) 92{ 93#ifdef WIDER_TYPE 94 WIDER_TYPE src13 = (WIDER_TYPE) src1 + (WIDER_TYPE) src3; 95 96 return dst < src13; 97#else 98 return src3 ? dst <= src1 : dst < src1; 99#endif 100} 101 102static uint32_t glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) 103{ 104 uint32_t cf, pf, af, zf, sf, of; 105 DATA_TYPE src1 = dst + src2; 106 107 cf = src1 < src2; 108 pf = compute_pf(dst); 109 af = (dst ^ src1 ^ src2) & CC_A; 110 zf = (dst == 0) * CC_Z; 111 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 112 of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; 113 return cf + pf + af + zf + sf + of; 114} 115 116static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) 117{ 118 DATA_TYPE src1 = dst + src2; 119 120 return src1 < src2; 121} 122 123static uint32_t glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, 124 DATA_TYPE src3) 125{ 126 uint32_t cf, pf, af, zf, sf, of; 127 128#ifdef WIDER_TYPE 129 WIDER_TYPE src23 = (WIDER_TYPE) src2 + (WIDER_TYPE) src3; 130 DATA_TYPE src1 = dst + src23; 131 132 cf = src1 < src23; 133#else 134 DATA_TYPE src1 = dst + src2 + src3; 135 136 cf = (src3 ? src1 <= src2 : src1 < src2); 137#endif 138 139 pf = compute_pf(dst); 140 af = (dst ^ src1 ^ src2) & 0x10; 141 zf = (dst == 0) << 6; 142 sf = lshift(dst, 8 - DATA_BITS) & 0x80; 143 of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; 144 return cf + pf + af + zf + sf + of; 145} 146 147static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, 148 DATA_TYPE src3) 149{ 150#ifdef WIDER_TYPE 151 WIDER_TYPE src23 = (WIDER_TYPE) src2 + (WIDER_TYPE) src3; 152 DATA_TYPE src1 = dst + src23; 153 154 return src1 < src23; 155#else 156 DATA_TYPE src1 = dst + src2 + src3; 157 158 return (src3 ? src1 <= src2 : src1 < src2); 159#endif 160} 161 162static uint32_t glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 163{ 164 uint32_t cf, pf, af, zf, sf, of; 165 166 cf = 0; 167 pf = compute_pf(dst); 168 af = 0; 169 zf = (dst == 0) * CC_Z; 170 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 171 of = 0; 172 return cf + pf + af + zf + sf + of; 173} 174 175static uint32_t glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 176{ 177 uint32_t cf, pf, af, zf, sf, of; 178 DATA_TYPE src2; 179 180 cf = src1; 181 src1 = dst - 1; 182 src2 = 1; 183 pf = compute_pf(dst); 184 af = (dst ^ src1 ^ src2) & CC_A; 185 zf = (dst == 0) * CC_Z; 186 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 187 of = (dst == SIGN_MASK) * CC_O; 188 return cf + pf + af + zf + sf + of; 189} 190 191static uint32_t glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 192{ 193 uint32_t cf, pf, af, zf, sf, of; 194 DATA_TYPE src2; 195 196 cf = src1; 197 src1 = dst + 1; 198 src2 = 1; 199 pf = compute_pf(dst); 200 af = (dst ^ src1 ^ src2) & CC_A; 201 zf = (dst == 0) * CC_Z; 202 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 203 of = (dst == SIGN_MASK - 1) * CC_O; 204 return cf + pf + af + zf + sf + of; 205} 206 207static uint32_t glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 208{ 209 uint32_t cf, pf, af, zf, sf, of; 210 211 cf = (src1 >> (DATA_BITS - 1)) & CC_C; 212 pf = compute_pf(dst); 213 af = 0; /* undefined */ 214 zf = (dst == 0) * CC_Z; 215 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 216 /* of is defined iff shift count == 1 */ 217 of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O; 218 return cf + pf + af + zf + sf + of; 219} 220 221static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 222{ 223 return (src1 >> (DATA_BITS - 1)) & CC_C; 224} 225 226static uint32_t glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 227{ 228 uint32_t cf, pf, af, zf, sf, of; 229 230 cf = src1 & 1; 231 pf = compute_pf(dst); 232 af = 0; /* undefined */ 233 zf = (dst == 0) * CC_Z; 234 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 235 /* of is defined iff shift count == 1 */ 236 of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O; 237 return cf + pf + af + zf + sf + of; 238} 239 240/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and 241 CF are modified and it is slower to do that. Note as well that we 242 don't truncate SRC1 for computing carry to DATA_TYPE. */ 243static uint32_t glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1) 244{ 245 uint32_t cf, pf, af, zf, sf, of; 246 247 cf = (src1 != 0); 248 pf = compute_pf(dst); 249 af = 0; /* undefined */ 250 zf = (dst == 0) * CC_Z; 251 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 252 of = cf * CC_O; 253 return cf + pf + af + zf + sf + of; 254} 255 256static uint32_t glue(compute_all_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 257{ 258 uint32_t cf, pf, af, zf, sf, of; 259 260 cf = (src1 == 0); 261 pf = 0; /* undefined */ 262 af = 0; /* undefined */ 263 zf = (dst == 0) * CC_Z; 264 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 265 of = 0; 266 return cf + pf + af + zf + sf + of; 267} 268 269static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 270{ 271 return src1 == 0; 272} 273 274static int glue(compute_all_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 275{ 276 uint32_t cf, pf, af, zf, sf, of; 277 278 cf = (src1 != 0); 279 pf = 0; /* undefined */ 280 af = 0; /* undefined */ 281 zf = (dst == 0) * CC_Z; 282 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 283 of = 0; 284 return cf + pf + af + zf + sf + of; 285} 286 287static int glue(compute_c_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 288{ 289 return src1 != 0; 290} 291 292#undef DATA_BITS 293#undef SIGN_MASK 294#undef DATA_TYPE 295#undef DATA_MASK 296#undef SUFFIX 297#undef WIDER_TYPE 298