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