1 /* 2 * PowerPC memory access emulation helpers for QEMU. 3 * 4 * Copyright (c) 2003-2007 Jocelyn Mayer 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 20 #include "qemu/osdep.h" 21 #include "cpu.h" 22 #include "exec/exec-all.h" 23 #include "qemu/host-utils.h" 24 #include "qemu/main-loop.h" 25 #include "exec/helper-proto.h" 26 #include "helper_regs.h" 27 #include "exec/cpu_ldst.h" 28 #include "tcg.h" 29 #include "internal.h" 30 #include "qemu/atomic128.h" 31 32 /* #define DEBUG_OP */ 33 34 static inline bool needs_byteswap(const CPUPPCState *env) 35 { 36 #if defined(TARGET_WORDS_BIGENDIAN) 37 return msr_le; 38 #else 39 return !msr_le; 40 #endif 41 } 42 43 /*****************************************************************************/ 44 /* Memory load and stores */ 45 46 static inline target_ulong addr_add(CPUPPCState *env, target_ulong addr, 47 target_long arg) 48 { 49 #if defined(TARGET_PPC64) 50 if (!msr_is_64bit(env, env->msr)) { 51 return (uint32_t)(addr + arg); 52 } else 53 #endif 54 { 55 return addr + arg; 56 } 57 } 58 59 void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg) 60 { 61 for (; reg < 32; reg++) { 62 if (needs_byteswap(env)) { 63 env->gpr[reg] = bswap32(cpu_ldl_data_ra(env, addr, GETPC())); 64 } else { 65 env->gpr[reg] = cpu_ldl_data_ra(env, addr, GETPC()); 66 } 67 addr = addr_add(env, addr, 4); 68 } 69 } 70 71 void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg) 72 { 73 for (; reg < 32; reg++) { 74 if (needs_byteswap(env)) { 75 cpu_stl_data_ra(env, addr, bswap32((uint32_t)env->gpr[reg]), 76 GETPC()); 77 } else { 78 cpu_stl_data_ra(env, addr, (uint32_t)env->gpr[reg], GETPC()); 79 } 80 addr = addr_add(env, addr, 4); 81 } 82 } 83 84 static void do_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, 85 uint32_t reg, uintptr_t raddr) 86 { 87 int sh; 88 89 for (; nb > 3; nb -= 4) { 90 env->gpr[reg] = cpu_ldl_data_ra(env, addr, raddr); 91 reg = (reg + 1) % 32; 92 addr = addr_add(env, addr, 4); 93 } 94 if (unlikely(nb > 0)) { 95 env->gpr[reg] = 0; 96 for (sh = 24; nb > 0; nb--, sh -= 8) { 97 env->gpr[reg] |= cpu_ldub_data_ra(env, addr, raddr) << sh; 98 addr = addr_add(env, addr, 1); 99 } 100 } 101 } 102 103 void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t reg) 104 { 105 do_lsw(env, addr, nb, reg, GETPC()); 106 } 107 108 /* 109 * PPC32 specification says we must generate an exception if rA is in 110 * the range of registers to be loaded. In an other hand, IBM says 111 * this is valid, but rA won't be loaded. For now, I'll follow the 112 * spec... 113 */ 114 void helper_lswx(CPUPPCState *env, target_ulong addr, uint32_t reg, 115 uint32_t ra, uint32_t rb) 116 { 117 if (likely(xer_bc != 0)) { 118 int num_used_regs = DIV_ROUND_UP(xer_bc, 4); 119 if (unlikely((ra != 0 && lsw_reg_in_range(reg, num_used_regs, ra)) || 120 lsw_reg_in_range(reg, num_used_regs, rb))) { 121 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 122 POWERPC_EXCP_INVAL | 123 POWERPC_EXCP_INVAL_LSWX, GETPC()); 124 } else { 125 do_lsw(env, addr, xer_bc, reg, GETPC()); 126 } 127 } 128 } 129 130 void helper_stsw(CPUPPCState *env, target_ulong addr, uint32_t nb, 131 uint32_t reg) 132 { 133 int sh; 134 135 for (; nb > 3; nb -= 4) { 136 cpu_stl_data_ra(env, addr, env->gpr[reg], GETPC()); 137 reg = (reg + 1) % 32; 138 addr = addr_add(env, addr, 4); 139 } 140 if (unlikely(nb > 0)) { 141 for (sh = 24; nb > 0; nb--, sh -= 8) { 142 cpu_stb_data_ra(env, addr, (env->gpr[reg] >> sh) & 0xFF, GETPC()); 143 addr = addr_add(env, addr, 1); 144 } 145 } 146 } 147 148 static void dcbz_common(CPUPPCState *env, target_ulong addr, 149 uint32_t opcode, bool epid, uintptr_t retaddr) 150 { 151 target_ulong mask, dcbz_size = env->dcache_line_size; 152 uint32_t i; 153 void *haddr; 154 int mmu_idx = epid ? PPC_TLB_EPID_STORE : env->dmmu_idx; 155 156 #if defined(TARGET_PPC64) 157 /* Check for dcbz vs dcbzl on 970 */ 158 if (env->excp_model == POWERPC_EXCP_970 && 159 !(opcode & 0x00200000) && ((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) { 160 dcbz_size = 32; 161 } 162 #endif 163 164 /* Align address */ 165 mask = ~(dcbz_size - 1); 166 addr &= mask; 167 168 /* Check reservation */ 169 if ((env->reserve_addr & mask) == (addr & mask)) { 170 env->reserve_addr = (target_ulong)-1ULL; 171 } 172 173 /* Try fast path translate */ 174 haddr = tlb_vaddr_to_host(env, addr, MMU_DATA_STORE, mmu_idx); 175 if (haddr) { 176 memset(haddr, 0, dcbz_size); 177 } else { 178 /* Slow path */ 179 for (i = 0; i < dcbz_size; i += 8) { 180 if (epid) { 181 #if !defined(CONFIG_USER_ONLY) 182 /* Does not make sense on USER_ONLY config */ 183 cpu_stq_eps_ra(env, addr + i, 0, retaddr); 184 #endif 185 } else { 186 cpu_stq_data_ra(env, addr + i, 0, retaddr); 187 } 188 } 189 } 190 } 191 192 void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode) 193 { 194 dcbz_common(env, addr, opcode, false, GETPC()); 195 } 196 197 void helper_dcbzep(CPUPPCState *env, target_ulong addr, uint32_t opcode) 198 { 199 dcbz_common(env, addr, opcode, true, GETPC()); 200 } 201 202 void helper_icbi(CPUPPCState *env, target_ulong addr) 203 { 204 addr &= ~(env->dcache_line_size - 1); 205 /* 206 * Invalidate one cache line : 207 * PowerPC specification says this is to be treated like a load 208 * (not a fetch) by the MMU. To be sure it will be so, 209 * do the load "by hand". 210 */ 211 cpu_ldl_data_ra(env, addr, GETPC()); 212 } 213 214 void helper_icbiep(CPUPPCState *env, target_ulong addr) 215 { 216 #if !defined(CONFIG_USER_ONLY) 217 /* See comments above */ 218 addr &= ~(env->dcache_line_size - 1); 219 cpu_ldl_epl_ra(env, addr, GETPC()); 220 #endif 221 } 222 223 /* XXX: to be tested */ 224 target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg, 225 uint32_t ra, uint32_t rb) 226 { 227 int i, c, d; 228 229 d = 24; 230 for (i = 0; i < xer_bc; i++) { 231 c = cpu_ldub_data_ra(env, addr, GETPC()); 232 addr = addr_add(env, addr, 1); 233 /* ra (if not 0) and rb are never modified */ 234 if (likely(reg != rb && (ra == 0 || reg != ra))) { 235 env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d); 236 } 237 if (unlikely(c == xer_cmp)) { 238 break; 239 } 240 if (likely(d != 0)) { 241 d -= 8; 242 } else { 243 d = 24; 244 reg++; 245 reg = reg & 0x1F; 246 } 247 } 248 return i; 249 } 250 251 #ifdef TARGET_PPC64 252 uint64_t helper_lq_le_parallel(CPUPPCState *env, target_ulong addr, 253 uint32_t opidx) 254 { 255 Int128 ret; 256 257 /* We will have raised EXCP_ATOMIC from the translator. */ 258 assert(HAVE_ATOMIC128); 259 ret = helper_atomic_ldo_le_mmu(env, addr, opidx, GETPC()); 260 env->retxh = int128_gethi(ret); 261 return int128_getlo(ret); 262 } 263 264 uint64_t helper_lq_be_parallel(CPUPPCState *env, target_ulong addr, 265 uint32_t opidx) 266 { 267 Int128 ret; 268 269 /* We will have raised EXCP_ATOMIC from the translator. */ 270 assert(HAVE_ATOMIC128); 271 ret = helper_atomic_ldo_be_mmu(env, addr, opidx, GETPC()); 272 env->retxh = int128_gethi(ret); 273 return int128_getlo(ret); 274 } 275 276 void helper_stq_le_parallel(CPUPPCState *env, target_ulong addr, 277 uint64_t lo, uint64_t hi, uint32_t opidx) 278 { 279 Int128 val; 280 281 /* We will have raised EXCP_ATOMIC from the translator. */ 282 assert(HAVE_ATOMIC128); 283 val = int128_make128(lo, hi); 284 helper_atomic_sto_le_mmu(env, addr, val, opidx, GETPC()); 285 } 286 287 void helper_stq_be_parallel(CPUPPCState *env, target_ulong addr, 288 uint64_t lo, uint64_t hi, uint32_t opidx) 289 { 290 Int128 val; 291 292 /* We will have raised EXCP_ATOMIC from the translator. */ 293 assert(HAVE_ATOMIC128); 294 val = int128_make128(lo, hi); 295 helper_atomic_sto_be_mmu(env, addr, val, opidx, GETPC()); 296 } 297 298 uint32_t helper_stqcx_le_parallel(CPUPPCState *env, target_ulong addr, 299 uint64_t new_lo, uint64_t new_hi, 300 uint32_t opidx) 301 { 302 bool success = false; 303 304 /* We will have raised EXCP_ATOMIC from the translator. */ 305 assert(HAVE_CMPXCHG128); 306 307 if (likely(addr == env->reserve_addr)) { 308 Int128 oldv, cmpv, newv; 309 310 cmpv = int128_make128(env->reserve_val2, env->reserve_val); 311 newv = int128_make128(new_lo, new_hi); 312 oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, 313 opidx, GETPC()); 314 success = int128_eq(oldv, cmpv); 315 } 316 env->reserve_addr = -1; 317 return env->so + success * CRF_EQ_BIT; 318 } 319 320 uint32_t helper_stqcx_be_parallel(CPUPPCState *env, target_ulong addr, 321 uint64_t new_lo, uint64_t new_hi, 322 uint32_t opidx) 323 { 324 bool success = false; 325 326 /* We will have raised EXCP_ATOMIC from the translator. */ 327 assert(HAVE_CMPXCHG128); 328 329 if (likely(addr == env->reserve_addr)) { 330 Int128 oldv, cmpv, newv; 331 332 cmpv = int128_make128(env->reserve_val2, env->reserve_val); 333 newv = int128_make128(new_lo, new_hi); 334 oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, 335 opidx, GETPC()); 336 success = int128_eq(oldv, cmpv); 337 } 338 env->reserve_addr = -1; 339 return env->so + success * CRF_EQ_BIT; 340 } 341 #endif 342 343 /*****************************************************************************/ 344 /* Altivec extension helpers */ 345 #if defined(HOST_WORDS_BIGENDIAN) 346 #define HI_IDX 0 347 #define LO_IDX 1 348 #else 349 #define HI_IDX 1 350 #define LO_IDX 0 351 #endif 352 353 /* 354 * We use msr_le to determine index ordering in a vector. However, 355 * byteswapping is not simply controlled by msr_le. We also need to 356 * take into account endianness of the target. This is done for the 357 * little-endian PPC64 user-mode target. 358 */ 359 360 #define LVE(name, access, swap, element) \ 361 void helper_##name(CPUPPCState *env, ppc_avr_t *r, \ 362 target_ulong addr) \ 363 { \ 364 size_t n_elems = ARRAY_SIZE(r->element); \ 365 int adjust = HI_IDX * (n_elems - 1); \ 366 int sh = sizeof(r->element[0]) >> 1; \ 367 int index = (addr & 0xf) >> sh; \ 368 if (msr_le) { \ 369 index = n_elems - index - 1; \ 370 } \ 371 \ 372 if (needs_byteswap(env)) { \ 373 r->element[LO_IDX ? index : (adjust - index)] = \ 374 swap(access(env, addr, GETPC())); \ 375 } else { \ 376 r->element[LO_IDX ? index : (adjust - index)] = \ 377 access(env, addr, GETPC()); \ 378 } \ 379 } 380 #define I(x) (x) 381 LVE(lvebx, cpu_ldub_data_ra, I, u8) 382 LVE(lvehx, cpu_lduw_data_ra, bswap16, u16) 383 LVE(lvewx, cpu_ldl_data_ra, bswap32, u32) 384 #undef I 385 #undef LVE 386 387 #define STVE(name, access, swap, element) \ 388 void helper_##name(CPUPPCState *env, ppc_avr_t *r, \ 389 target_ulong addr) \ 390 { \ 391 size_t n_elems = ARRAY_SIZE(r->element); \ 392 int adjust = HI_IDX * (n_elems - 1); \ 393 int sh = sizeof(r->element[0]) >> 1; \ 394 int index = (addr & 0xf) >> sh; \ 395 if (msr_le) { \ 396 index = n_elems - index - 1; \ 397 } \ 398 \ 399 if (needs_byteswap(env)) { \ 400 access(env, addr, swap(r->element[LO_IDX ? index : \ 401 (adjust - index)]), \ 402 GETPC()); \ 403 } else { \ 404 access(env, addr, r->element[LO_IDX ? index : \ 405 (adjust - index)], GETPC()); \ 406 } \ 407 } 408 #define I(x) (x) 409 STVE(stvebx, cpu_stb_data_ra, I, u8) 410 STVE(stvehx, cpu_stw_data_ra, bswap16, u16) 411 STVE(stvewx, cpu_stl_data_ra, bswap32, u32) 412 #undef I 413 #undef LVE 414 415 #ifdef TARGET_PPC64 416 #define GET_NB(rb) ((rb >> 56) & 0xFF) 417 418 #define VSX_LXVL(name, lj) \ 419 void helper_##name(CPUPPCState *env, target_ulong addr, \ 420 ppc_vsr_t *xt, target_ulong rb) \ 421 { \ 422 ppc_vsr_t t; \ 423 uint64_t nb = GET_NB(rb); \ 424 int i; \ 425 \ 426 t.s128 = int128_zero(); \ 427 if (nb) { \ 428 nb = (nb >= 16) ? 16 : nb; \ 429 if (msr_le && !lj) { \ 430 for (i = 16; i > 16 - nb; i--) { \ 431 t.VsrB(i - 1) = cpu_ldub_data_ra(env, addr, GETPC()); \ 432 addr = addr_add(env, addr, 1); \ 433 } \ 434 } else { \ 435 for (i = 0; i < nb; i++) { \ 436 t.VsrB(i) = cpu_ldub_data_ra(env, addr, GETPC()); \ 437 addr = addr_add(env, addr, 1); \ 438 } \ 439 } \ 440 } \ 441 *xt = t; \ 442 } 443 444 VSX_LXVL(lxvl, 0) 445 VSX_LXVL(lxvll, 1) 446 #undef VSX_LXVL 447 448 #define VSX_STXVL(name, lj) \ 449 void helper_##name(CPUPPCState *env, target_ulong addr, \ 450 ppc_vsr_t *xt, target_ulong rb) \ 451 { \ 452 target_ulong nb = GET_NB(rb); \ 453 int i; \ 454 \ 455 if (!nb) { \ 456 return; \ 457 } \ 458 \ 459 nb = (nb >= 16) ? 16 : nb; \ 460 if (msr_le && !lj) { \ 461 for (i = 16; i > 16 - nb; i--) { \ 462 cpu_stb_data_ra(env, addr, xt->VsrB(i - 1), GETPC()); \ 463 addr = addr_add(env, addr, 1); \ 464 } \ 465 } else { \ 466 for (i = 0; i < nb; i++) { \ 467 cpu_stb_data_ra(env, addr, xt->VsrB(i), GETPC()); \ 468 addr = addr_add(env, addr, 1); \ 469 } \ 470 } \ 471 } 472 473 VSX_STXVL(stxvl, 0) 474 VSX_STXVL(stxvll, 1) 475 #undef VSX_STXVL 476 #undef GET_NB 477 #endif /* TARGET_PPC64 */ 478 479 #undef HI_IDX 480 #undef LO_IDX 481 482 void helper_tbegin(CPUPPCState *env) 483 { 484 /* 485 * As a degenerate implementation, always fail tbegin. The reason 486 * given is "Nesting overflow". The "persistent" bit is set, 487 * providing a hint to the error handler to not retry. The TFIAR 488 * captures the address of the failure, which is this tbegin 489 * instruction. Instruction execution will continue with the next 490 * instruction in memory, which is precisely what we want. 491 */ 492 493 env->spr[SPR_TEXASR] = 494 (1ULL << TEXASR_FAILURE_PERSISTENT) | 495 (1ULL << TEXASR_NESTING_OVERFLOW) | 496 (msr_hv << TEXASR_PRIVILEGE_HV) | 497 (msr_pr << TEXASR_PRIVILEGE_PR) | 498 (1ULL << TEXASR_FAILURE_SUMMARY) | 499 (1ULL << TEXASR_TFIAR_EXACT); 500 env->spr[SPR_TFIAR] = env->nip | (msr_hv << 1) | msr_pr; 501 env->spr[SPR_TFHAR] = env->nip + 4; 502 env->crf[0] = 0xB; /* 0b1010 = transaction failure */ 503 } 504