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