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 55 static 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 70 static 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 79 static 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 94 static 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 103 static 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 118 static 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 128 static 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 143 static 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 153 static 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 165 static int glue(compute_c_logic, SUFFIX)(void) 166 { 167 return 0; 168 } 169 170 static 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 186 static int glue(compute_c_inc, SUFFIX)(void) 187 { 188 return CC_SRC; 189 } 190 #endif 191 192 static 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 207 static 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 220 static int glue(compute_c_shl, SUFFIX)(void) 221 { 222 return (CC_SRC >> (DATA_BITS - 1)) & CC_C; 223 } 224 225 #if DATA_BITS == 32 226 static int glue(compute_c_sar, SUFFIX)(void) 227 { 228 return CC_SRC & 1; 229 } 230 #endif 231 232 static 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 246 static 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. */ 256 static 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 270 target_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 299 target_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