}
#ifdef TARGET_NR_sysmips
+static abi_long do_sysmips_atomic_set(CPUArchState *env, abi_ulong addr,
+ abi_long value)
+{
+ uint32_t *ptr;
+ abi_long old;
+
+ if (addr & 3) {
+ return -TARGET_EINVAL;
+ }
+
+ ptr = lock_user(VERIFY_WRITE, addr, sizeof(*ptr), true);
+ if (!ptr) {
+ return -TARGET_EINVAL;
+ }
+
+ old = tswap32(qatomic_xchg(ptr, tswap32((uint32_t)value)));
+ unlock_user(ptr, addr, sizeof(*ptr));
+
+ /*
+ * MIPS uses a separate error flag, but the common linux-user syscall
+ * path infers that flag from the return value. Successful atomic_set
+ * results can overlap the target errno range, so write the result
+ * registers here and ask the CPU loop to leave them alone.
+ */
+ env->active_tc.gpr[2] = old;
+ env->active_tc.gpr[7] = 0;
+ return -QEMU_ESIGRETURN;
+}
+
static abi_long do_sysmips(CPUArchState *env, abi_long cmd, abi_long arg1,
abi_long arg2)
{
switch (cmd) {
+ case TARGET_SYSMIPS_ATOMIC_SET:
+ return do_sysmips_atomic_set(env, arg1, arg2);
case TARGET_SYSMIPS_FLUSH_CACHE:
return 0;
default: