1/* 2 * i386 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, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA 19 */ 20#define DATA_BITS (1 << (3 + SHIFT)) 21#define SHIFT_MASK (DATA_BITS - 1) 22#define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1)) 23#if DATA_BITS <= 32 24#define SHIFT1_MASK 0x1f 25#else 26#define SHIFT1_MASK 0x3f 27#endif 28 29#if DATA_BITS == 8 30#define SUFFIX b 31#define DATA_TYPE uint8_t 32#define DATA_STYPE int8_t 33#define DATA_MASK 0xff 34#elif DATA_BITS == 16 35#define SUFFIX w 36#define DATA_TYPE uint16_t 37#define DATA_STYPE int16_t 38#define DATA_MASK 0xffff 39#elif DATA_BITS == 32 40#define SUFFIX l 41#define DATA_TYPE uint32_t 42#define DATA_STYPE int32_t 43#define DATA_MASK 0xffffffff 44#elif DATA_BITS == 64 45#define SUFFIX q 46#define DATA_TYPE uint64_t 47#define DATA_STYPE int64_t 48#define DATA_MASK 0xffffffffffffffffULL 49#else 50#error unhandled operand size 51#endif 52 53/* dynamic flags computation */ 54 55static int glue(compute_all_add, SUFFIX)(void) 56{ 57 int cf, pf, af, zf, sf, of; 58 target_long src1, src2; 59 src1 = CC_SRC; 60 src2 = CC_DST - CC_SRC; 61 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1; 62 pf = parity_table[(uint8_t)CC_DST]; 63 af = (CC_DST ^ src1 ^ src2) & 0x10; 64 zf = ((DATA_TYPE)CC_DST == 0) << 6; 65 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 66 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; 67 return cf | pf | af | zf | sf | of; 68} 69 70static int glue(compute_c_add, SUFFIX)(void) 71{ 72 int cf; 73 target_long src1; 74 src1 = CC_SRC; 75 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1; 76 return cf; 77} 78 79static int glue(compute_all_adc, SUFFIX)(void) 80{ 81 int cf, pf, af, zf, sf, of; 82 target_long src1, src2; 83 src1 = CC_SRC; 84 src2 = CC_DST - CC_SRC - 1; 85 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1; 86 pf = parity_table[(uint8_t)CC_DST]; 87 af = (CC_DST ^ src1 ^ src2) & 0x10; 88 zf = ((DATA_TYPE)CC_DST == 0) << 6; 89 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 90 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; 91 return cf | pf | af | zf | sf | of; 92} 93 94static int glue(compute_c_adc, SUFFIX)(void) 95{ 96 int cf; 97 target_long src1; 98 src1 = CC_SRC; 99 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1; 100 return cf; 101} 102 103static int glue(compute_all_sub, SUFFIX)(void) 104{ 105 int cf, pf, af, zf, sf, of; 106 target_long src1, src2; 107 src1 = CC_DST + CC_SRC; 108 src2 = CC_SRC; 109 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; 110 pf = parity_table[(uint8_t)CC_DST]; 111 af = (CC_DST ^ src1 ^ src2) & 0x10; 112 zf = ((DATA_TYPE)CC_DST == 0) << 6; 113 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 114 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; 115 return cf | pf | af | zf | sf | of; 116} 117 118static int glue(compute_c_sub, SUFFIX)(void) 119{ 120 int cf; 121 target_long src1, src2; 122 src1 = CC_DST + CC_SRC; 123 src2 = CC_SRC; 124 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; 125 return cf; 126} 127 128static int glue(compute_all_sbb, SUFFIX)(void) 129{ 130 int cf, pf, af, zf, sf, of; 131 target_long src1, src2; 132 src1 = CC_DST + CC_SRC + 1; 133 src2 = CC_SRC; 134 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; 135 pf = parity_table[(uint8_t)CC_DST]; 136 af = (CC_DST ^ src1 ^ src2) & 0x10; 137 zf = ((DATA_TYPE)CC_DST == 0) << 6; 138 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 139 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; 140 return cf | pf | af | zf | sf | of; 141} 142 143static int glue(compute_c_sbb, SUFFIX)(void) 144{ 145 int cf; 146 target_long src1, src2; 147 src1 = CC_DST + CC_SRC + 1; 148 src2 = CC_SRC; 149 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; 150 return cf; 151} 152 153static int glue(compute_all_logic, SUFFIX)(void) 154{ 155 int cf, pf, af, zf, sf, of; 156 cf = 0; 157 pf = parity_table[(uint8_t)CC_DST]; 158 af = 0; 159 zf = ((DATA_TYPE)CC_DST == 0) << 6; 160 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 161 of = 0; 162 return cf | pf | af | zf | sf | of; 163} 164 165static int glue(compute_c_logic, SUFFIX)(void) 166{ 167 return 0; 168} 169 170static int glue(compute_all_inc, SUFFIX)(void) 171{ 172 int cf, pf, af, zf, sf, of; 173 target_long src1, src2; 174 src1 = CC_DST - 1; 175 src2 = 1; 176 cf = CC_SRC; 177 pf = parity_table[(uint8_t)CC_DST]; 178 af = (CC_DST ^ src1 ^ src2) & 0x10; 179 zf = ((DATA_TYPE)CC_DST == 0) << 6; 180 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 181 of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11; 182 return cf | pf | af | zf | sf | of; 183} 184 185#if DATA_BITS == 32 186static int glue(compute_c_inc, SUFFIX)(void) 187{ 188 return CC_SRC; 189} 190#endif 191 192static int glue(compute_all_dec, SUFFIX)(void) 193{ 194 int cf, pf, af, zf, sf, of; 195 target_long src1, src2; 196 src1 = CC_DST + 1; 197 src2 = 1; 198 cf = CC_SRC; 199 pf = parity_table[(uint8_t)CC_DST]; 200 af = (CC_DST ^ src1 ^ src2) & 0x10; 201 zf = ((DATA_TYPE)CC_DST == 0) << 6; 202 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 203 of = ((CC_DST & DATA_MASK) == ((target_ulong)SIGN_MASK - 1)) << 11; 204 return cf | pf | af | zf | sf | of; 205} 206 207static int glue(compute_all_shl, SUFFIX)(void) 208{ 209 int cf, pf, af, zf, sf, of; 210 cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C; 211 pf = parity_table[(uint8_t)CC_DST]; 212 af = 0; /* undefined */ 213 zf = ((DATA_TYPE)CC_DST == 0) << 6; 214 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 215 /* of is defined if shift count == 1 */ 216 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O; 217 return cf | pf | af | zf | sf | of; 218} 219 220static int glue(compute_c_shl, SUFFIX)(void) 221{ 222 return (CC_SRC >> (DATA_BITS - 1)) & CC_C; 223} 224 225#if DATA_BITS == 32 226static int glue(compute_c_sar, SUFFIX)(void) 227{ 228 return CC_SRC & 1; 229} 230#endif 231 232static int glue(compute_all_sar, SUFFIX)(void) 233{ 234 int cf, pf, af, zf, sf, of; 235 cf = CC_SRC & 1; 236 pf = parity_table[(uint8_t)CC_DST]; 237 af = 0; /* undefined */ 238 zf = ((DATA_TYPE)CC_DST == 0) << 6; 239 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 240 /* of is defined if shift count == 1 */ 241 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O; 242 return cf | pf | af | zf | sf | of; 243} 244 245#if DATA_BITS == 32 246static int glue(compute_c_mul, SUFFIX)(void) 247{ 248 int cf; 249 cf = (CC_SRC != 0); 250 return cf; 251} 252#endif 253 254/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and 255 CF are modified and it is slower to do that. */ 256static int glue(compute_all_mul, SUFFIX)(void) 257{ 258 int cf, pf, af, zf, sf, of; 259 cf = (CC_SRC != 0); 260 pf = parity_table[(uint8_t)CC_DST]; 261 af = 0; /* undefined */ 262 zf = ((DATA_TYPE)CC_DST == 0) << 6; 263 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 264 of = cf << 11; 265 return cf | pf | af | zf | sf | of; 266} 267 268/* shifts */ 269 270target_ulong glue(helper_rcl, SUFFIX)(target_ulong t0, target_ulong t1) 271{ 272 int count, eflags; 273 target_ulong src; 274 target_long res; 275 276 count = t1 & SHIFT1_MASK; 277#if DATA_BITS == 16 278 count = rclw_table[count]; 279#elif DATA_BITS == 8 280 count = rclb_table[count]; 281#endif 282 if (count) { 283 eflags = helper_cc_compute_all(CC_OP); 284 t0 &= DATA_MASK; 285 src = t0; 286 res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1)); 287 if (count > 1) 288 res |= t0 >> (DATA_BITS + 1 - count); 289 t0 = res; 290 env->cc_tmp = (eflags & ~(CC_C | CC_O)) | 291 (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | 292 ((src >> (DATA_BITS - count)) & CC_C); 293 } else { 294 env->cc_tmp = -1; 295 } 296 return t0; 297} 298 299target_ulong glue(helper_rcr, SUFFIX)(target_ulong t0, target_ulong t1) 300{ 301 int count, eflags; 302 target_ulong src; 303 target_long res; 304 305 count = t1 & SHIFT1_MASK; 306#if DATA_BITS == 16 307 count = rclw_table[count]; 308#elif DATA_BITS == 8 309 count = rclb_table[count]; 310#endif 311 if (count) { 312 eflags = helper_cc_compute_all(CC_OP); 313 t0 &= DATA_MASK; 314 src = t0; 315 res = (t0 >> count) | ((target_ulong)(eflags & CC_C) << (DATA_BITS - count)); 316 if (count > 1) 317 res |= t0 << (DATA_BITS + 1 - count); 318 t0 = res; 319 env->cc_tmp = (eflags & ~(CC_C | CC_O)) | 320 (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | 321 ((src >> (count - 1)) & CC_C); 322 } else { 323 env->cc_tmp = -1; 324 } 325 return t0; 326} 327 328#undef DATA_BITS 329#undef SHIFT_MASK 330#undef SHIFT1_MASK 331#undef SIGN_MASK 332#undef DATA_TYPE 333#undef DATA_STYPE 334#undef DATA_MASK 335#undef SUFFIX 336