void helper_cmpxchg16b(CPUX86State *env, target_ulong a0) { uint64_t d0, d1; int eflags; if ((a0 & 0xf) != 0) { raise_exception(env, EXCP0D_GPF); } eflags = cpu_cc_compute_all(env, CC_OP); d0 = cpu_ldq_data(env, a0); d1 = cpu_ldq_data(env, a0 + 8); if (d0 == EAX && d1 == EDX) { cpu_stq_data(env, a0, EBX); cpu_stq_data(env, a0 + 8, ECX); eflags |= CC_Z; } else { /* always do the store */ cpu_stq_data(env, a0, d0); cpu_stq_data(env, a0 + 8, d1); EDX = d1; EAX = d0; eflags &= ~CC_Z; } CC_SRC = eflags; }
/* Store Clock Extended */ uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1) { cpu_stb_data(env, a1, 0); /* basically the same value as stck */ cpu_stq_data(env, a1 + 1, clock_value(env) | env->cpu_num); /* more fine grained than stck */ cpu_stq_data(env, a1 + 9, 0); /* XXX programmable fields */ cpu_stw_data(env, a1 + 17, 0); return 0; }
void helper_cmpxchg8b(CPUX86State *env, target_ulong a0) { uint64_t d; int eflags; eflags = cpu_cc_compute_all(env, CC_OP); d = cpu_ldq_data(env, a0); if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) { cpu_stq_data(env, a0, ((uint64_t)ECX << 32) | (uint32_t)EBX); eflags |= CC_Z; } else { /* always do the store */ cpu_stq_data(env, a0, d); EDX = (uint32_t)(d >> 32); EAX = (uint32_t)d; eflags &= ~CC_Z; } CC_SRC = eflags; }
uint32_t HELPER(stfle)(CPUS390XState *env, uint64_t addr) { uint64_t words[MAX_STFL_WORDS]; unsigned count_m1 = env->regs[0] & 0xff; unsigned max_m1 = do_stfle(env, words); unsigned i; for (i = 0; i <= count_m1; ++i) { cpu_stq_data(env, addr + 8 * i, words[i]); } env->regs[0] = deposit64(env->regs[0], 0, 8, max_m1); return (count_m1 >= max_m1 ? 0 : 3); }
/* memmove */ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) { int i = 0; int x = 0; uint32_t l_64 = (l + 1) / 8; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); #ifndef CONFIG_USER_ONLY if ((l > 32) && (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) && (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) { if (dest == (src + 1)) { mvc_fast_memset(env, l + 1, dest, cpu_ldub_data(env, src)); return; } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) { mvc_fast_memmove(env, l + 1, dest, src); return; } } #else if (dest == (src + 1)) { memset(g2h(dest), cpu_ldub_data(env, src), l + 1); return; } else { memmove(g2h(dest), g2h(src), l + 1); return; } #endif /* handle the parts that fit into 8-byte loads/stores */ if (dest != (src + 1)) { for (i = 0; i < l_64; i++) { cpu_stq_data(env, dest + x, cpu_ldq_data(env, src + x)); x += 8; } } /* slow version crossing pages with byte accesses */ for (i = x; i <= l; i++) { cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i)); } }
/* Store CPU Timer */ void HELPER(stpt)(CPUS390XState *env, uint64_t a1) { /* XXX implement */ cpu_stq_data(env, a1, 0); }
/* Store Clock */ uint32_t HELPER(stck)(CPUS390XState *env, uint64_t a1) { cpu_stq_data(env, a1, clock_value(env)); return 0; }
/* Store CPU ID */ void HELPER(stidp)(CPUS390XState *env, uint64_t a1) { cpu_stq_data(env, a1, env->cpu_num); }