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 cpu_stq_mmuidx_ra(env, addr + i, 0, mmu_idx, retaddr); 181 } 182 } 183 } 184 185 void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t opcode) 186 { 187 dcbz_common(env, addr, opcode, false, GETPC()); 188 } 189 190 void helper_dcbzep(CPUPPCState *env, target_ulong addr, uint32_t opcode) 191 { 192 dcbz_common(env, addr, opcode, true, GETPC()); 193 } 194 195 void helper_icbi(CPUPPCState *env, target_ulong addr) 196 { 197 addr &= ~(env->dcache_line_size - 1); 198 /* 199 * Invalidate one cache line : 200 * PowerPC specification says this is to be treated like a load 201 * (not a fetch) by the MMU. To be sure it will be so, 202 * do the load "by hand". 203 */ 204 cpu_ldl_data_ra(env, addr, GETPC()); 205 } 206 207 void helper_icbiep(CPUPPCState *env, target_ulong addr) 208 { 209 #if !defined(CONFIG_USER_ONLY) 210 /* See comments above */ 211 addr &= ~(env->dcache_line_size - 1); 212 cpu_ldl_mmuidx_ra(env, addr, PPC_TLB_EPID_LOAD, GETPC()); 213 #endif 214 } 215 216 /* XXX: to be tested */ 217 target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg, 218 uint32_t ra, uint32_t rb) 219 { 220 int i, c, d; 221 222 d = 24; 223 for (i = 0; i < xer_bc; i++) { 224 c = cpu_ldub_data_ra(env, addr, GETPC()); 225 addr = addr_add(env, addr, 1); 226 /* ra (if not 0) and rb are never modified */ 227 if (likely(reg != rb && (ra == 0 || reg != ra))) { 228 env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d); 229 } 230 if (unlikely(c == xer_cmp)) { 231 break; 232 } 233 if (likely(d != 0)) { 234 d -= 8; 235 } else { 236 d = 24; 237 reg++; 238 reg = reg & 0x1F; 239 } 240 } 241 return i; 242 } 243 244 #ifdef TARGET_PPC64 245 uint64_t helper_lq_le_parallel(CPUPPCState *env, target_ulong addr, 246 uint32_t opidx) 247 { 248 Int128 ret; 249 250 /* We will have raised EXCP_ATOMIC from the translator. */ 251 assert(HAVE_ATOMIC128); 252 ret = helper_atomic_ldo_le_mmu(env, addr, opidx, GETPC()); 253 env->retxh = int128_gethi(ret); 254 return int128_getlo(ret); 255 } 256 257 uint64_t helper_lq_be_parallel(CPUPPCState *env, target_ulong addr, 258 uint32_t opidx) 259 { 260 Int128 ret; 261 262 /* We will have raised EXCP_ATOMIC from the translator. */ 263 assert(HAVE_ATOMIC128); 264 ret = helper_atomic_ldo_be_mmu(env, addr, opidx, GETPC()); 265 env->retxh = int128_gethi(ret); 266 return int128_getlo(ret); 267 } 268 269 void helper_stq_le_parallel(CPUPPCState *env, target_ulong addr, 270 uint64_t lo, uint64_t hi, uint32_t opidx) 271 { 272 Int128 val; 273 274 /* We will have raised EXCP_ATOMIC from the translator. */ 275 assert(HAVE_ATOMIC128); 276 val = int128_make128(lo, hi); 277 helper_atomic_sto_le_mmu(env, addr, val, opidx, GETPC()); 278 } 279 280 void helper_stq_be_parallel(CPUPPCState *env, target_ulong addr, 281 uint64_t lo, uint64_t hi, uint32_t opidx) 282 { 283 Int128 val; 284 285 /* We will have raised EXCP_ATOMIC from the translator. */ 286 assert(HAVE_ATOMIC128); 287 val = int128_make128(lo, hi); 288 helper_atomic_sto_be_mmu(env, addr, val, opidx, GETPC()); 289 } 290 291 uint32_t helper_stqcx_le_parallel(CPUPPCState *env, target_ulong addr, 292 uint64_t new_lo, uint64_t new_hi, 293 uint32_t opidx) 294 { 295 bool success = false; 296 297 /* We will have raised EXCP_ATOMIC from the translator. */ 298 assert(HAVE_CMPXCHG128); 299 300 if (likely(addr == env->reserve_addr)) { 301 Int128 oldv, cmpv, newv; 302 303 cmpv = int128_make128(env->reserve_val2, env->reserve_val); 304 newv = int128_make128(new_lo, new_hi); 305 oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, 306 opidx, GETPC()); 307 success = int128_eq(oldv, cmpv); 308 } 309 env->reserve_addr = -1; 310 return env->so + success * CRF_EQ_BIT; 311 } 312 313 uint32_t helper_stqcx_be_parallel(CPUPPCState *env, target_ulong addr, 314 uint64_t new_lo, uint64_t new_hi, 315 uint32_t opidx) 316 { 317 bool success = false; 318 319 /* We will have raised EXCP_ATOMIC from the translator. */ 320 assert(HAVE_CMPXCHG128); 321 322 if (likely(addr == env->reserve_addr)) { 323 Int128 oldv, cmpv, newv; 324 325 cmpv = int128_make128(env->reserve_val2, env->reserve_val); 326 newv = int128_make128(new_lo, new_hi); 327 oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, 328 opidx, GETPC()); 329 success = int128_eq(oldv, cmpv); 330 } 331 env->reserve_addr = -1; 332 return env->so + success * CRF_EQ_BIT; 333 } 334 #endif 335 336 /*****************************************************************************/ 337 /* Altivec extension helpers */ 338 #if defined(HOST_WORDS_BIGENDIAN) 339 #define HI_IDX 0 340 #define LO_IDX 1 341 #else 342 #define HI_IDX 1 343 #define LO_IDX 0 344 #endif 345 346 /* 347 * We use msr_le to determine index ordering in a vector. However, 348 * byteswapping is not simply controlled by msr_le. We also need to 349 * take into account endianness of the target. This is done for the 350 * little-endian PPC64 user-mode target. 351 */ 352 353 #define LVE(name, access, swap, element) \ 354 void helper_##name(CPUPPCState *env, ppc_avr_t *r, \ 355 target_ulong addr) \ 356 { \ 357 size_t n_elems = ARRAY_SIZE(r->element); \ 358 int adjust = HI_IDX * (n_elems - 1); \ 359 int sh = sizeof(r->element[0]) >> 1; \ 360 int index = (addr & 0xf) >> sh; \ 361 if (msr_le) { \ 362 index = n_elems - index - 1; \ 363 } \ 364 \ 365 if (needs_byteswap(env)) { \ 366 r->element[LO_IDX ? index : (adjust - index)] = \ 367 swap(access(env, addr, GETPC())); \ 368 } else { \ 369 r->element[LO_IDX ? index : (adjust - index)] = \ 370 access(env, addr, GETPC()); \ 371 } \ 372 } 373 #define I(x) (x) 374 LVE(lvebx, cpu_ldub_data_ra, I, u8) 375 LVE(lvehx, cpu_lduw_data_ra, bswap16, u16) 376 LVE(lvewx, cpu_ldl_data_ra, bswap32, u32) 377 #undef I 378 #undef LVE 379 380 #define STVE(name, access, swap, element) \ 381 void helper_##name(CPUPPCState *env, ppc_avr_t *r, \ 382 target_ulong addr) \ 383 { \ 384 size_t n_elems = ARRAY_SIZE(r->element); \ 385 int adjust = HI_IDX * (n_elems - 1); \ 386 int sh = sizeof(r->element[0]) >> 1; \ 387 int index = (addr & 0xf) >> sh; \ 388 if (msr_le) { \ 389 index = n_elems - index - 1; \ 390 } \ 391 \ 392 if (needs_byteswap(env)) { \ 393 access(env, addr, swap(r->element[LO_IDX ? index : \ 394 (adjust - index)]), \ 395 GETPC()); \ 396 } else { \ 397 access(env, addr, r->element[LO_IDX ? index : \ 398 (adjust - index)], GETPC()); \ 399 } \ 400 } 401 #define I(x) (x) 402 STVE(stvebx, cpu_stb_data_ra, I, u8) 403 STVE(stvehx, cpu_stw_data_ra, bswap16, u16) 404 STVE(stvewx, cpu_stl_data_ra, bswap32, u32) 405 #undef I 406 #undef LVE 407 408 #ifdef TARGET_PPC64 409 #define GET_NB(rb) ((rb >> 56) & 0xFF) 410 411 #define VSX_LXVL(name, lj) \ 412 void helper_##name(CPUPPCState *env, target_ulong addr, \ 413 ppc_vsr_t *xt, target_ulong rb) \ 414 { \ 415 ppc_vsr_t t; \ 416 uint64_t nb = GET_NB(rb); \ 417 int i; \ 418 \ 419 t.s128 = int128_zero(); \ 420 if (nb) { \ 421 nb = (nb >= 16) ? 16 : nb; \ 422 if (msr_le && !lj) { \ 423 for (i = 16; i > 16 - nb; i--) { \ 424 t.VsrB(i - 1) = cpu_ldub_data_ra(env, addr, GETPC()); \ 425 addr = addr_add(env, addr, 1); \ 426 } \ 427 } else { \ 428 for (i = 0; i < nb; i++) { \ 429 t.VsrB(i) = cpu_ldub_data_ra(env, addr, GETPC()); \ 430 addr = addr_add(env, addr, 1); \ 431 } \ 432 } \ 433 } \ 434 *xt = t; \ 435 } 436 437 VSX_LXVL(lxvl, 0) 438 VSX_LXVL(lxvll, 1) 439 #undef VSX_LXVL 440 441 #define VSX_STXVL(name, lj) \ 442 void helper_##name(CPUPPCState *env, target_ulong addr, \ 443 ppc_vsr_t *xt, target_ulong rb) \ 444 { \ 445 target_ulong nb = GET_NB(rb); \ 446 int i; \ 447 \ 448 if (!nb) { \ 449 return; \ 450 } \ 451 \ 452 nb = (nb >= 16) ? 16 : nb; \ 453 if (msr_le && !lj) { \ 454 for (i = 16; i > 16 - nb; i--) { \ 455 cpu_stb_data_ra(env, addr, xt->VsrB(i - 1), GETPC()); \ 456 addr = addr_add(env, addr, 1); \ 457 } \ 458 } else { \ 459 for (i = 0; i < nb; i++) { \ 460 cpu_stb_data_ra(env, addr, xt->VsrB(i), GETPC()); \ 461 addr = addr_add(env, addr, 1); \ 462 } \ 463 } \ 464 } 465 466 VSX_STXVL(stxvl, 0) 467 VSX_STXVL(stxvll, 1) 468 #undef VSX_STXVL 469 #undef GET_NB 470 #endif /* TARGET_PPC64 */ 471 472 #undef HI_IDX 473 #undef LO_IDX 474 475 void helper_tbegin(CPUPPCState *env) 476 { 477 /* 478 * As a degenerate implementation, always fail tbegin. The reason 479 * given is "Nesting overflow". The "persistent" bit is set, 480 * providing a hint to the error handler to not retry. The TFIAR 481 * captures the address of the failure, which is this tbegin 482 * instruction. Instruction execution will continue with the next 483 * instruction in memory, which is precisely what we want. 484 */ 485 486 env->spr[SPR_TEXASR] = 487 (1ULL << TEXASR_FAILURE_PERSISTENT) | 488 (1ULL << TEXASR_NESTING_OVERFLOW) | 489 (msr_hv << TEXASR_PRIVILEGE_HV) | 490 (msr_pr << TEXASR_PRIVILEGE_PR) | 491 (1ULL << TEXASR_FAILURE_SUMMARY) | 492 (1ULL << TEXASR_TFIAR_EXACT); 493 env->spr[SPR_TFIAR] = env->nip | (msr_hv << 1) | msr_pr; 494 env->spr[SPR_TFHAR] = env->nip + 4; 495 env->crf[0] = 0xB; /* 0b1010 = transaction failure */ 496 } 497