1 /* 2 * ARM helper routines 3 * 4 * Copyright (c) 2005-2007 CodeSourcery, LLC 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 #include "exec.h" 21 #include "helpers.h" 22 23 #define SIGNBIT (uint32_t)0x80000000 24 #define SIGNBIT64 ((uint64_t)1 << 63) 25 26 void raise_exception(int tt) 27 { 28 env->exception_index = tt; 29 cpu_loop_exit(); 30 } 31 32 /* thread support */ 33 34 static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; 35 36 void cpu_lock(void) 37 { 38 spin_lock(&global_cpu_lock); 39 } 40 41 void cpu_unlock(void) 42 { 43 spin_unlock(&global_cpu_lock); 44 } 45 46 uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, 47 uint32_t rn, uint32_t maxindex) 48 { 49 uint32_t val; 50 uint32_t tmp; 51 int index; 52 int shift; 53 uint64_t *table; 54 table = (uint64_t *)&env->vfp.regs[rn]; 55 val = 0; 56 for (shift = 0; shift < 32; shift += 8) { 57 index = (ireg >> shift) & 0xff; 58 if (index < maxindex) { 59 tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff; 60 val |= tmp << shift; 61 } else { 62 val |= def & (0xff << shift); 63 } 64 } 65 return val; 66 } 67 68 #if !defined(CONFIG_USER_ONLY) 69 70 static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr); 71 72 #define MMUSUFFIX _mmu 73 //#define ALIGNED_ONLY 1 74 75 #define SHIFT 0 76 #include "softmmu_template.h" 77 78 #define SHIFT 1 79 #include "softmmu_template.h" 80 81 #define SHIFT 2 82 #include "softmmu_template.h" 83 84 #define SHIFT 3 85 #include "softmmu_template.h" 86 87 static void do_unaligned_access (target_ulong addr, int is_write, int mmu_idx, void *retaddr) 88 { 89 //printf("::UNALIGNED:: addr=%lx is_write=%d is_user=%d retaddr=%p\n", addr, is_write, is_user, retaddr); 90 if (mmu_idx) 91 { 92 env = cpu_single_env; 93 env->cp15.c5_data = 0x00000001; /* corresponds to an alignment fault */ 94 env->cp15.c6_data = addr; 95 env->exception_index = EXCP_DATA_ABORT; 96 cpu_loop_exit(); 97 } 98 } 99 100 /* try to fill the TLB and return an exception if error. If retaddr is 101 NULL, it means that the function was called in C code (i.e. not 102 from generated code or from helper.c) */ 103 /* XXX: fix it to restore all registers */ 104 void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) 105 { 106 TranslationBlock *tb; 107 CPUState *saved_env; 108 unsigned long pc; 109 int ret; 110 111 /* XXX: hack to restore env in all cases, even if not called from 112 generated code */ 113 saved_env = env; 114 env = cpu_single_env; 115 ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); 116 if (unlikely(ret)) { 117 if (retaddr) { 118 /* now we have a real cpu fault */ 119 pc = (unsigned long)retaddr; 120 tb = tb_find_pc(pc); 121 if (tb) { 122 /* the PC is inside the translated code. It means that we have 123 a virtual CPU fault */ 124 cpu_restore_state(tb, env, pc, NULL); 125 } 126 } 127 raise_exception(env->exception_index); 128 } 129 env = saved_env; 130 } 131 132 /* copy a string from the simulated virtual space to a buffer in QEMU */ 133 void vstrcpy(target_ulong ptr, char *buf, int max) 134 { 135 int index; 136 137 if (buf == NULL) return; 138 139 for (index = 0; index < max; index += 1) { 140 cpu_physical_memory_read(ptr + index, buf + index, 1); 141 if (buf[index] == 0) 142 break; 143 } 144 } 145 #endif 146 147 /* FIXME: Pass an axplicit pointer to QF to CPUState, and move saturating 148 instructions into helper.c */ 149 uint32_t HELPER(add_setq)(uint32_t a, uint32_t b) 150 { 151 uint32_t res = a + b; 152 if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) 153 env->QF = 1; 154 return res; 155 } 156 157 uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b) 158 { 159 uint32_t res = a + b; 160 if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) { 161 env->QF = 1; 162 res = ~(((int32_t)a >> 31) ^ SIGNBIT); 163 } 164 return res; 165 } 166 167 uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b) 168 { 169 uint32_t res = a - b; 170 if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) { 171 env->QF = 1; 172 res = ~(((int32_t)a >> 31) ^ SIGNBIT); 173 } 174 return res; 175 } 176 177 uint32_t HELPER(double_saturate)(int32_t val) 178 { 179 uint32_t res; 180 if (val >= 0x40000000) { 181 res = ~SIGNBIT; 182 env->QF = 1; 183 } else if (val <= (int32_t)0xc0000000) { 184 res = SIGNBIT; 185 env->QF = 1; 186 } else { 187 res = val << 1; 188 } 189 return res; 190 } 191 192 uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b) 193 { 194 uint32_t res = a + b; 195 if (res < a) { 196 env->QF = 1; 197 res = ~0; 198 } 199 return res; 200 } 201 202 uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b) 203 { 204 uint32_t res = a - b; 205 if (res > a) { 206 env->QF = 1; 207 res = 0; 208 } 209 return res; 210 } 211 212 /* Signed saturation. */ 213 static inline uint32_t do_ssat(int32_t val, int shift) 214 { 215 int32_t top; 216 uint32_t mask; 217 218 top = val >> shift; 219 mask = (1u << shift) - 1; 220 if (top > 0) { 221 env->QF = 1; 222 return mask; 223 } else if (top < -1) { 224 env->QF = 1; 225 return ~mask; 226 } 227 return val; 228 } 229 230 /* Unsigned saturation. */ 231 static inline uint32_t do_usat(int32_t val, int shift) 232 { 233 uint32_t max; 234 235 max = (1u << shift) - 1; 236 if (val < 0) { 237 env->QF = 1; 238 return 0; 239 } else if (val > max) { 240 env->QF = 1; 241 return max; 242 } 243 return val; 244 } 245 246 /* Signed saturate. */ 247 uint32_t HELPER(ssat)(uint32_t x, uint32_t shift) 248 { 249 return do_ssat(x, shift); 250 } 251 252 /* Dual halfword signed saturate. */ 253 uint32_t HELPER(ssat16)(uint32_t x, uint32_t shift) 254 { 255 uint32_t res; 256 257 res = (uint16_t)do_ssat((int16_t)x, shift); 258 res |= do_ssat(((int32_t)x) >> 16, shift) << 16; 259 return res; 260 } 261 262 /* Unsigned saturate. */ 263 uint32_t HELPER(usat)(uint32_t x, uint32_t shift) 264 { 265 return do_usat(x, shift); 266 } 267 268 /* Dual halfword unsigned saturate. */ 269 uint32_t HELPER(usat16)(uint32_t x, uint32_t shift) 270 { 271 uint32_t res; 272 273 res = (uint16_t)do_usat((int16_t)x, shift); 274 res |= do_usat(((int32_t)x) >> 16, shift) << 16; 275 return res; 276 } 277 278 void HELPER(wfi)(void) 279 { 280 env->exception_index = EXCP_HLT; 281 env->halted = 1; 282 cpu_loop_exit(); 283 } 284 285 void HELPER(exception)(uint32_t excp) 286 { 287 env->exception_index = excp; 288 cpu_loop_exit(); 289 } 290 291 uint32_t HELPER(cpsr_read)(void) 292 { 293 return cpsr_read(env) & ~CPSR_EXEC; 294 } 295 296 void HELPER(cpsr_write)(uint32_t val, uint32_t mask) 297 { 298 cpsr_write(env, val, mask); 299 } 300 301 /* Access to user mode registers from privileged modes. */ 302 uint32_t HELPER(get_user_reg)(uint32_t regno) 303 { 304 uint32_t val; 305 306 if (regno == 13) { 307 val = env->banked_r13[0]; 308 } else if (regno == 14) { 309 val = env->banked_r14[0]; 310 } else if (regno >= 8 311 && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { 312 val = env->usr_regs[regno - 8]; 313 } else { 314 val = env->regs[regno]; 315 } 316 return val; 317 } 318 319 void HELPER(set_user_reg)(uint32_t regno, uint32_t val) 320 { 321 if (regno == 13) { 322 env->banked_r13[0] = val; 323 } else if (regno == 14) { 324 env->banked_r14[0] = val; 325 } else if (regno >= 8 326 && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { 327 env->usr_regs[regno - 8] = val; 328 } else { 329 env->regs[regno] = val; 330 } 331 } 332 333 /* ??? Flag setting arithmetic is awkward because we need to do comparisons. 334 The only way to do that in TCG is a conditional branch, which clobbers 335 all our temporaries. For now implement these as helper functions. */ 336 337 uint32_t HELPER (add_cc)(uint32_t a, uint32_t b) 338 { 339 uint32_t result; 340 result = a + b; 341 env->NF = env->ZF = result; 342 env->CF = result < a; 343 env->VF = (a ^ b ^ -1) & (a ^ result); 344 return result; 345 } 346 347 uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b) 348 { 349 uint32_t result; 350 if (!env->CF) { 351 result = a + b; 352 env->CF = result < a; 353 } else { 354 result = a + b + 1; 355 env->CF = result <= a; 356 } 357 env->VF = (a ^ b ^ -1) & (a ^ result); 358 env->NF = env->ZF = result; 359 return result; 360 } 361 362 uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b) 363 { 364 uint32_t result; 365 result = a - b; 366 env->NF = env->ZF = result; 367 env->CF = a >= b; 368 env->VF = (a ^ b) & (a ^ result); 369 return result; 370 } 371 372 uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b) 373 { 374 uint32_t result; 375 if (!env->CF) { 376 result = a - b - 1; 377 env->CF = a > b; 378 } else { 379 result = a - b; 380 env->CF = a >= b; 381 } 382 env->VF = (a ^ b) & (a ^ result); 383 env->NF = env->ZF = result; 384 return result; 385 } 386 387 /* Similarly for variable shift instructions. */ 388 389 uint32_t HELPER(shl)(uint32_t x, uint32_t i) 390 { 391 int shift = i & 0xff; 392 if (shift >= 32) 393 return 0; 394 return x << shift; 395 } 396 397 uint32_t HELPER(shr)(uint32_t x, uint32_t i) 398 { 399 int shift = i & 0xff; 400 if (shift >= 32) 401 return 0; 402 return (uint32_t)x >> shift; 403 } 404 405 uint32_t HELPER(sar)(uint32_t x, uint32_t i) 406 { 407 int shift = i & 0xff; 408 if (shift >= 32) 409 shift = 31; 410 return (int32_t)x >> shift; 411 } 412 413 uint32_t HELPER(ror)(uint32_t x, uint32_t i) 414 { 415 int shift = i & 0xff; 416 if (shift == 0) 417 return x; 418 return (x >> shift) | (x << (32 - shift)); 419 } 420 421 uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) 422 { 423 int shift = i & 0xff; 424 if (shift >= 32) { 425 if (shift == 32) 426 env->CF = x & 1; 427 else 428 env->CF = 0; 429 return 0; 430 } else if (shift != 0) { 431 env->CF = (x >> (32 - shift)) & 1; 432 return x << shift; 433 } 434 return x; 435 } 436 437 uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i) 438 { 439 int shift = i & 0xff; 440 if (shift >= 32) { 441 if (shift == 32) 442 env->CF = (x >> 31) & 1; 443 else 444 env->CF = 0; 445 return 0; 446 } else if (shift != 0) { 447 env->CF = (x >> (shift - 1)) & 1; 448 return x >> shift; 449 } 450 return x; 451 } 452 453 uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i) 454 { 455 int shift = i & 0xff; 456 if (shift >= 32) { 457 env->CF = (x >> 31) & 1; 458 return (int32_t)x >> 31; 459 } else if (shift != 0) { 460 env->CF = (x >> (shift - 1)) & 1; 461 return (int32_t)x >> shift; 462 } 463 return x; 464 } 465 466 uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i) 467 { 468 int shift1, shift; 469 shift1 = i & 0xff; 470 shift = shift1 & 0x1f; 471 if (shift == 0) { 472 if (shift1 != 0) 473 env->CF = (x >> 31) & 1; 474 return x; 475 } else { 476 env->CF = (x >> (shift - 1)) & 1; 477 return ((uint32_t)x >> shift) | (x << (32 - shift)); 478 } 479 } 480 481 uint64_t HELPER(neon_add_saturate_s64)(uint64_t src1, uint64_t src2) 482 { 483 uint64_t res; 484 485 res = src1 + src2; 486 if (((res ^ src1) & SIGNBIT64) && !((src1 ^ src2) & SIGNBIT64)) { 487 env->QF = 1; 488 res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64; 489 } 490 return res; 491 } 492 493 uint64_t HELPER(neon_add_saturate_u64)(uint64_t src1, uint64_t src2) 494 { 495 uint64_t res; 496 497 res = src1 + src2; 498 if (res < src1) { 499 env->QF = 1; 500 res = ~(uint64_t)0; 501 } 502 return res; 503 } 504 505 uint64_t HELPER(neon_sub_saturate_s64)(uint64_t src1, uint64_t src2) 506 { 507 uint64_t res; 508 509 res = src1 - src2; 510 if (((res ^ src1) & SIGNBIT64) && ((src1 ^ src2) & SIGNBIT64)) { 511 env->QF = 1; 512 res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64; 513 } 514 return res; 515 } 516 517 uint64_t HELPER(neon_sub_saturate_u64)(uint64_t src1, uint64_t src2) 518 { 519 uint64_t res; 520 521 if (src1 < src2) { 522 env->QF = 1; 523 res = 0; 524 } else { 525 res = src1 - src2; 526 } 527 return res; 528 } 529 530 /* These need to return a pair of value, so still use T0/T1. */ 531 /* Transpose. Argument order is rather strange to avoid special casing 532 the tranlation code. 533 On input T0 = rm, T1 = rd. On output T0 = rd, T1 = rm */ 534 void HELPER(neon_trn_u8)(void) 535 { 536 uint32_t rd; 537 uint32_t rm; 538 rd = ((T0 & 0x00ff00ff) << 8) | (T1 & 0x00ff00ff); 539 rm = ((T1 & 0xff00ff00) >> 8) | (T0 & 0xff00ff00); 540 T0 = rd; 541 T1 = rm; 542 } 543 544 void HELPER(neon_trn_u16)(void) 545 { 546 uint32_t rd; 547 uint32_t rm; 548 rd = (T0 << 16) | (T1 & 0xffff); 549 rm = (T1 >> 16) | (T0 & 0xffff0000); 550 T0 = rd; 551 T1 = rm; 552 } 553 554 /* Worker routines for zip and unzip. */ 555 void HELPER(neon_unzip_u8)(void) 556 { 557 uint32_t rd; 558 uint32_t rm; 559 rd = (T0 & 0xff) | ((T0 >> 8) & 0xff00) 560 | ((T1 << 16) & 0xff0000) | ((T1 << 8) & 0xff000000); 561 rm = ((T0 >> 8) & 0xff) | ((T0 >> 16) & 0xff00) 562 | ((T1 << 8) & 0xff0000) | (T1 & 0xff000000); 563 T0 = rd; 564 T1 = rm; 565 } 566 567 void HELPER(neon_zip_u8)(void) 568 { 569 uint32_t rd; 570 uint32_t rm; 571 rd = (T0 & 0xff) | ((T1 << 8) & 0xff00) 572 | ((T0 << 16) & 0xff0000) | ((T1 << 24) & 0xff000000); 573 rm = ((T0 >> 16) & 0xff) | ((T1 >> 8) & 0xff00) 574 | ((T0 >> 8) & 0xff0000) | (T1 & 0xff000000); 575 T0 = rd; 576 T1 = rm; 577 } 578 579 void HELPER(neon_zip_u16)(void) 580 { 581 uint32_t tmp; 582 583 tmp = (T0 & 0xffff) | (T1 << 16); 584 T1 = (T1 & 0xffff0000) | (T0 >> 16); 585 T0 = tmp; 586 } 587