@@ -83,6 +83,20 @@ static uint64_t tci_uint64(uint32_t high, uint32_t low)
}
#endif
+/* Read constant byte from bytecode. */
+static uint8_t tci_read_b(const uint8_t **tb_ptr)
+{
+ return *(tb_ptr[0]++);
+}
+
+/* Read register number from bytecode. */
+static TCGReg tci_read_r(const uint8_t **tb_ptr)
+{
+ uint8_t regno = tci_read_b(tb_ptr);
+ tci_assert(regno < TCG_TARGET_NB_REGS);
+ return regno;
+}
+
/* Read constant (native size) from bytecode. */
static tcg_target_ulong tci_read_i(const uint8_t **tb_ptr)
{
@@ -161,6 +175,23 @@ static tcg_target_ulong tci_read_label(const uint8_t **tb_ptr)
return label;
}
+/*
+ * Load sets of arguments all at once. The naming convention is:
+ * tci_args_<arguments>
+ * where arguments is a sequence of
+ *
+ * r = register
+ * s = signed ldst offset
+ */
+
+static void tci_args_rrs(const uint8_t **tb_ptr,
+ TCGReg *r0, TCGReg *r1, int32_t *i2)
+{
+ *r0 = tci_read_r(tb_ptr);
+ *r1 = tci_read_r(tb_ptr);
+ *i2 = tci_read_s32(tb_ptr);
+}
+
static bool tci_compare32(uint32_t u0, uint32_t u1, TCGCond condition)
{
bool result = false;
@@ -311,6 +342,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
uint8_t op_size = tb_ptr[1];
const uint8_t *old_code_ptr = tb_ptr;
#endif
+ TCGReg r0, r1;
tcg_target_ulong t0;
tcg_target_ulong t1;
tcg_target_ulong t2;
@@ -325,6 +357,8 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
uint64_t v64;
#endif
TCGMemOpIdx oi;
+ int32_t ofs;
+ void *ptr;
/* Skip opcode and size entry. */
tb_ptr += 2;
@@ -401,54 +435,46 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
/* Load/store operations (32 bit). */
CASE_32_64(ld8u)
- t0 = *tb_ptr++;
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- tci_write_reg(regs, t0, *(uint8_t *)(t1 + t2));
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ regs[r0] = *(uint8_t *)ptr;
break;
CASE_32_64(ld8s)
- t0 = *tb_ptr++;
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- tci_write_reg(regs, t0, *(int8_t *)(t1 + t2));
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ regs[r0] = *(int8_t *)ptr;
break;
CASE_32_64(ld16u)
- t0 = *tb_ptr++;
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- tci_write_reg(regs, t0, *(uint16_t *)(t1 + t2));
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ regs[r0] = *(uint16_t *)ptr;
break;
CASE_32_64(ld16s)
- t0 = *tb_ptr++;
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- tci_write_reg(regs, t0, *(int16_t *)(t1 + t2));
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ regs[r0] = *(int16_t *)ptr;
break;
case INDEX_op_ld_i32:
CASE_64(ld32u)
- t0 = *tb_ptr++;
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- tci_write_reg(regs, t0, *(uint32_t *)(t1 + t2));
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ regs[r0] = *(uint32_t *)ptr;
break;
CASE_32_64(st8)
- t0 = tci_read_rval(regs, &tb_ptr);
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- *(uint8_t *)(t1 + t2) = t0;
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ *(uint8_t *)ptr = regs[r0];
break;
CASE_32_64(st16)
- t0 = tci_read_rval(regs, &tb_ptr);
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- *(uint16_t *)(t1 + t2) = t0;
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ *(uint16_t *)ptr = regs[r0];
break;
case INDEX_op_st_i32:
CASE_64(st32)
- t0 = tci_read_rval(regs, &tb_ptr);
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- *(uint32_t *)(t1 + t2) = t0;
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ *(uint32_t *)ptr = regs[r0];
break;
/* Arithmetic operations (mixed 32/64 bit). */
@@ -673,22 +699,19 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
/* Load/store operations (64 bit). */
case INDEX_op_ld32s_i64:
- t0 = *tb_ptr++;
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- tci_write_reg(regs, t0, *(int32_t *)(t1 + t2));
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ regs[r0] = *(int32_t *)ptr;
break;
case INDEX_op_ld_i64:
- t0 = *tb_ptr++;
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- tci_write_reg(regs, t0, *(uint64_t *)(t1 + t2));
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ regs[r0] = *(uint64_t *)ptr;
break;
case INDEX_op_st_i64:
- t0 = tci_read_rval(regs, &tb_ptr);
- t1 = tci_read_rval(regs, &tb_ptr);
- t2 = tci_read_s32(&tb_ptr);
- *(uint64_t *)(t1 + t2) = t0;
+ tci_args_rrs(&tb_ptr, &r0, &r1, &ofs);
+ ptr = (void *)(regs[r1] + ofs);
+ *(uint64_t *)ptr = regs[r0];
break;
/* Arithmetic operations (64 bit). */
Begin splitting out functions that do pure argument decode, without actually loading values from the register set. This means that decoding need not concern itself between input and output registers. We can assert that the register number is in range during decode, so that it is safe to simply dereference from regs[] later. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- tcg/tci.c | 111 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 44 deletions(-) -- 2.25.1