*/
#include "qemu/osdep.h"
-#include "cpu.h"
#include "exec/exec-all.h"
#include "tcg/tcg.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-mo.h"
-#include "trace-tcg.h"
-#include "trace/mem.h"
#include "exec/plugin-gen.h"
/* Reduce the number of ifdefs below. This assumes that all uses of
/* 32 bit ops */
+void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
+{
+ tcg_gen_mov_i32(ret, tcg_constant_i32(arg));
+}
+
void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
/* some cases can be optimized here */
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_add_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2));
}
}
/* Don't recurse with tcg_gen_neg_i32. */
tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
} else {
- TCGv_i32 t0 = tcg_const_i32(arg1);
- tcg_gen_sub_i32(ret, t0, arg2);
- tcg_temp_free_i32(t0);
+ tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2);
}
}
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_sub_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2));
}
}
void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
- TCGv_i32 t0;
/* Some cases can be optimized here. */
switch (arg2) {
case 0:
}
break;
}
- t0 = tcg_const_i32(arg2);
- tcg_gen_and_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+
+ tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2));
}
void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
} else if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_or_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2));
}
}
/* Don't recurse with tcg_gen_not_i32. */
tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
} else {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_xor_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2));
}
}
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_shl_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_shl_i32(ret, arg1, tcg_constant_i32(arg2));
}
}
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_shr_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_shr_i32(ret, arg1, tcg_constant_i32(arg2));
}
}
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_sar_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_sar_i32(ret, arg1, tcg_constant_i32(arg2));
}
}
if (cond == TCG_COND_ALWAYS) {
tcg_gen_br(l);
} else if (cond != TCG_COND_NEVER) {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_brcond_i32(cond, arg1, t0, l);
- tcg_temp_free_i32(t0);
+ tcg_gen_brcond_i32(cond, arg1, tcg_constant_i32(arg2), l);
}
}
void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, int32_t arg2)
{
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_setcond_i32(cond, ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2));
}
void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
} else if (is_power_of_2(arg2)) {
tcg_gen_shli_i32(ret, arg1, ctz32(arg2));
} else {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_mul_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_mul_i32(ret, arg1, tcg_constant_i32(arg2));
}
}
void tcg_gen_clzi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
{
- TCGv_i32 t = tcg_const_i32(arg2);
- tcg_gen_clz_i32(ret, arg1, t);
- tcg_temp_free_i32(t);
+ tcg_gen_clz_i32(ret, arg1, tcg_constant_i32(arg2));
}
void tcg_gen_ctz_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
tcg_gen_clzi_i32(t, t, 32);
tcg_gen_xori_i32(t, t, 31);
}
- z = tcg_const_i32(0);
+ z = tcg_constant_i32(0);
tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg1, z, arg2, t);
tcg_temp_free_i32(t);
- tcg_temp_free_i32(z);
} else {
gen_helper_ctz_i32(ret, arg1, arg2);
}
tcg_gen_ctpop_i32(ret, t);
tcg_temp_free_i32(t);
} else {
- TCGv_i32 t = tcg_const_i32(arg2);
- tcg_gen_ctz_i32(ret, arg1, t);
- tcg_temp_free_i32(t);
+ tcg_gen_ctz_i32(ret, arg1, tcg_constant_i32(arg2));
}
}
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else if (TCG_TARGET_HAS_rot_i32) {
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_rotl_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_rotl_i32(ret, arg1, tcg_constant_i32(arg2));
} else {
TCGv_i32 t0, t1;
t0 = tcg_temp_new_i32();
tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
} else if (TCG_TARGET_HAS_deposit_i32
&& TCG_TARGET_deposit_i32_valid(ofs, len)) {
- TCGv_i32 zero = tcg_const_i32(0);
+ TCGv_i32 zero = tcg_constant_i32(0);
tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len);
- tcg_temp_free_i32(zero);
} else {
/* To help two-operand hosts we prefer to zero-extend first,
which allows ARG to stay live. */
}
}
-/* Note: we assume the two high bytes are set to zero */
-void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
+void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags)
{
+ /* Only one extension flag may be present. */
+ tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
+
if (TCG_TARGET_HAS_bswap16_i32) {
- tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg);
+ tcg_gen_op3i_i32(INDEX_op_bswap16_i32, ret, arg, flags);
} else {
TCGv_i32 t0 = tcg_temp_new_i32();
+ TCGv_i32 t1 = tcg_temp_new_i32();
+
+ tcg_gen_shri_i32(t0, arg, 8);
+ if (!(flags & TCG_BSWAP_IZ)) {
+ tcg_gen_ext8u_i32(t0, t0);
+ }
+
+ if (flags & TCG_BSWAP_OS) {
+ tcg_gen_shli_i32(t1, arg, 24);
+ tcg_gen_sari_i32(t1, t1, 16);
+ } else if (flags & TCG_BSWAP_OZ) {
+ tcg_gen_ext8u_i32(t1, arg);
+ tcg_gen_shli_i32(t1, t1, 8);
+ } else {
+ tcg_gen_shli_i32(t1, arg, 8);
+ }
- tcg_gen_ext8u_i32(t0, arg);
- tcg_gen_shli_i32(t0, t0, 8);
- tcg_gen_shri_i32(ret, arg, 8);
- tcg_gen_or_i32(ret, ret, t0);
+ tcg_gen_or_i32(ret, t0, t1);
tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
}
}
void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
{
if (TCG_TARGET_HAS_bswap32_i32) {
- tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
+ tcg_gen_op3i_i32(INDEX_op_bswap32_i32, ret, arg, 0);
} else {
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
- TCGv_i32 t2 = tcg_const_i32(0x00ff00ff);
+ TCGv_i32 t2 = tcg_constant_i32(0x00ff00ff);
/* arg = abcd */
tcg_gen_shri_i32(t0, arg, 8); /* t0 = .abc */
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
- tcg_temp_free_i32(t2);
}
}
+void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg)
+{
+ /* Swapping 2 16-bit elements is a rotate. */
+ tcg_gen_rotli_i32(ret, arg, 16);
+}
+
void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
{
tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
- tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
+ TCGTemp *ts = tcgv_i64_temp(arg);
+
+ /* Canonicalize TCGv_i64 TEMP_CONST into TCGv_i32 TEMP_CONST. */
+ if (ts->kind == TEMP_CONST) {
+ tcg_gen_movi_i64(ret, ts->val);
+ } else {
+ tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
+ tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
+ }
}
void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
{
/* Since arg2 and ret have different types,
they cannot be the same temporary */
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
#else
void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
{
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
#else
tcg_temp_free_i64(t0);
tcg_temp_free_i32(t1);
}
+
+#else
+
+void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
+{
+ tcg_gen_mov_i64(ret, tcg_constant_i64(arg));
+}
+
#endif /* TCG_TARGET_REG_SIZE == 32 */
void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
/* some cases can be optimized here */
if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
+ } else if (TCG_TARGET_REG_BITS == 64) {
+ tcg_gen_add_i64(ret, arg1, tcg_constant_i64(arg2));
} else {
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_add_i64(ret, arg1, t0);
- tcg_temp_free_i64(t0);
+ tcg_gen_add2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
+ TCGV_LOW(arg1), TCGV_HIGH(arg1),
+ tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
}
}
if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
/* Don't recurse with tcg_gen_neg_i64. */
tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
+ } else if (TCG_TARGET_REG_BITS == 64) {
+ tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2);
} else {
- TCGv_i64 t0 = tcg_const_i64(arg1);
- tcg_gen_sub_i64(ret, t0, arg2);
- tcg_temp_free_i64(t0);
+ tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
+ tcg_constant_i32(arg1), tcg_constant_i32(arg1 >> 32),
+ TCGV_LOW(arg2), TCGV_HIGH(arg2));
}
}
/* some cases can be optimized here */
if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
+ } else if (TCG_TARGET_REG_BITS == 64) {
+ tcg_gen_sub_i64(ret, arg1, tcg_constant_i64(arg2));
} else {
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_sub_i64(ret, arg1, t0);
- tcg_temp_free_i64(t0);
+ tcg_gen_sub2_i32(TCGV_LOW(ret), TCGV_HIGH(ret),
+ TCGV_LOW(arg1), TCGV_HIGH(arg1),
+ tcg_constant_i32(arg2), tcg_constant_i32(arg2 >> 32));
}
}
void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
- TCGv_i64 t0;
-
if (TCG_TARGET_REG_BITS == 32) {
tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
}
break;
}
- t0 = tcg_const_i64(arg2);
- tcg_gen_and_i64(ret, arg1, t0);
- tcg_temp_free_i64(t0);
+
+ tcg_gen_and_i64(ret, arg1, tcg_constant_i64(arg2));
}
void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
} else if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
} else {
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_or_i64(ret, arg1, t0);
- tcg_temp_free_i64(t0);
+ tcg_gen_or_i64(ret, arg1, tcg_constant_i64(arg2));
}
}
/* Don't recurse with tcg_gen_not_i64. */
tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg1);
} else {
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_xor_i64(ret, arg1, t0);
- tcg_temp_free_i64(t0);
+ tcg_gen_xor_i64(ret, arg1, tcg_constant_i64(arg2));
}
}
} else if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
} else {
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_shl_i64(ret, arg1, t0);
- tcg_temp_free_i64(t0);
+ tcg_gen_shl_i64(ret, arg1, tcg_constant_i64(arg2));
}
}
} else if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
} else {
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_shr_i64(ret, arg1, t0);
- tcg_temp_free_i64(t0);
+ tcg_gen_shr_i64(ret, arg1, tcg_constant_i64(arg2));
}
}
} else if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
} else {
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_sar_i64(ret, arg1, t0);
- tcg_temp_free_i64(t0);
+ tcg_gen_sar_i64(ret, arg1, tcg_constant_i64(arg2));
}
}
void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1, int64_t arg2, TCGLabel *l)
{
- if (cond == TCG_COND_ALWAYS) {
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_gen_brcond_i64(cond, arg1, tcg_constant_i64(arg2), l);
+ } else if (cond == TCG_COND_ALWAYS) {
tcg_gen_br(l);
} else if (cond != TCG_COND_NEVER) {
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_brcond_i64(cond, arg1, t0, l);
- tcg_temp_free_i64(t0);
+ l->refs++;
+ tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
+ TCGV_LOW(arg1), TCGV_HIGH(arg1),
+ tcg_constant_i32(arg2),
+ tcg_constant_i32(arg2 >> 32),
+ cond, label_arg(l));
}
}
void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, int64_t arg2)
{
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_setcond_i64(cond, ret, arg1, t0);
- tcg_temp_free_i64(t0);
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_gen_setcond_i64(cond, ret, arg1, tcg_constant_i64(arg2));
+ } else if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i64(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i64(ret, 0);
+ } else {
+ tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
+ TCGV_LOW(arg1), TCGV_HIGH(arg1),
+ tcg_constant_i32(arg2),
+ tcg_constant_i32(arg2 >> 32), cond);
+ tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
+ }
}
void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
}
}
-/* Note: we assume the six high bytes are set to zero */
-void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
+void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
{
+ /* Only one extension flag may be present. */
+ tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
+
if (TCG_TARGET_REG_BITS == 32) {
- tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
- tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
+ tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg), flags);
+ if (flags & TCG_BSWAP_OS) {
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
+ } else {
+ tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
+ }
} else if (TCG_TARGET_HAS_bswap16_i64) {
- tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg);
+ tcg_gen_op3i_i64(INDEX_op_bswap16_i64, ret, arg, flags);
} else {
TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+
+ tcg_gen_shri_i64(t0, arg, 8);
+ if (!(flags & TCG_BSWAP_IZ)) {
+ tcg_gen_ext8u_i64(t0, t0);
+ }
+
+ if (flags & TCG_BSWAP_OS) {
+ tcg_gen_shli_i64(t1, arg, 56);
+ tcg_gen_sari_i64(t1, t1, 48);
+ } else if (flags & TCG_BSWAP_OZ) {
+ tcg_gen_ext8u_i64(t1, arg);
+ tcg_gen_shli_i64(t1, t1, 8);
+ } else {
+ tcg_gen_shli_i64(t1, arg, 8);
+ }
- tcg_gen_ext8u_i64(t0, arg);
- tcg_gen_shli_i64(t0, t0, 8);
- tcg_gen_shri_i64(ret, arg, 8);
- tcg_gen_or_i64(ret, ret, t0);
+ tcg_gen_or_i64(ret, t0, t1);
tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
}
}
-/* Note: we assume the four high bytes are set to zero */
-void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
+void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
{
+ /* Only one extension flag may be present. */
+ tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
+
if (TCG_TARGET_REG_BITS == 32) {
tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
- tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
+ if (flags & TCG_BSWAP_OS) {
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
+ } else {
+ tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
+ }
} else if (TCG_TARGET_HAS_bswap32_i64) {
- tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
+ tcg_gen_op3i_i64(INDEX_op_bswap32_i64, ret, arg, flags);
} else {
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
- TCGv_i64 t2 = tcg_const_i64(0x00ff00ff);
-
- /* arg = ....abcd */
- tcg_gen_shri_i64(t0, arg, 8); /* t0 = .....abc */
- tcg_gen_and_i64(t1, arg, t2); /* t1 = .....b.d */
- tcg_gen_and_i64(t0, t0, t2); /* t0 = .....a.c */
- tcg_gen_shli_i64(t1, t1, 8); /* t1 = ....b.d. */
- tcg_gen_or_i64(ret, t0, t1); /* ret = ....badc */
-
- tcg_gen_shli_i64(t1, ret, 48); /* t1 = dc...... */
- tcg_gen_shri_i64(t0, ret, 16); /* t0 = ......ba */
- tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */
- tcg_gen_or_i64(ret, t0, t1); /* ret = ....dcba */
+ TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff);
+
+ /* arg = xxxxabcd */
+ tcg_gen_shri_i64(t0, arg, 8); /* t0 = .xxxxabc */
+ tcg_gen_and_i64(t1, arg, t2); /* t1 = .....b.d */
+ tcg_gen_and_i64(t0, t0, t2); /* t0 = .....a.c */
+ tcg_gen_shli_i64(t1, t1, 8); /* t1 = ....b.d. */
+ tcg_gen_or_i64(ret, t0, t1); /* ret = ....badc */
+
+ tcg_gen_shli_i64(t1, ret, 48); /* t1 = dc...... */
+ tcg_gen_shri_i64(t0, ret, 16); /* t0 = ......ba */
+ if (flags & TCG_BSWAP_OS) {
+ tcg_gen_sari_i64(t1, t1, 32); /* t1 = ssssdc.. */
+ } else {
+ tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */
+ }
+ tcg_gen_or_i64(ret, t0, t1); /* ret = ssssdcba */
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
- tcg_temp_free_i64(t2);
}
}
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
} else if (TCG_TARGET_HAS_bswap64_i64) {
- tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
+ tcg_gen_op3i_i64(INDEX_op_bswap64_i64, ret, arg, 0);
} else {
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
}
}
+void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg)
+{
+ uint64_t m = 0x0000ffff0000ffffull;
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+
+ /* See include/qemu/bitops.h, hswap64. */
+ tcg_gen_rotli_i64(t1, arg, 32);
+ tcg_gen_andi_i64(t0, t1, m);
+ tcg_gen_shli_i64(t0, t0, 16);
+ tcg_gen_shri_i64(t1, t1, 16);
+ tcg_gen_andi_i64(t1, t1, m);
+ tcg_gen_or_i64(ret, t0, t1);
+
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+}
+
+void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg)
+{
+ /* Swapping 2 32-bit elements is a rotate. */
+ tcg_gen_rotli_i64(ret, arg, 32);
+}
+
void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
{
if (TCG_TARGET_REG_BITS == 32) {
if (TCG_TARGET_REG_BITS == 32
&& TCG_TARGET_HAS_clz_i32
&& arg2 <= 0xffffffffu) {
- TCGv_i32 t = tcg_const_i32((uint32_t)arg2 - 32);
- tcg_gen_clz_i32(t, TCGV_LOW(arg1), t);
+ TCGv_i32 t = tcg_temp_new_i32();
+ tcg_gen_clzi_i32(t, TCGV_LOW(arg1), arg2 - 32);
tcg_gen_addi_i32(t, t, 32);
tcg_gen_clz_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), t);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
tcg_temp_free_i32(t);
} else {
- TCGv_i64 t = tcg_const_i64(arg2);
- tcg_gen_clz_i64(ret, arg1, t);
- tcg_temp_free_i64(t);
+ TCGv_i64 t0 = tcg_const_i64(arg2);
+ tcg_gen_clz_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
}
}
tcg_gen_clzi_i64(t, t, 64);
tcg_gen_xori_i64(t, t, 63);
}
- z = tcg_const_i64(0);
+ z = tcg_constant_i64(0);
tcg_gen_movcond_i64(TCG_COND_EQ, ret, arg1, z, arg2, t);
tcg_temp_free_i64(t);
tcg_temp_free_i64(z);
if (TCG_TARGET_REG_BITS == 32
&& TCG_TARGET_HAS_ctz_i32
&& arg2 <= 0xffffffffu) {
- TCGv_i32 t32 = tcg_const_i32((uint32_t)arg2 - 32);
- tcg_gen_ctz_i32(t32, TCGV_HIGH(arg1), t32);
+ TCGv_i32 t32 = tcg_temp_new_i32();
+ tcg_gen_ctzi_i32(t32, TCGV_HIGH(arg1), arg2 - 32);
tcg_gen_addi_i32(t32, t32, 32);
tcg_gen_ctz_i32(TCGV_LOW(ret), TCGV_LOW(arg1), t32);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
tcg_gen_ctpop_i64(ret, t);
tcg_temp_free_i64(t);
} else {
- TCGv_i64 t64 = tcg_const_i64(arg2);
- tcg_gen_ctz_i64(ret, arg1, t64);
- tcg_temp_free_i64(t64);
+ TCGv_i64 t0 = tcg_const_i64(arg2);
+ tcg_gen_ctz_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
}
}
if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
} else if (TCG_TARGET_HAS_rot_i64) {
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_rotl_i64(ret, arg1, t0);
- tcg_temp_free_i64(t0);
+ tcg_gen_rotl_i64(ret, arg1, tcg_constant_i64(arg2));
} else {
TCGv_i64 t0, t1;
t0 = tcg_temp_new_i64();
tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
} else if (TCG_TARGET_HAS_deposit_i64
&& TCG_TARGET_deposit_i64_valid(ofs, len)) {
- TCGv_i64 zero = tcg_const_i64(0);
+ TCGv_i64 zero = tcg_constant_i64(0);
tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len);
- tcg_temp_free_i64(zero);
} else {
if (TCG_TARGET_REG_BITS == 32) {
if (ofs >= 32) {
/* QEMU specific operations. */
-void tcg_gen_exit_tb(TranslationBlock *tb, unsigned idx)
-{
- uintptr_t val = (uintptr_t)tb + idx;
+void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx)
+{
+ /*
+ * Let the jit code return the read-only version of the
+ * TranslationBlock, so that we minimize the pc-relative
+ * distance of the address of the exit_tb code to TB.
+ * This will improve utilization of pc-relative address loads.
+ *
+ * TODO: Move this to translator_loop, so that all const
+ * TranslationBlock pointers refer to read-only memory.
+ * This requires coordination with targets that do not use
+ * the translator_loop.
+ */
+ uintptr_t val = (uintptr_t)tcg_splitwx_to_rx((void *)tb) + idx;
if (tb == NULL) {
tcg_debug_assert(idx == 0);
seen this numbered exit before, via tcg_gen_goto_tb. */
tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
#endif
- /* When not chaining, exit without indicating a link. */
- if (qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
- val = 0;
- }
} else {
/* This is an exit via the exitreq label. */
tcg_debug_assert(idx == TB_EXIT_REQUESTED);
void tcg_gen_goto_tb(unsigned idx)
{
+ /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */
+ tcg_debug_assert(!(tcg_ctx->tb_cflags & CF_NO_GOTO_TB));
/* We only support two chained exits. */
tcg_debug_assert(idx <= TB_EXIT_IDXMAX);
#ifdef CONFIG_DEBUG_TCG
- /* Verify that we havn't seen this numbered exit before. */
+ /* Verify that we haven't seen this numbered exit before. */
tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
tcg_ctx->goto_tb_issue_mask |= 1 << idx;
#endif
plugin_gen_disable_mem_helpers();
- /* When not chaining, we simply fall through to the "fallback" exit. */
- if (!qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
- tcg_gen_op1i(INDEX_op_goto_tb, idx);
- }
+ tcg_gen_op1i(INDEX_op_goto_tb, idx);
}
void tcg_gen_lookup_and_goto_ptr(void)
{
- if (TCG_TARGET_HAS_goto_ptr && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
- TCGv_ptr ptr;
+ TCGv_ptr ptr;
- plugin_gen_disable_mem_helpers();
- ptr = tcg_temp_new_ptr();
- gen_helper_lookup_tb_ptr(ptr, cpu_env);
- tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
- tcg_temp_free_ptr(ptr);
- } else {
+ if (tcg_ctx->tb_cflags & CF_NO_GOTO_PTR) {
tcg_gen_exit_tb(NULL, 0);
+ return;
}
+
+ plugin_gen_disable_mem_helpers();
+ ptr = tcg_temp_new_ptr();
+ gen_helper_lookup_tb_ptr(ptr, cpu_env);
+ tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
+ tcg_temp_free_ptr(ptr);
}
static inline MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st)
{
/* Trigger the asserts within as early as possible. */
- (void)get_alignment_bits(op);
+ unsigned a_bits = get_alignment_bits(op);
+
+ /* Prefer MO_ALIGN+MO_XX over MO_ALIGN_XX+MO_XX */
+ if (a_bits == (op & MO_SIZE)) {
+ op = (op & ~MO_AMASK) | MO_ALIGN;
+ }
switch (op & MO_SIZE) {
case MO_8:
}
break;
case MO_64:
- if (!is64) {
- tcg_abort();
+ if (is64) {
+ op &= ~MO_SIGN;
+ break;
}
- break;
+ /* fall through */
+ default:
+ g_assert_not_reached();
}
if (st) {
op &= ~MO_SIGN;
static void gen_ldst_i32(TCGOpcode opc, TCGv_i32 val, TCGv addr,
MemOp memop, TCGArg idx)
{
- TCGMemOpIdx oi = make_memop_idx(memop, idx);
+ MemOpIdx oi = make_memop_idx(memop, idx);
#if TARGET_LONG_BITS == 32
tcg_gen_op3i_i32(opc, val, addr, oi);
#else
static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 val, TCGv addr,
MemOp memop, TCGArg idx)
{
- TCGMemOpIdx oi = make_memop_idx(memop, idx);
+ MemOpIdx oi = make_memop_idx(memop, idx);
#if TARGET_LONG_BITS == 32
if (TCG_TARGET_REG_BITS == 32) {
tcg_gen_op4i_i32(opc, TCGV_LOW(val), TCGV_HIGH(val), addr, oi);
return vaddr;
}
-static inline void plugin_gen_mem_callbacks(TCGv vaddr, uint16_t info)
+static void plugin_gen_mem_callbacks(TCGv vaddr, MemOpIdx oi,
+ enum qemu_plugin_mem_rw rw)
{
#ifdef CONFIG_PLUGIN
if (tcg_ctx->plugin_insn != NULL) {
+ qemu_plugin_meminfo_t info = make_plugin_meminfo(oi, rw);
plugin_gen_empty_mem_callback(vaddr, info);
tcg_temp_free(vaddr);
}
void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
{
MemOp orig_memop;
- uint16_t info = trace_mem_get_info(memop, idx, 0);
+ MemOpIdx oi;
tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
memop = tcg_canonicalize_memop(memop, 0, 0);
- trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
+ oi = make_memop_idx(memop, idx);
orig_memop = memop;
if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
memop &= ~MO_BSWAP;
- /* The bswap primitive requires zero-extended input. */
+ /* The bswap primitive benefits from zero-extended input. */
if ((memop & MO_SSIZE) == MO_SW) {
memop &= ~MO_SIGN;
}
addr = plugin_prep_mem_callbacks(addr);
gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
- plugin_gen_mem_callbacks(addr, info);
+ plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_R);
if ((orig_memop ^ memop) & MO_BSWAP) {
switch (orig_memop & MO_SIZE) {
case MO_16:
- tcg_gen_bswap16_i32(val, val);
- if (orig_memop & MO_SIGN) {
- tcg_gen_ext16s_i32(val, val);
- }
+ tcg_gen_bswap16_i32(val, val, (orig_memop & MO_SIGN
+ ? TCG_BSWAP_IZ | TCG_BSWAP_OS
+ : TCG_BSWAP_IZ | TCG_BSWAP_OZ));
break;
case MO_32:
tcg_gen_bswap32_i32(val, val);
void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
{
TCGv_i32 swap = NULL;
- uint16_t info = trace_mem_get_info(memop, idx, 1);
+ MemOpIdx oi;
tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
memop = tcg_canonicalize_memop(memop, 0, 1);
- trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
+ oi = make_memop_idx(memop, idx);
if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
swap = tcg_temp_new_i32();
switch (memop & MO_SIZE) {
case MO_16:
- tcg_gen_ext16u_i32(swap, val);
- tcg_gen_bswap16_i32(swap, swap);
+ tcg_gen_bswap16_i32(swap, val, 0);
break;
case MO_32:
tcg_gen_bswap32_i32(swap, val);
}
addr = plugin_prep_mem_callbacks(addr);
- gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
- plugin_gen_mem_callbacks(addr, info);
+ if (TCG_TARGET_HAS_qemu_st8_i32 && (memop & MO_SIZE) == MO_8) {
+ gen_ldst_i32(INDEX_op_qemu_st8_i32, val, addr, memop, idx);
+ } else {
+ gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
+ }
+ plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_W);
if (swap) {
tcg_temp_free_i32(swap);
void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
{
MemOp orig_memop;
- uint16_t info;
+ MemOpIdx oi;
if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
memop = tcg_canonicalize_memop(memop, 1, 0);
- info = trace_mem_get_info(memop, idx, 0);
- trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
+ oi = make_memop_idx(memop, idx);
orig_memop = memop;
if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
memop &= ~MO_BSWAP;
- /* The bswap primitive requires zero-extended input. */
+ /* The bswap primitive benefits from zero-extended input. */
if ((memop & MO_SIGN) && (memop & MO_SIZE) < MO_64) {
memop &= ~MO_SIGN;
}
addr = plugin_prep_mem_callbacks(addr);
gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
- plugin_gen_mem_callbacks(addr, info);
+ plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_R);
if ((orig_memop ^ memop) & MO_BSWAP) {
+ int flags = (orig_memop & MO_SIGN
+ ? TCG_BSWAP_IZ | TCG_BSWAP_OS
+ : TCG_BSWAP_IZ | TCG_BSWAP_OZ);
switch (orig_memop & MO_SIZE) {
case MO_16:
- tcg_gen_bswap16_i64(val, val);
- if (orig_memop & MO_SIGN) {
- tcg_gen_ext16s_i64(val, val);
- }
+ tcg_gen_bswap16_i64(val, val, flags);
break;
case MO_32:
- tcg_gen_bswap32_i64(val, val);
- if (orig_memop & MO_SIGN) {
- tcg_gen_ext32s_i64(val, val);
- }
+ tcg_gen_bswap32_i64(val, val, flags);
break;
case MO_64:
tcg_gen_bswap64_i64(val, val);
void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
{
TCGv_i64 swap = NULL;
- uint16_t info;
+ MemOpIdx oi;
if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
memop = tcg_canonicalize_memop(memop, 1, 1);
- info = trace_mem_get_info(memop, idx, 1);
- trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env, addr, info);
+ oi = make_memop_idx(memop, idx);
if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
swap = tcg_temp_new_i64();
switch (memop & MO_SIZE) {
case MO_16:
- tcg_gen_ext16u_i64(swap, val);
- tcg_gen_bswap16_i64(swap, swap);
+ tcg_gen_bswap16_i64(swap, val, 0);
break;
case MO_32:
- tcg_gen_ext32u_i64(swap, val);
- tcg_gen_bswap32_i64(swap, swap);
+ tcg_gen_bswap32_i64(swap, val, 0);
break;
case MO_64:
tcg_gen_bswap64_i64(swap, val);
addr = plugin_prep_mem_callbacks(addr);
gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
- plugin_gen_mem_callbacks(addr, info);
+ plugin_gen_mem_callbacks(addr, oi, QEMU_PLUGIN_MEM_W);
if (swap) {
tcg_temp_free_i64(swap);
}
}
-#ifdef CONFIG_SOFTMMU
typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv,
TCGv_i32, TCGv_i32, TCGv_i32);
typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv,
TCGv_i32, TCGv_i32);
typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv,
TCGv_i64, TCGv_i32);
-#else
-typedef void (*gen_atomic_cx_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32, TCGv_i32);
-typedef void (*gen_atomic_cx_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64, TCGv_i64);
-typedef void (*gen_atomic_op_i32)(TCGv_i32, TCGv_env, TCGv, TCGv_i32);
-typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, TCGv, TCGv_i64);
-#endif
#ifdef CONFIG_ATOMIC64
# define WITH_ATOMIC64(X) X,
# define WITH_ATOMIC64(X)
#endif
-static void * const table_cmpxchg[16] = {
+static void * const table_cmpxchg[(MO_SIZE | MO_BSWAP) + 1] = {
[MO_8] = gen_helper_atomic_cmpxchgb,
[MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
[MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
tcg_temp_free_i32(t1);
} else {
gen_atomic_cx_i32 gen;
+ MemOpIdx oi;
gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
tcg_debug_assert(gen != NULL);
-#ifdef CONFIG_SOFTMMU
- {
- TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
- gen(retv, cpu_env, addr, cmpv, newv, oi);
- tcg_temp_free_i32(oi);
- }
-#else
- gen(retv, cpu_env, addr, cmpv, newv);
-#endif
+ oi = make_memop_idx(memop & ~MO_SIGN, idx);
+ gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
if (memop & MO_SIGN) {
tcg_gen_ext_i32(retv, retv, memop);
} else if ((memop & MO_SIZE) == MO_64) {
#ifdef CONFIG_ATOMIC64
gen_atomic_cx_i64 gen;
+ MemOpIdx oi;
gen = table_cmpxchg[memop & (MO_SIZE | MO_BSWAP)];
tcg_debug_assert(gen != NULL);
-#ifdef CONFIG_SOFTMMU
- {
- TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop, idx));
- gen(retv, cpu_env, addr, cmpv, newv, oi);
- tcg_temp_free_i32(oi);
- }
-#else
- gen(retv, cpu_env, addr, cmpv, newv);
-#endif
+ oi = make_memop_idx(memop, idx);
+ gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
#else
gen_helper_exit_atomic(cpu_env);
/* Produce a result, so that we have a well-formed opcode stream
TCGArg idx, MemOp memop, void * const table[])
{
gen_atomic_op_i32 gen;
+ MemOpIdx oi;
memop = tcg_canonicalize_memop(memop, 0, 0);
gen = table[memop & (MO_SIZE | MO_BSWAP)];
tcg_debug_assert(gen != NULL);
-#ifdef CONFIG_SOFTMMU
- {
- TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
- gen(ret, cpu_env, addr, val, oi);
- tcg_temp_free_i32(oi);
- }
-#else
- gen(ret, cpu_env, addr, val);
-#endif
+ oi = make_memop_idx(memop & ~MO_SIGN, idx);
+ gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
if (memop & MO_SIGN) {
tcg_gen_ext_i32(ret, ret, memop);
if ((memop & MO_SIZE) == MO_64) {
#ifdef CONFIG_ATOMIC64
gen_atomic_op_i64 gen;
+ MemOpIdx oi;
gen = table[memop & (MO_SIZE | MO_BSWAP)];
tcg_debug_assert(gen != NULL);
-#ifdef CONFIG_SOFTMMU
- {
- TCGv_i32 oi = tcg_const_i32(make_memop_idx(memop & ~MO_SIGN, idx));
- gen(ret, cpu_env, addr, val, oi);
- tcg_temp_free_i32(oi);
- }
-#else
- gen(ret, cpu_env, addr, val);
-#endif
+ oi = make_memop_idx(memop & ~MO_SIGN, idx);
+ gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
#else
gen_helper_exit_atomic(cpu_env);
/* Produce a result, so that we have a well-formed opcode stream
}
#define GEN_ATOMIC_HELPER(NAME, OP, NEW) \
-static void * const table_##NAME[16] = { \
+static void * const table_##NAME[(MO_SIZE | MO_BSWAP) + 1] = { \
[MO_8] = gen_helper_atomic_##NAME##b, \
[MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le, \
[MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be, \