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#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 42static 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 56static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 57{ 58 return dst < src1; 59} 60 61static 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 76static 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 82static 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 96static 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 103static 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 118static 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 126static 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 139static 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 155static 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 171static 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 185static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 186{ 187 return (src1 >> (DATA_BITS - 1)) & CC_C; 188} 189 190static 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. */ 207static 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 220static 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 238static int glue(compute_all_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 239{ 240 int cf, pf, af, zf, sf, of; 241 242 cf = (src1 != 0); 243 pf = 0; /* undefined */ 244 af = 0; /* undefined */ 245 zf = (dst == 0) * CC_Z; 246 sf = lshift(dst, 8 - DATA_BITS) & CC_S; 247 of = 0; 248 return cf | pf | af | zf | sf | of; 249} 250 251static int glue(compute_c_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) 252{ 253 return src1 != 0; 254} 255 256#undef DATA_BITS 257#undef SIGN_MASK 258#undef DATA_TYPE 259#undef DATA_MASK 260#undef SUFFIX 261