*/
#include "cpu.h"
#include "qemu/host-utils.h"
-#include "helper.h"
+#include "exec/helper-proto.h"
#include "helper_regs.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
+#include "exec/cpu_ldst.h"
//#define DEBUG_OP
+static inline bool needs_byteswap(const CPUPPCState *env)
+{
+#if defined(TARGET_WORDS_BIGENDIAN)
+ return msr_le;
+#else
+ return !msr_le;
+#endif
+}
+
/*****************************************************************************/
/* Memory load and stores */
void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
{
for (; reg < 32; reg++) {
- if (msr_le) {
+ if (needs_byteswap(env)) {
env->gpr[reg] = bswap32(cpu_ldl_data(env, addr));
} else {
env->gpr[reg] = cpu_ldl_data(env, addr);
void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
{
for (; reg < 32; reg++) {
- if (msr_le) {
+ if (needs_byteswap(env)) {
cpu_stl_data(env, addr, bswap32((uint32_t)env->gpr[reg]));
} else {
cpu_stl_data(env, addr, (uint32_t)env->gpr[reg]);
#define LO_IDX 0
#endif
+/* We use msr_le to determine index ordering in a vector. However,
+ byteswapping is not simply controlled by msr_le. We also need to take
+ into account endianness of the target. This is done for the little-endian
+ PPC64 user-mode target. */
+
#define LVE(name, access, swap, element) \
void helper_##name(CPUPPCState *env, ppc_avr_t *r, \
target_ulong addr) \
int adjust = HI_IDX*(n_elems - 1); \
int sh = sizeof(r->element[0]) >> 1; \
int index = (addr & 0xf) >> sh; \
- \
if (msr_le) { \
+ index = n_elems - index - 1; \
+ } \
+ \
+ if (needs_byteswap(env)) { \
r->element[LO_IDX ? index : (adjust - index)] = \
swap(access(env, addr)); \
} else { \
int adjust = HI_IDX * (n_elems - 1); \
int sh = sizeof(r->element[0]) >> 1; \
int index = (addr & 0xf) >> sh; \
- \
if (msr_le) { \
+ index = n_elems - index - 1; \
+ } \
+ \
+ if (needs_byteswap(env)) { \
access(env, addr, swap(r->element[LO_IDX ? index : \
(adjust - index)])); \
} else { \
#undef HI_IDX
#undef LO_IDX
+
+void helper_tbegin(CPUPPCState *env)
+{
+ /* As a degenerate implementation, always fail tbegin. The reason
+ * given is "Nesting overflow". The "persistent" bit is set,
+ * providing a hint to the error handler to not retry. The TFIAR
+ * captures the address of the failure, which is this tbegin
+ * instruction. Instruction execution will continue with the
+ * next instruction in memory, which is precisely what we want.
+ */
+
+ env->spr[SPR_TEXASR] =
+ (1ULL << TEXASR_FAILURE_PERSISTENT) |
+ (1ULL << TEXASR_NESTING_OVERFLOW) |
+ (msr_hv << TEXASR_PRIVILEGE_HV) |
+ (msr_pr << TEXASR_PRIVILEGE_PR) |
+ (1ULL << TEXASR_FAILURE_SUMMARY) |
+ (1ULL << TEXASR_TFIAR_EXACT);
+ env->spr[SPR_TFIAR] = env->nip | (msr_hv << 1) | msr_pr;
+ env->spr[SPR_TFHAR] = env->nip + 4;
+ env->crf[0] = 0xB; /* 0b1010 = transaction failure */
+}