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