+ case OP_ATOMIC_EXCHANGE_I4:
+ case OP_ATOMIC_CAS_I4:
+ case OP_ATOMIC_ADD_NEW_I4: {
+ int tmpreg;
+ guint8 *buf [16];
+
+ g_assert (v7_supported);
+
+ /* Free up a reg */
+ if (ins->sreg1 != ARMREG_IP && ins->sreg2 != ARMREG_IP && ins->sreg3 != ARMREG_IP)
+ tmpreg = ARMREG_IP;
+ else if (ins->sreg1 != ARMREG_R0 && ins->sreg2 != ARMREG_R0 && ins->sreg3 != ARMREG_R0)
+ tmpreg = ARMREG_R0;
+ else if (ins->sreg1 != ARMREG_R1 && ins->sreg2 != ARMREG_R1 && ins->sreg3 != ARMREG_R1)
+ tmpreg = ARMREG_R1;
+ else
+ tmpreg = ARMREG_R2;
+ g_assert (cfg->arch.atomic_tmp_offset != -1);
+ ARM_STR_IMM (code, tmpreg, cfg->frame_reg, cfg->arch.atomic_tmp_offset);
+
+ switch (ins->opcode) {
+ case OP_ATOMIC_EXCHANGE_I4:
+ buf [0] = code;
+ ARM_DMB (code, ARM_DMB_SY);
+ ARM_LDREX_REG (code, ARMREG_LR, ins->sreg1);
+ ARM_STREX_REG (code, tmpreg, ins->sreg2, ins->sreg1);
+ ARM_CMP_REG_IMM (code, tmpreg, 0, 0);
+ buf [1] = code;
+ ARM_B_COND (code, ARMCOND_NE, 0);
+ arm_patch (buf [1], buf [0]);
+ break;
+ case OP_ATOMIC_CAS_I4:
+ ARM_DMB (code, ARM_DMB_SY);
+ buf [0] = code;
+ ARM_LDREX_REG (code, ARMREG_LR, ins->sreg1);
+ ARM_CMP_REG_REG (code, ARMREG_LR, ins->sreg3);
+ buf [1] = code;
+ ARM_B_COND (code, ARMCOND_NE, 0);
+ ARM_STREX_REG (code, tmpreg, ins->sreg2, ins->sreg1);
+ ARM_CMP_REG_IMM (code, tmpreg, 0, 0);
+ buf [2] = code;
+ ARM_B_COND (code, ARMCOND_NE, 0);
+ arm_patch (buf [2], buf [1]);
+ arm_patch (buf [1], code);
+ break;
+ case OP_ATOMIC_ADD_NEW_I4:
+ buf [0] = code;
+ ARM_DMB (code, ARM_DMB_SY);
+ ARM_LDREX_REG (code, ARMREG_LR, ins->sreg1);
+ ARM_ADD_REG_REG (code, ARMREG_LR, ARMREG_LR, ins->sreg2);
+ ARM_STREX_REG (code, tmpreg, ARMREG_LR, ins->sreg1);
+ ARM_CMP_REG_IMM (code, tmpreg, 0, 0);
+ buf [1] = code;
+ ARM_B_COND (code, ARMCOND_NE, 0);
+ arm_patch (buf [1], buf [0]);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ ARM_DMB (code, ARM_DMB_SY);
+ if (tmpreg != ins->dreg)
+ ARM_LDR_IMM (code, tmpreg, cfg->frame_reg, cfg->arch.atomic_tmp_offset);
+ ARM_MOV_REG_REG (code, ins->dreg, ARMREG_LR);
+ break;
+ }
+