/* 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. */
} 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_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)
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)
} else {
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
- TCGv_i64 t2 = tcg_const_i64(0x00ff00ff);
+ TCGv_i64 t2 = tcg_constant_i64(0x00ff00ff);
/* arg = ....abcd */
tcg_gen_shri_i64(t0, arg, 8); /* t0 = .....abc */
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
- tcg_temp_free_i64(t2);
}
}
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);
}
addr = plugin_prep_mem_callbacks(addr);
- gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
+ 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, info);
if (swap) {
#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);
+ TCGMemOpIdx oi = make_memop_idx(memop & ~MO_SIGN, idx);
+ gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
}
#else
gen(retv, cpu_env, addr, cmpv, newv);
#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);
+ TCGMemOpIdx oi = make_memop_idx(memop, idx);
+ gen(retv, cpu_env, addr, cmpv, newv, tcg_constant_i32(oi));
}
#else
gen(retv, cpu_env, addr, cmpv, newv);
#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);
+ TCGMemOpIdx oi = make_memop_idx(memop & ~MO_SIGN, idx);
+ gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
}
#else
gen(ret, cpu_env, addr, val);
#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);
+ TCGMemOpIdx oi = make_memop_idx(memop & ~MO_SIGN, idx);
+ gen(ret, cpu_env, addr, val, tcg_constant_i32(oi));
}
#else
gen(ret, cpu_env, addr, val);