78 changes: 33 additions & 45 deletions target/ppc/translate.c
Expand Up @@ -41,6 +41,10 @@
#include "qemu/qemu-print.h"
#include "qapi/error.h"

#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H

#define CPU_SINGLE_STEP 0x1
#define CPU_BRANCH_STEP 0x2

Expand Down Expand Up @@ -76,8 +80,6 @@ static TCGv cpu_reserve_val2;
static TCGv cpu_fpscr;
static TCGv_i32 cpu_access_type;

#include "exec/gen-icount.h"

void ppc_translate_init(void)
{
int i;
Expand Down Expand Up @@ -294,24 +296,10 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
ctx->base.is_jmp = DISAS_NORETURN;
}

static void gen_icount_io_start(DisasContext *ctx)
{
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
/*
* An I/O instruction must be last in the TB.
* Chain to the next TB, and let the code from gen_tb_start
* decide if we need to return to the main loop.
* Doing this first also allows this value to be overridden.
*/
ctx->base.is_jmp = DISAS_TOO_MANY;
}
}

#if !defined(CONFIG_USER_ONLY)
static void gen_ppc_maybe_interrupt(DisasContext *ctx)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_ppc_maybe_interrupt(cpu_env);
}
#endif
Expand Down Expand Up @@ -548,13 +536,13 @@ void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)
#if !defined(CONFIG_USER_ONLY)
void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_decr(cpu_gpr[gprn], cpu_env);
}

void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_decr(cpu_env, cpu_gpr[gprn]);
}
#endif
Expand All @@ -563,13 +551,13 @@ void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
/* Time base */
void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_tbl(cpu_gpr[gprn], cpu_env);
}

void spr_read_tbu(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_tbu(cpu_gpr[gprn], cpu_env);
}

Expand All @@ -586,13 +574,13 @@ void spr_read_atbu(DisasContext *ctx, int gprn, int sprn)
#if !defined(CONFIG_USER_ONLY)
void spr_write_tbl(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_tbl(cpu_env, cpu_gpr[gprn]);
}

void spr_write_tbu(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_tbu(cpu_env, cpu_gpr[gprn]);
}

Expand All @@ -609,44 +597,44 @@ void spr_write_atbu(DisasContext *ctx, int sprn, int gprn)
#if defined(TARGET_PPC64)
void spr_read_purr(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
}

void spr_write_purr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_purr(cpu_env, cpu_gpr[gprn]);
}

/* HDECR */
void spr_read_hdecr(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_hdecr(cpu_gpr[gprn], cpu_env);
}

void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_hdecr(cpu_env, cpu_gpr[gprn]);
}

void spr_read_vtb(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_vtb(cpu_gpr[gprn], cpu_env);
}

void spr_write_vtb(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_vtb(cpu_env, cpu_gpr[gprn]);
}

void spr_write_tbu40(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_tbu40(cpu_env, cpu_gpr[gprn]);
}

Expand Down Expand Up @@ -791,19 +779,19 @@ void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn)
#if !defined(CONFIG_USER_ONLY)
void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_load_40x_pit(cpu_gpr[gprn], cpu_env);
}

void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_40x_pit(cpu_env, cpu_gpr[gprn]);
}

void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_store_spr(sprn, cpu_gpr[gprn]);
gen_helper_store_40x_dbcr0(cpu_env, cpu_gpr[gprn]);
/* We must stop translation as we may have rebooted */
Expand All @@ -812,19 +800,19 @@ void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn)

void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_40x_sler(cpu_env, cpu_gpr[gprn]);
}

void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_40x_tcr(cpu_env, cpu_gpr[gprn]);
}

void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_40x_tsr(cpu_env, cpu_gpr[gprn]);
}

Expand All @@ -837,13 +825,13 @@ void spr_write_40x_pid(DisasContext *ctx, int sprn, int gprn)

void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_booke_tcr(cpu_env, cpu_gpr[gprn]);
}

void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn)
{
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_helper_store_booke_tsr(cpu_env, cpu_gpr[gprn]);
}
#endif
Expand Down Expand Up @@ -2469,7 +2457,7 @@ static void gen_darn(DisasContext *ctx)
if (l > 2) {
tcg_gen_movi_i64(cpu_gpr[rD(ctx->opcode)], -1);
} else {
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
if (l == 0) {
gen_helper_darn32(cpu_gpr[rD(ctx->opcode)]);
} else {
Expand Down Expand Up @@ -4063,7 +4051,7 @@ static void pmu_count_insns(DisasContext *ctx)
* running with icount and we do not handle it beforehand,
* the helper can trigger a 'bad icount read'.
*/
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);

/* Avoid helper calls when only PMC5-6 are enabled. */
if (!ctx->pmc_other) {
Expand Down Expand Up @@ -4376,7 +4364,7 @@ static void gen_rfi(DisasContext *ctx)
}
/* Restore CPU state */
CHK_SV(ctx);
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_update_cfar(ctx, ctx->cia);
gen_helper_rfi(cpu_env);
ctx->base.is_jmp = DISAS_EXIT;
Expand All @@ -4391,7 +4379,7 @@ static void gen_rfid(DisasContext *ctx)
#else
/* Restore CPU state */
CHK_SV(ctx);
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_update_cfar(ctx, ctx->cia);
gen_helper_rfid(cpu_env);
ctx->base.is_jmp = DISAS_EXIT;
Expand All @@ -4406,7 +4394,7 @@ static void gen_rfscv(DisasContext *ctx)
#else
/* Restore CPU state */
CHK_SV(ctx);
gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_update_cfar(ctx, ctx->cia);
gen_helper_rfscv(cpu_env);
ctx->base.is_jmp = DISAS_EXIT;
Expand Down Expand Up @@ -4731,7 +4719,7 @@ static void gen_mtmsrd(DisasContext *ctx)
t0 = tcg_temp_new();
t1 = tcg_temp_new();

gen_icount_io_start(ctx);
translator_io_start(&ctx->base);

if (ctx->opcode & 0x00010000) {
/* L=1 form only updates EE and RI */
Expand Down Expand Up @@ -4771,7 +4759,7 @@ static void gen_mtmsr(DisasContext *ctx)
t0 = tcg_temp_new();
t1 = tcg_temp_new();

gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
if (ctx->opcode & 0x00010000) {
/* L=1 form only updates EE and RI */
mask &= (1ULL << MSR_RI) | (1ULL << MSR_EE);
Expand Down
2 changes: 1 addition & 1 deletion target/ppc/translate/branch-impl.c.inc
Expand Up @@ -16,7 +16,7 @@ static bool trans_RFEBB(DisasContext *ctx, arg_XL_s *arg)
{
REQUIRE_INSNS_FLAGS2(ctx, ISA207S);

gen_icount_io_start(ctx);
translator_io_start(&ctx->base);
gen_update_cfar(ctx, ctx->cia);
gen_helper_rfebb(cpu_env, cpu_gpr[arg->s]);

Expand Down
1 change: 1 addition & 0 deletions target/riscv/cpu_helper.c
Expand Up @@ -31,6 +31,7 @@
#include "sysemu/cpu-timers.h"
#include "cpu_bits.h"
#include "debug.h"
#include "tcg/oversized-guest.h"

int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
{
Expand Down
8 changes: 2 additions & 6 deletions target/riscv/insn_trans/trans_privileged.c.inc
Expand Up @@ -77,9 +77,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
#ifndef CONFIG_USER_ONLY
if (has_ext(ctx, RVS)) {
decode_save_opc(ctx);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_sret(cpu_pc, cpu_env);
exit_tb(ctx); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
Expand All @@ -96,9 +94,7 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
{
#ifndef CONFIG_USER_ONLY
decode_save_opc(ctx);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_mret(cpu_pc, cpu_env);
exit_tb(ctx); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
Expand Down
24 changes: 6 additions & 18 deletions target/riscv/insn_trans/trans_rvi.c.inc
Expand Up @@ -813,9 +813,7 @@ static bool do_csrr(DisasContext *ctx, int rd, int rc)
TCGv dest = dest_gpr(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);

if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrr(dest, cpu_env, csr);
gen_set_gpr(ctx, rd, dest);
return do_csr_post(ctx);
Expand All @@ -825,9 +823,7 @@ static bool do_csrw(DisasContext *ctx, int rc, TCGv src)
{
TCGv_i32 csr = tcg_constant_i32(rc);

if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrw(cpu_env, csr, src);
return do_csr_post(ctx);
}
Expand All @@ -837,9 +833,7 @@ static bool do_csrrw(DisasContext *ctx, int rd, int rc, TCGv src, TCGv mask)
TCGv dest = dest_gpr(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);

if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrrw(dest, cpu_env, csr, src, mask);
gen_set_gpr(ctx, rd, dest);
return do_csr_post(ctx);
Expand All @@ -851,9 +845,7 @@ static bool do_csrr_i128(DisasContext *ctx, int rd, int rc)
TCGv desth = dest_gprh(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);

if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrr_i128(destl, cpu_env, csr);
tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
gen_set_gpr128(ctx, rd, destl, desth);
Expand All @@ -864,9 +856,7 @@ static bool do_csrw_i128(DisasContext *ctx, int rc, TCGv srcl, TCGv srch)
{
TCGv_i32 csr = tcg_constant_i32(rc);

if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrw_i128(cpu_env, csr, srcl, srch);
return do_csr_post(ctx);
}
Expand All @@ -878,9 +868,7 @@ static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc,
TCGv desth = dest_gprh(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);

if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&ctx->base);
gen_helper_csrrw_i128(destl, cpu_env, csr, srcl, srch, maskl, maskh);
tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
gen_set_gpr128(ctx, rd, destl, desth);
Expand Down
6 changes: 4 additions & 2 deletions target/riscv/translate.c
Expand Up @@ -33,6 +33,10 @@
#include "instmap.h"
#include "internals.h"

#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H

/* global register indices */
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
Expand All @@ -42,8 +46,6 @@ static TCGv load_val;
static TCGv pm_mask;
static TCGv pm_base;

#include "exec/gen-icount.h"

/*
* If an operation is being performed on less than TARGET_LONG_BITS,
* it may require the inputs to be sign- or zero-extended; which will
Expand Down
1 change: 1 addition & 0 deletions target/rx/cpu.c
Expand Up @@ -24,6 +24,7 @@
#include "exec/exec-all.h"
#include "hw/loader.h"
#include "fpu/softfloat.h"
#include "tcg/debug-assert.h"

static void rx_cpu_set_pc(CPUState *cs, vaddr value)
{
Expand Down
1 change: 1 addition & 0 deletions target/rx/op_helper.c
Expand Up @@ -23,6 +23,7 @@
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"
#include "fpu/softfloat.h"
#include "tcg/debug-assert.h"

static inline G_NORETURN
void raise_exception(CPURXState *env, int index,
Expand Down
7 changes: 5 additions & 2 deletions target/rx/translate.c
Expand Up @@ -28,6 +28,11 @@
#include "exec/translator.h"
#include "exec/log.h"

#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H


typedef struct DisasContext {
DisasContextBase base;
CPURXState *env;
Expand Down Expand Up @@ -68,8 +73,6 @@ static TCGv_i64 cpu_acc;

#define cpu_sp cpu_regs[0]

#include "exec/gen-icount.h"

/* decoder helper */
static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
int i, int n)
Expand Down
10 changes: 5 additions & 5 deletions target/s390x/tcg/translate.c
Expand Up @@ -38,14 +38,17 @@
#include "qemu/log.h"
#include "qemu/host-utils.h"
#include "exec/cpu_ldst.h"
#include "exec/gen-icount.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"

#include "exec/translator.h"
#include "exec/log.h"
#include "qemu/atomic128.h"

#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H


/* Information that (most) every instruction needs to manipulate. */
typedef struct DisasContext DisasContext;
Expand Down Expand Up @@ -6350,10 +6353,7 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)

/* input/output is the special case for icount mode */
if (unlikely(insn->flags & IF_IO)) {
icount = tb_cflags(s->base.tb) & CF_USE_ICOUNT;
if (icount) {
gen_io_start();
}
icount = translator_io_start(&s->base);
}
}

Expand Down
21 changes: 16 additions & 5 deletions target/sh4/translate.c
Expand Up @@ -29,6 +29,10 @@
#include "exec/log.h"
#include "qemu/qemu-print.h"

#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H


typedef struct DisasContext {
DisasContextBase base;
Expand Down Expand Up @@ -71,8 +75,6 @@ static TCGv cpu_fregs[32];
/* internal register indexes */
static TCGv cpu_flags, cpu_delayed_pc, cpu_delayed_cond;

#include "exec/gen-icount.h"

void sh4_translate_init(void)
{
int i;
Expand Down Expand Up @@ -2142,9 +2144,7 @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)

/* The entire region has been translated. */
ctx->envflags &= ~TB_FLAG_GUSA_MASK;
ctx->base.pc_next = pc_end;
ctx->base.num_insns += max_insns - 1;
return;
goto done;

fail:
qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",
Expand All @@ -2161,8 +2161,19 @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
purposes of accounting within the TB. We might as well report the
entire region consumed via ctx->base.pc_next so that it's immediately
available in the disassembly dump. */

done:
ctx->base.pc_next = pc_end;
ctx->base.num_insns += max_insns - 1;

/*
* Emit insn_start to cover each of the insns in the region.
* This matches an assert in tcg.c making sure that we have
* tb->icount * insn_start.
*/
for (i = 1; i < max_insns; ++i) {
tcg_gen_insn_start(pc + i * 2, ctx->envflags);
}
}
#endif

Expand Down
2 changes: 0 additions & 2 deletions target/sparc/cpu.h
Expand Up @@ -581,7 +581,6 @@ G_NORETURN void sparc_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
uintptr_t retaddr);
G_NORETURN void cpu_raise_exception_ra(CPUSPARCState *, int, uintptr_t);

#ifndef NO_CPU_IO_DEFS
/* cpu_init.c */
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
void sparc_cpu_list(void);
Expand Down Expand Up @@ -637,7 +636,6 @@ static inline int tlb_compare_context(const SparcTLBEntry *tlb,
return compare_masked(context, tlb->tag, MMU_CONTEXT_MASK);
}

#endif
#endif

/* cpu-exec.c */
Expand Down
78 changes: 20 additions & 58 deletions target/sparc/translate.c
Expand Up @@ -33,6 +33,9 @@
#include "exec/log.h"
#include "asi.h"

#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H

#define DYNAMIC_PC 1 /* dynamic pc value */
#define JUMP_PC 2 /* dynamic pc value which takes only two values
Expand Down Expand Up @@ -63,8 +66,6 @@ static TCGv cpu_wim;
/* Floating point registers */
static TCGv_i64 cpu_fpr[TARGET_DPREGS];

#include "exec/gen-icount.h"

typedef struct DisasContext {
DisasContextBase base;
target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
Expand Down Expand Up @@ -3214,16 +3215,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_const = tcg_constant_i32(dc->mem_idx);
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, tick));
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
r_const);
gen_store_gpr(dc, rd, cpu_dst);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O operations in icount mode must end the TB */
dc->base.is_jmp = DISAS_EXIT;
}
}
break;
case 0x5: /* V9 rdpc */
Expand Down Expand Up @@ -3266,16 +3263,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_const = tcg_constant_i32(dc->mem_idx);
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, stick));
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
r_const);
gen_store_gpr(dc, rd, cpu_dst);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O operations in icount mode must end the TB */
dc->base.is_jmp = DISAS_EXIT;
}
}
break;
case 0x19: /* System tick compare */
Expand Down Expand Up @@ -3396,15 +3389,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_const = tcg_constant_i32(dc->mem_idx);
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, tick));
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_tick_get_count(cpu_tmp0, cpu_env,
r_tickptr, r_const);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O operations in icount mode must end the TB */
dc->base.is_jmp = DISAS_EXIT;
}
}
break;
case 5: // tba
Expand Down Expand Up @@ -4209,10 +4198,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, tick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_limit(r_tickptr,
cpu_tick_cmpr);
/* End TB to handle timer interrupt */
Expand All @@ -4232,10 +4218,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, stick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_count(r_tickptr,
cpu_tmp0);
/* End TB to handle timer interrupt */
Expand All @@ -4255,10 +4238,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, stick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_limit(r_tickptr,
cpu_stick_cmpr);
/* End TB to handle timer interrupt */
Expand Down Expand Up @@ -4366,10 +4346,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, tick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_count(r_tickptr,
cpu_tmp0);
/* End TB to handle timer interrupt */
Expand All @@ -4381,14 +4358,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
break;
case 6: // pstate
save_state(dc);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_helper_wrpstate(cpu_env, cpu_tmp0);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O ops in icount mode must end the TB */
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_wrpstate(cpu_env, cpu_tmp0);
dc->npc = DYNAMIC_PC;
break;
case 7: // tl
Expand All @@ -4398,14 +4371,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
dc->npc = DYNAMIC_PC;
break;
case 8: // pil
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_helper_wrpil(cpu_env, cpu_tmp0);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
/* I/O ops in icount mode must end the TB */
if (translator_io_start(&dc->base)) {
dc->base.is_jmp = DISAS_EXIT;
}
gen_helper_wrpil(cpu_env, cpu_tmp0);
break;
case 9: // cwp
gen_helper_wrcwp(cpu_env, cpu_tmp0);
Expand Down Expand Up @@ -4496,10 +4465,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
r_tickptr = tcg_temp_new_ptr();
tcg_gen_ld_ptr(r_tickptr, cpu_env,
offsetof(CPUSPARCState, hstick));
if (tb_cflags(dc->base.tb) &
CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_tick_set_limit(r_tickptr,
cpu_hstick_cmpr);
/* End TB to handle timer interrupt */
Expand Down Expand Up @@ -5122,19 +5088,15 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
goto priv_insn;
dc->npc = DYNAMIC_PC;
dc->pc = DYNAMIC_PC;
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_done(cpu_env);
goto jmp_insn;
case 1:
if (!supervisor(dc))
goto priv_insn;
dc->npc = DYNAMIC_PC;
dc->pc = DYNAMIC_PC;
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_retry(cpu_env);
goto jmp_insn;
default:
Expand Down
1 change: 1 addition & 0 deletions target/tricore/cpu.c
Expand Up @@ -22,6 +22,7 @@
#include "cpu.h"
#include "exec/exec-all.h"
#include "qemu/error-report.h"
#include "tcg/debug-assert.h"

static inline void set_feature(CPUTriCoreState *env, int feature)
{
Expand Down
7 changes: 5 additions & 2 deletions target/tricore/translate.c
Expand Up @@ -33,6 +33,11 @@
#include "exec/translator.h"
#include "exec/log.h"

#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H


/*
* TCG registers
*/
Expand All @@ -50,8 +55,6 @@ static TCGv cpu_PSW_SV;
static TCGv cpu_PSW_AV;
static TCGv cpu_PSW_SAV;

#include "exec/gen-icount.h"

static const char *regnames_a[] = {
"a0" , "a1" , "a2" , "a3" , "a4" , "a5" ,
"a6" , "a7" , "a8" , "a9" , "sp" , "a11" ,
Expand Down
31 changes: 10 additions & 21 deletions target/xtensa/translate.c
Expand Up @@ -45,6 +45,10 @@

#include "exec/log.h"

#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H


struct DisasContext {
DisasContextBase base;
Expand Down Expand Up @@ -90,8 +94,6 @@ static TCGv_i32 cpu_exclusive_val;

static GHashTable *xtensa_regfile_table;

#include "exec/gen-icount.h"

static char *sr_name[256];
static char *ur_name[256];

Expand Down Expand Up @@ -573,9 +575,7 @@ static int gen_postprocess(DisasContext *dc, int slot)

#ifndef CONFIG_USER_ONLY
if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_check_interrupts(cpu_env);
}
#endif
Expand Down Expand Up @@ -2125,9 +2125,7 @@ static void translate_rsr_ccount(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_update_ccount(cpu_env);
tcg_gen_mov_i32(arg[0].out, cpu_SR[par[0]]);
#endif
Expand Down Expand Up @@ -2443,9 +2441,7 @@ static void translate_waiti(DisasContext *dc, const OpcodeArg arg[],
#ifndef CONFIG_USER_ONLY
TCGv_i32 pc = tcg_constant_i32(dc->base.pc_next);

if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_waiti(cpu_env, pc, tcg_constant_i32(arg[0].imm));
#endif
}
Expand Down Expand Up @@ -2510,9 +2506,7 @@ static void translate_wsr_ccompare(DisasContext *dc, const OpcodeArg arg[],
uint32_t id = par[0] - CCOMPARE;

assert(id < dc->config->nccompare);
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
tcg_gen_mov_i32(cpu_SR[par[0]], arg[0].in);
gen_helper_update_ccompare(cpu_env, tcg_constant_i32(id));
#endif
Expand All @@ -2522,9 +2516,7 @@ static void translate_wsr_ccount(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
translator_io_start(&dc->base);
gen_helper_wsr_ccount(cpu_env, arg[0].in);
#endif
}
Expand Down Expand Up @@ -2711,10 +2703,7 @@ static void translate_xsr_ccount(DisasContext *dc, const OpcodeArg arg[],
#ifndef CONFIG_USER_ONLY
TCGv_i32 tmp = tcg_temp_new_i32();

if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}

translator_io_start(&dc->base);
gen_helper_update_ccount(cpu_env);
tcg_gen_mov_i32(tmp, cpu_SR[par[0]]);
gen_helper_wsr_ccount(cpu_env, arg[0].in);
Expand Down
12 changes: 12 additions & 0 deletions tcg/aarch64/tcg-target-reg-bits.h
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Define target-specific register size
* Copyright (c) 2023 Linaro
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

#define TCG_TARGET_REG_BITS 64

#endif
8 changes: 5 additions & 3 deletions tcg/aarch64/tcg-target.c.inc
Expand Up @@ -1636,6 +1636,9 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
return true;
}

/* We expect to use a 7-bit scaled negative offset from ENV. */
#define MIN_TLB_MASK_TABLE_OFS -512

/*
* For softmmu, perform the TLB load and compare.
* For useronly, perform any required alignment tests.
Expand Down Expand Up @@ -1674,12 +1677,10 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
? TCG_TYPE_I64 : TCG_TYPE_I32);

/* Load env_tlb(env)->f[mmu_idx].{mask,table} into {tmp0,tmp1}. */
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -512);
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0);
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 8);
tcg_out_insn(s, 3314, LDP, TCG_REG_TMP0, TCG_REG_TMP1, TCG_AREG0,
TLB_MASK_TABLE_OFS(mem_index), 1, 0);
tlb_mask_table_ofs(s, mem_index), 1, 0);

/* Extract the TLB index from the address into X0. */
tcg_out_insn(s, 3502S, AND_LSR, mask_type == TCG_TYPE_I64,
Expand All @@ -1690,6 +1691,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
tcg_out_insn(s, 3502, ADD, 1, TCG_REG_TMP1, TCG_REG_TMP1, TCG_REG_TMP0);

/* Load the tlb comparator into TMP0, and the fast path addend into TMP1. */
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP1,
is_ld ? offsetof(CPUTLBEntry, addr_read)
: offsetof(CPUTLBEntry, addr_write));
Expand Down
12 changes: 12 additions & 0 deletions tcg/arm/tcg-target-reg-bits.h
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: MIT */
/*
* Define target-specific register size
* Copyright (c) 2023 Linaro
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

#define TCG_TARGET_REG_BITS 32

#endif
8 changes: 5 additions & 3 deletions tcg/arm/tcg-target.c.inc
Expand Up @@ -1374,6 +1374,9 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
return true;
}

/* We expect to use an 9-bit sign-magnitude negative offset from ENV. */
#define MIN_TLB_MASK_TABLE_OFS -256

static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
TCGReg addrlo, TCGReg addrhi,
MemOpIdx oi, bool is_ld)
Expand Down Expand Up @@ -1405,7 +1408,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
int mem_index = get_mmuidx(oi);
int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
: offsetof(CPUTLBEntry, addr_write);
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
int fast_off = tlb_mask_table_ofs(s, mem_index);
unsigned s_mask = (1 << (opc & MO_SIZE)) - 1;
TCGReg t_addr;

Expand All @@ -1416,8 +1419,6 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
ldst->addrhi_reg = addrhi;

/* Load env_tlb(env)->f[mmu_idx].{mask,table} into {r0,r1}. */
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -256);
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0);
QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 4);
tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_AREG0, fast_off);
Expand All @@ -1430,6 +1431,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
* Add the tlb_table pointer, creating the CPUTLBEntry address in R1.
* Load the tlb comparator into R2/R3 and the fast path addend into R1.
*/
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
if (cmp_off == 0) {
if (s->addr_type == TCG_TYPE_I32) {
tcg_out_ld32_rwb(s, COND_AL, TCG_REG_R2, TCG_REG_R1, TCG_REG_R0);
Expand Down
16 changes: 16 additions & 0 deletions tcg/i386/tcg-target-reg-bits.h
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: MIT */
/*
* Define target-specific register size
* Copyright (c) 2008 Fabrice Bellard
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

#ifdef __x86_64__
# define TCG_TARGET_REG_BITS 64
#else
# define TCG_TARGET_REG_BITS 32
#endif

#endif
9 changes: 5 additions & 4 deletions tcg/i386/tcg-target.c.inc
Expand Up @@ -1900,6 +1900,8 @@ static inline int setup_guest_base_seg(void)
#endif /* setup_guest_base_seg */
#endif /* !SOFTMMU */

#define MIN_TLB_MASK_TABLE_OFS INT_MIN

/*
* For softmmu, perform the TLB load and compare.
* For useronly, perform any required alignment tests.
Expand Down Expand Up @@ -1934,6 +1936,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
int trexw = 0, hrexw = 0, tlbrexw = 0;
unsigned mem_index = get_mmuidx(oi);
unsigned s_mask = (1 << s_bits) - 1;
int fast_ofs = tlb_mask_table_ofs(s, mem_index);
int tlb_mask;

ldst = new_ldst_label(s);
Expand All @@ -1959,12 +1962,10 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
s->page_bits - CPU_TLB_ENTRY_BITS);

tcg_out_modrm_offset(s, OPC_AND_GvEv + trexw, TCG_REG_L0, TCG_AREG0,
TLB_MASK_TABLE_OFS(mem_index) +
offsetof(CPUTLBDescFast, mask));
fast_ofs + offsetof(CPUTLBDescFast, mask));

tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, TCG_REG_L0, TCG_AREG0,
TLB_MASK_TABLE_OFS(mem_index) +
offsetof(CPUTLBDescFast, table));
fast_ofs + offsetof(CPUTLBDescFast, table));

/*
* If the required alignment is at least as large as the access, simply
Expand Down
2 changes: 0 additions & 2 deletions tcg/i386/tcg-target.h
Expand Up @@ -30,11 +30,9 @@
#define TCG_TARGET_INSN_UNIT_SIZE 1

#ifdef __x86_64__
# define TCG_TARGET_REG_BITS 64
# define TCG_TARGET_NB_REGS 32
# define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB)
#else
# define TCG_TARGET_REG_BITS 32
# define TCG_TARGET_NB_REGS 24
# define MAX_CODE_GEN_BUFFER_SIZE UINT32_MAX
#endif
Expand Down
21 changes: 21 additions & 0 deletions tcg/loongarch64/tcg-target-reg-bits.h
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: MIT */
/*
* Define target-specific register size
* Copyright (c) 2021 WANG Xuerui <git@xen0n.name>
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

/*
* Loongson removed the (incomplete) 32-bit support from kernel and toolchain
* for the initial upstreaming of this architecture, so don't bother and just
* support the LP64* ABI for now.
*/
#if defined(__loongarch64)
# define TCG_TARGET_REG_BITS 64
#else
# error unsupported LoongArch register size
#endif

#endif
8 changes: 5 additions & 3 deletions tcg/loongarch64/tcg-target.c.inc
Expand Up @@ -834,6 +834,9 @@ bool tcg_target_has_memory_bswap(MemOp memop)
return false;
}

/* We expect to use a 12-bit negative offset from ENV. */
#define MIN_TLB_MASK_TABLE_OFS -(1 << 11)

/*
* For softmmu, perform the TLB load and compare.
* For useronly, perform any required alignment tests.
Expand All @@ -855,7 +858,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
#ifdef CONFIG_SOFTMMU
unsigned s_bits = opc & MO_SIZE;
int mem_index = get_mmuidx(oi);
int fast_ofs = TLB_MASK_TABLE_OFS(mem_index);
int fast_ofs = tlb_mask_table_ofs(s, mem_index);
int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);

Expand All @@ -864,8 +867,6 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
ldst->oi = oi;
ldst->addrlo_reg = addr_reg;

QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11));
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);

Expand All @@ -875,6 +876,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);

/* Load the tlb comparator and the addend. */
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
is_ld ? offsetof(CPUTLBEntry, addr_read)
: offsetof(CPUTLBEntry, addr_write));
Expand Down
11 changes: 0 additions & 11 deletions tcg/loongarch64/tcg-target.h
Expand Up @@ -29,17 +29,6 @@
#ifndef LOONGARCH_TCG_TARGET_H
#define LOONGARCH_TCG_TARGET_H

/*
* Loongson removed the (incomplete) 32-bit support from kernel and toolchain
* for the initial upstreaming of this architecture, so don't bother and just
* support the LP64* ABI for now.
*/
#if defined(__loongarch64)
# define TCG_TARGET_REG_BITS 64
#else
# error unsupported LoongArch register size
#endif

#define TCG_TARGET_INSN_UNIT_SIZE 4
#define TCG_TARGET_NB_REGS 32

Expand Down
30 changes: 27 additions & 3 deletions tcg/meson.build
@@ -1,3 +1,7 @@
if not get_option('tcg').allowed()
subdir_done()
endif

tcg_ss = ss.source_set()

tcg_ss.add(files(
Expand All @@ -14,8 +18,28 @@ tcg_ss.add(files(
if get_option('tcg_interpreter')
libffi = dependency('libffi', version: '>=3.0', required: true,
method: 'pkg-config')
specific_ss.add(libffi)
specific_ss.add(files('tci.c'))
tcg_ss.add(libffi)
tcg_ss.add(files('tci.c'))
endif

specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
tcg_ss = tcg_ss.apply(config_host, strict: false)

libtcg_user = static_library('tcg_user',
tcg_ss.sources() + genh,
name_suffix: 'fa',
c_args: '-DCONFIG_USER_ONLY',
build_by_default: have_user)

tcg_user = declare_dependency(link_with: libtcg_user,
dependencies: tcg_ss.dependencies())
user_ss.add(tcg_user)

libtcg_softmmu = static_library('tcg_softmmu',
tcg_ss.sources() + genh,
name_suffix: 'fa',
c_args: '-DCONFIG_SOFTMMU',
build_by_default: have_system)

tcg_softmmu = declare_dependency(link_with: libtcg_softmmu,
dependencies: tcg_ss.dependencies())
softmmu_ss.add(tcg_softmmu)
18 changes: 18 additions & 0 deletions tcg/mips/tcg-target-reg-bits.h
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: MIT */
/*
* Define target-specific register size
* Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

#if _MIPS_SIM == _ABIO32
# define TCG_TARGET_REG_BITS 32
#elif _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
# define TCG_TARGET_REG_BITS 64
#else
# error "Unknown ABI"
#endif

#endif
20 changes: 12 additions & 8 deletions tcg/mips/tcg-target.c.inc
Expand Up @@ -1254,6 +1254,9 @@ bool tcg_target_has_memory_bswap(MemOp memop)
return false;
}

/* We expect to use a 16-bit negative offset from ENV. */
#define MIN_TLB_MASK_TABLE_OFS -32768

/*
* For softmmu, perform the TLB load and compare.
* For useronly, perform any required alignment tests.
Expand All @@ -1279,7 +1282,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
#ifdef CONFIG_SOFTMMU
unsigned s_mask = (1 << s_bits) - 1;
int mem_index = get_mmuidx(oi);
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
int fast_off = tlb_mask_table_ofs(s, mem_index);
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
int add_off = offsetof(CPUTLBEntry, addend);
Expand All @@ -1293,8 +1296,6 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
ldst->addrhi_reg = addrhi;

/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -32768);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP1, TCG_AREG0, table_off);

Expand All @@ -1311,14 +1312,17 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
/* Add the tlb_table pointer, creating the CPUTLBEntry address in TMP3. */
tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP3, TCG_TMP3, TCG_TMP1);

if (TCG_TARGET_REG_BITS == 32 || addr_type == TCG_TYPE_I32) {
/* Load the (low half) tlb comparator. */
tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3,
cmp_off + HOST_BIG_ENDIAN * 4);
} else {
tcg_out_ld(s, TCG_TYPE_I64, TCG_TMP0, TCG_TMP3, cmp_off);
}

if (TCG_TARGET_REG_BITS == 64 || addr_type == TCG_TYPE_I32) {
/* Load the tlb comparator. */
tcg_out_ld(s, addr_type, TCG_TMP0, TCG_TMP3, cmp_off);
/* Load the tlb addend for the fast path. */
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP3, TCG_TMP3, add_off);
} else {
/* Load the low half of the tlb comparator. */
tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + LO_OFF);
}

/*
Expand Down
8 changes: 0 additions & 8 deletions tcg/mips/tcg-target.h
Expand Up @@ -27,14 +27,6 @@
#ifndef MIPS_TCG_TARGET_H
#define MIPS_TCG_TARGET_H

#if _MIPS_SIM == _ABIO32
# define TCG_TARGET_REG_BITS 32
#elif _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
# define TCG_TARGET_REG_BITS 64
#else
# error "Unknown ABI"
#endif

#define TCG_TARGET_INSN_UNIT_SIZE 4
#define TCG_TARGET_NB_REGS 32

Expand Down
2 changes: 1 addition & 1 deletion tcg/optimize.c
Expand Up @@ -25,7 +25,7 @@

#include "qemu/osdep.h"
#include "qemu/int128.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-common.h"
#include "tcg-internal.h"

#define CASE_OP_32_64(x) \
Expand Down
16 changes: 16 additions & 0 deletions tcg/ppc/tcg-target-reg-bits.h
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: MIT */
/*
* Define target-specific register size
* Copyright (c) 2008 Fabrice Bellard
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

#ifdef _ARCH_PPC64
# define TCG_TARGET_REG_BITS 64
#else
# define TCG_TARGET_REG_BITS 32
#endif

#endif
46 changes: 26 additions & 20 deletions tcg/ppc/tcg-target.c.inc
Expand Up @@ -2036,6 +2036,9 @@ bool tcg_target_has_memory_bswap(MemOp memop)
return aa.atom <= MO_64;
}

/* We expect to use a 16-bit negative offset from ENV. */
#define MIN_TLB_MASK_TABLE_OFS -32768

/*
* For softmmu, perform the TLB load and compare.
* For useronly, perform any required alignment tests.
Expand All @@ -2046,6 +2049,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
TCGReg addrlo, TCGReg addrhi,
MemOpIdx oi, bool is_ld)
{
TCGType addr_type = s->addr_type;
TCGLabelQemuLdst *ldst = NULL;
MemOp opc = get_memop(oi);
MemOp a_bits, s_bits;
Expand All @@ -2071,7 +2075,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
int mem_index = get_mmuidx(oi);
int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
: offsetof(CPUTLBEntry, addr_write);
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
int fast_off = tlb_mask_table_ofs(s, mem_index);
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
int table_off = fast_off + offsetof(CPUTLBDescFast, table);

Expand All @@ -2082,8 +2086,6 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
ldst->addrhi_reg = addrhi;

/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -32768);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, mask_off);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_AREG0, table_off);

Expand All @@ -2097,26 +2099,31 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
}
tcg_out32(s, AND | SAB(TCG_REG_TMP1, TCG_REG_TMP1, TCG_REG_R0));

/* Load the (low part) TLB comparator into TMP2. */
if (cmp_off == 0 && TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) {
uint32_t lxu = (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32
? LWZUX : LDUX);
tcg_out32(s, lxu | TAB(TCG_REG_TMP2, TCG_REG_TMP1, TCG_REG_TMP2));
} else {
tcg_out32(s, ADD | TAB(TCG_REG_TMP1, TCG_REG_TMP1, TCG_REG_TMP2));
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_TMP2,
TCG_REG_TMP1, cmp_off + 4 * HOST_BIG_ENDIAN);
/*
* Load the (low part) TLB comparator into TMP2.
* For 64-bit host, always load the entire 64-bit slot for simplicity.
* We will ignore the high bits with tcg_out_cmp(..., addr_type).
*/
if (TCG_TARGET_REG_BITS == 64) {
if (cmp_off == 0) {
tcg_out32(s, LDUX | TAB(TCG_REG_TMP2, TCG_REG_TMP1, TCG_REG_TMP2));
} else {
tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP2, TCG_REG_TMP1, cmp_off);
tcg_out32(s, ADD | TAB(TCG_REG_TMP1, TCG_REG_TMP1, TCG_REG_TMP2));
tcg_out_ld(s, TCG_TYPE_I64, TCG_REG_TMP2, TCG_REG_TMP1, cmp_off);
}
} else if (cmp_off == 0 && !HOST_BIG_ENDIAN) {
tcg_out32(s, LWZUX | TAB(TCG_REG_TMP2, TCG_REG_TMP1, TCG_REG_TMP2));
} else {
tcg_out32(s, ADD | TAB(TCG_REG_TMP1, TCG_REG_TMP1, TCG_REG_TMP2));
tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_TMP2, TCG_REG_TMP1,
cmp_off + 4 * HOST_BIG_ENDIAN);
}

/*
* Load the TLB addend for use on the fast path.
* Do this asap to minimize any load use delay.
*/
if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) {
if (TCG_TARGET_REG_BITS == 64 || addr_type == TCG_TYPE_I32) {
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_REG_TMP1,
offsetof(CPUTLBEntry, addend));
}
Expand Down Expand Up @@ -2151,7 +2158,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
}

/* Mask the address for the requested alignment. */
if (TARGET_LONG_BITS == 32) {
if (addr_type == TCG_TYPE_I32) {
tcg_out_rlw(s, RLWINM, TCG_REG_R0, t, 0,
(32 - a_bits) & 31, 31 - s->page_bits);
} else if (a_bits == 0) {
Expand All @@ -2163,7 +2170,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
}
}

if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
if (TCG_TARGET_REG_BITS == 32 && addr_type != TCG_TYPE_I32) {
/* Low part comparison into cr7. */
tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP2,
0, 7, TCG_TYPE_I32);
Expand All @@ -2183,8 +2190,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
} else {
/* Full comparison into cr7. */
tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP2,
0, 7, TCG_TYPE_TL);
tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP2, 0, 7, addr_type);
}

/* Load a pointer into the current opcode w/conditional branch-link. */
Expand All @@ -2211,7 +2217,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
h->base = guest_base ? TCG_GUEST_BASE_REG : 0;
#endif

if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
if (TCG_TARGET_REG_BITS == 64 && addr_type == TCG_TYPE_I32) {
/* Zero-extend the guest address for use in the host address. */
tcg_out_ext32u(s, TCG_REG_R0, addrlo);
h->index = TCG_REG_R0;
Expand Down
5 changes: 0 additions & 5 deletions tcg/ppc/tcg-target.h
Expand Up @@ -25,11 +25,6 @@
#ifndef PPC_TCG_TARGET_H
#define PPC_TCG_TARGET_H

#ifdef _ARCH_PPC64
# define TCG_TARGET_REG_BITS 64
#else
# define TCG_TARGET_REG_BITS 32
#endif
#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)

#define TCG_TARGET_NB_REGS 64
Expand Down
20 changes: 14 additions & 6 deletions tcg/region.c
Expand Up @@ -30,8 +30,8 @@
#include "qemu/cacheinfo.h"
#include "qemu/qtree.h"
#include "qapi/error.h"
#include "exec/exec-all.h"
#include "tcg/tcg.h"
#include "exec/translation-block.h"
#include "tcg-internal.h"


Expand Down Expand Up @@ -505,6 +505,14 @@ static int alloc_code_gen_buffer(size_t tb_size, int splitwx, Error **errp)
return PROT_READ | PROT_WRITE;
}
#elif defined(_WIN32)
/*
* Local source-level compatibility with Unix.
* Used by tcg_region_init below.
*/
#define PROT_READ 1
#define PROT_WRITE 2
#define PROT_EXEC 4

static int alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)
{
void *buf;
Expand All @@ -525,7 +533,7 @@ static int alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)
region.start_aligned = buf;
region.total_size = size;

return PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return PROT_READ | PROT_WRITE | PROT_EXEC;
}
#else
static int alloc_code_gen_buffer_anon(size_t size, int prot,
Expand Down Expand Up @@ -794,10 +802,10 @@ void tcg_region_init(size_t tb_size, int splitwx, unsigned max_cpus)
* buffer -- let that one use hugepages throughout.
* Work with the page protections set up with the initial mapping.
*/
need_prot = PAGE_READ | PAGE_WRITE;
need_prot = PROT_READ | PROT_WRITE;
#ifndef CONFIG_TCG_INTERPRETER
if (tcg_splitwx_diff == 0) {
need_prot |= PAGE_EXEC;
need_prot |= PROT_EXEC;
}
#endif
for (size_t i = 0, n = region.n; i < n; i++) {
Expand All @@ -807,9 +815,9 @@ void tcg_region_init(size_t tb_size, int splitwx, unsigned max_cpus)
if (have_prot != need_prot) {
int rc;

if (need_prot == (PAGE_READ | PAGE_WRITE | PAGE_EXEC)) {
if (need_prot == (PROT_READ | PROT_WRITE | PROT_EXEC)) {
rc = qemu_mprotect_rwx(start, end - start);
} else if (need_prot == (PAGE_READ | PAGE_WRITE)) {
} else if (need_prot == (PROT_READ | PROT_WRITE)) {
rc = qemu_mprotect_rw(start, end - start);
} else {
g_assert_not_reached();
Expand Down
19 changes: 19 additions & 0 deletions tcg/riscv/tcg-target-reg-bits.h
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: MIT */
/*
* Define target-specific register size
* Copyright (c) 2018 SiFive, Inc
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

/*
* We don't support oversize guests.
* Since we will only build tcg once, this in turn requires a 64-bit host.
*/
#if __riscv_xlen != 64
#error "unsupported code generation mode"
#endif
#define TCG_TARGET_REG_BITS 64

#endif
21 changes: 12 additions & 9 deletions tcg/riscv/tcg-target.c.inc
Expand Up @@ -1185,6 +1185,9 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
return true;
}

/* We expect to use a 12-bit negative offset from ENV. */
#define MIN_TLB_MASK_TABLE_OFS -(1 << 11)

/*
* For softmmu, perform the TLB load and compare.
* For useronly, perform any required alignment tests.
Expand All @@ -1195,6 +1198,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
TCGReg addr_reg, MemOpIdx oi,
bool is_ld)
{
TCGType addr_type = s->addr_type;
TCGLabelQemuLdst *ldst = NULL;
MemOp opc = get_memop(oi);
TCGAtomAlign aa;
Expand All @@ -1207,7 +1211,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
unsigned s_bits = opc & MO_SIZE;
unsigned s_mask = (1u << s_bits) - 1;
int mem_index = get_mmuidx(oi);
int fast_ofs = TLB_MASK_TABLE_OFS(mem_index);
int fast_ofs = tlb_mask_table_ofs(s, mem_index);
int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
int compare_mask;
Expand All @@ -1218,8 +1222,6 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
ldst->oi = oi;
ldst->addrlo_reg = addr_reg;

QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11));
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);

Expand All @@ -1236,19 +1238,20 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
addr_adj = addr_reg;
if (a_mask < s_mask) {
addr_adj = TCG_REG_TMP0;
tcg_out_opc_imm(s, TARGET_LONG_BITS == 32 ? OPC_ADDIW : OPC_ADDI,
tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI,
addr_adj, addr_reg, s_mask - a_mask);
}
compare_mask = s->page_mask | a_mask;
if (compare_mask == sextreg(compare_mask, 0, 12)) {
tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask);
} else {
tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask);
tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask);
tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj);
}

/* Load the tlb comparator and the addend. */
tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2,
QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
is_ld ? offsetof(CPUTLBEntry, addr_read)
: offsetof(CPUTLBEntry, addr_write));
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
Expand All @@ -1259,7 +1262,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);

/* TLB Hit - translate address using addend. */
if (TARGET_LONG_BITS == 64) {
if (addr_type != TCG_TYPE_I32) {
tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
} else if (have_zba) {
tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
Expand Down Expand Up @@ -1287,15 +1290,15 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,

if (guest_base != 0) {
base = TCG_REG_TMP0;
if (TARGET_LONG_BITS == 64) {
if (addr_type != TCG_TYPE_I32) {
tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, TCG_GUEST_BASE_REG);
} else if (have_zba) {
tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, TCG_GUEST_BASE_REG);
} else {
tcg_out_ext32u(s, base, addr_reg);
tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
}
} else if (TARGET_LONG_BITS == 64) {
} else if (addr_type != TCG_TYPE_I32) {
base = addr_reg;
} else {
base = TCG_REG_TMP0;
Expand Down
9 changes: 0 additions & 9 deletions tcg/riscv/tcg-target.h
Expand Up @@ -25,15 +25,6 @@
#ifndef RISCV_TCG_TARGET_H
#define RISCV_TCG_TARGET_H

/*
* We don't support oversize guests.
* Since we will only build tcg once, this in turn requires a 64-bit host.
*/
#if __riscv_xlen != 64
#error "unsupported code generation mode"
#endif
#define TCG_TARGET_REG_BITS 64

#define TCG_TARGET_INSN_UNIT_SIZE 4
#define TCG_TARGET_NB_REGS 32
#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
Expand Down
17 changes: 17 additions & 0 deletions tcg/s390x/tcg-target-reg-bits.h
@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: MIT */
/*
* Define target-specific register size
* Copyright (c) 2009 Ulrich Hecht <uli@suse.de>
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

/* We only support generating code for 64-bit mode. */
#if UINTPTR_MAX == UINT64_MAX
# define TCG_TARGET_REG_BITS 64
#else
# error "unsupported code generation mode"
#endif

#endif
22 changes: 10 additions & 12 deletions tcg/s390x/tcg-target.c.inc
Expand Up @@ -24,11 +24,6 @@
* THE SOFTWARE.
*/

/* We only support generating code for 64-bit mode. */
#if TCG_TARGET_REG_BITS != 64
#error "unsupported code generation mode"
#endif

#include "../tcg-ldst.c.inc"
#include "../tcg-pool.c.inc"
#include "elf.h"
Expand Down Expand Up @@ -1735,6 +1730,9 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
return true;
}

/* We're expecting to use a 20-bit negative offset on the tlb memory ops. */
#define MIN_TLB_MASK_TABLE_OFS -(1 << 19)

/*
* For softmmu, perform the TLB load and compare.
* For useronly, perform any required alignment tests.
Expand All @@ -1745,6 +1743,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
TCGReg addr_reg, MemOpIdx oi,
bool is_ld)
{
TCGType addr_type = s->addr_type;
TCGLabelQemuLdst *ldst = NULL;
MemOp opc = get_memop(oi);
MemOp s_bits = opc & MO_SIZE;
Expand All @@ -1756,7 +1755,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
#ifdef CONFIG_SOFTMMU
unsigned s_mask = (1 << s_bits) - 1;
int mem_index = get_mmuidx(oi);
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
int fast_off = tlb_mask_table_ofs(s, mem_index);
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
int ofs, a_off;
Expand All @@ -1770,8 +1769,6 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
tcg_out_sh64(s, RSY_SRLG, TCG_TMP0, addr_reg, TCG_REG_NONE,
s->page_bits - CPU_TLB_ENTRY_BITS);

QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 19));
tcg_out_insn(s, RXY, NG, TCG_TMP0, TCG_AREG0, TCG_REG_NONE, mask_off);
tcg_out_insn(s, RXY, AG, TCG_TMP0, TCG_AREG0, TCG_REG_NONE, table_off);

Expand All @@ -1786,15 +1783,16 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
tgen_andi_risbg(s, TCG_REG_R0, addr_reg, tlb_mask);
} else {
tcg_out_insn(s, RX, LA, TCG_REG_R0, addr_reg, TCG_REG_NONE, a_off);
tgen_andi(s, TCG_TYPE_TL, TCG_REG_R0, tlb_mask);
tgen_andi(s, addr_type, TCG_REG_R0, tlb_mask);
}

if (is_ld) {
ofs = offsetof(CPUTLBEntry, addr_read);
} else {
ofs = offsetof(CPUTLBEntry, addr_write);
}
if (TARGET_LONG_BITS == 32) {
if (addr_type == TCG_TYPE_I32) {
ofs += HOST_BIG_ENDIAN * 4;
tcg_out_insn(s, RX, C, TCG_REG_R0, TCG_TMP0, TCG_REG_NONE, ofs);
} else {
tcg_out_insn(s, RXY, CG, TCG_REG_R0, TCG_TMP0, TCG_REG_NONE, ofs);
Expand All @@ -1807,7 +1805,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
tcg_out_insn(s, RXY, LG, h->index, TCG_TMP0, TCG_REG_NONE,
offsetof(CPUTLBEntry, addend));

if (TARGET_LONG_BITS == 32) {
if (addr_type == TCG_TYPE_I32) {
tcg_out_insn(s, RRE, ALGFR, h->index, addr_reg);
h->base = TCG_REG_NONE;
} else {
Expand All @@ -1830,7 +1828,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
}

h->base = addr_reg;
if (TARGET_LONG_BITS == 32) {
if (addr_type == TCG_TYPE_I32) {
tcg_out_ext32u(s, TCG_TMP0, addr_reg);
h->base = TCG_TMP0;
}
Expand Down
12 changes: 12 additions & 0 deletions tcg/sparc64/tcg-target-reg-bits.h
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: MIT */
/*
* Define target-specific register size
* Copyright (c) 2023 Linaro
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

#define TCG_TARGET_REG_BITS 64

#endif
20 changes: 13 additions & 7 deletions tcg/sparc64/tcg-target.c.inc
Expand Up @@ -1017,6 +1017,9 @@ bool tcg_target_has_memory_bswap(MemOp memop)
return true;
}

/* We expect to use a 13-bit negative offset from ENV. */
#define MIN_TLB_MASK_TABLE_OFS -(1 << 12)

/*
* For softmmu, perform the TLB load and compare.
* For useronly, perform any required alignment tests.
Expand All @@ -1027,6 +1030,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
TCGReg addr_reg, MemOpIdx oi,
bool is_ld)
{
TCGType addr_type = s->addr_type;
TCGLabelQemuLdst *ldst = NULL;
MemOp opc = get_memop(oi);
MemOp s_bits = opc & MO_SIZE;
Expand All @@ -1039,7 +1043,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,

#ifdef CONFIG_SOFTMMU
int mem_index = get_mmuidx(oi);
int fast_off = TLB_MASK_TABLE_OFS(mem_index);
int fast_off = tlb_mask_table_ofs(s, mem_index);
int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
int table_off = fast_off + offsetof(CPUTLBDescFast, table);
int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
Expand All @@ -1049,8 +1053,6 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
int cc;

/* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 12));
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_T2, TCG_AREG0, mask_off);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_T3, TCG_AREG0, table_off);

Expand All @@ -1062,8 +1064,12 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
/* Add the tlb_table pointer, creating the CPUTLBEntry address into R2. */
tcg_out_arith(s, TCG_REG_T1, TCG_REG_T1, TCG_REG_T3, ARITH_ADD);

/* Load the tlb comparator and the addend. */
tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_T2, TCG_REG_T1, cmp_off);
/*
* Load the tlb comparator and the addend.
* Always load the entire 64-bit comparator for simplicity.
* We will ignore the high bits via BPCC_ICC below.
*/
tcg_out_ld(s, TCG_TYPE_I64, TCG_REG_T2, TCG_REG_T1, cmp_off);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_T1, TCG_REG_T1, add_off);
h->base = TCG_REG_T1;

Expand All @@ -1084,7 +1090,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
ldst->label_ptr[0] = s->code_ptr;

/* bne,pn %[xi]cc, label0 */
cc = TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC;
cc = addr_type == TCG_TYPE_I32 ? BPCC_ICC : BPCC_XCC;
tcg_out_bpcc0(s, COND_NE, BPCC_PN | cc, 0);
#else
/*
Expand All @@ -1110,7 +1116,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
#endif

/* If the guest address must be zero-extended, do in the delay slot. */
if (TARGET_LONG_BITS == 32) {
if (addr_type == TCG_TYPE_I32) {
tcg_out_ext32u(s, TCG_REG_T2, addr_reg);
h->index = TCG_REG_T2;
} else {
Expand Down
47 changes: 1 addition & 46 deletions tcg/tcg-internal.h
Expand Up @@ -25,55 +25,10 @@
#ifndef TCG_INTERNAL_H
#define TCG_INTERNAL_H

#ifdef CONFIG_TCG_INTERPRETER
#include <ffi.h>
#endif
#include "tcg/helper-info.h"

#define TCG_HIGHWATER 1024

/*
* Describe the calling convention of a given argument type.
*/
typedef enum {
TCG_CALL_RET_NORMAL, /* by registers */
TCG_CALL_RET_BY_REF, /* for i128, by reference */
TCG_CALL_RET_BY_VEC, /* for i128, by vector register */
} TCGCallReturnKind;

typedef enum {
TCG_CALL_ARG_NORMAL, /* by registers (continuing onto stack) */
TCG_CALL_ARG_EVEN, /* like normal, but skipping odd slots */
TCG_CALL_ARG_EXTEND, /* for i32, as a sign/zero-extended i64 */
TCG_CALL_ARG_EXTEND_U, /* ... as a zero-extended i64 */
TCG_CALL_ARG_EXTEND_S, /* ... as a sign-extended i64 */
TCG_CALL_ARG_BY_REF, /* for i128, by reference, first */
TCG_CALL_ARG_BY_REF_N, /* ... by reference, subsequent */
} TCGCallArgumentKind;

typedef struct TCGCallArgumentLoc {
TCGCallArgumentKind kind : 8;
unsigned arg_slot : 8;
unsigned ref_slot : 8;
unsigned arg_idx : 4;
unsigned tmp_subindex : 2;
} TCGCallArgumentLoc;

typedef struct TCGHelperInfo {
void *func;
const char *name;
#ifdef CONFIG_TCG_INTERPRETER
ffi_cif *cif;
#endif
unsigned typemask : 32;
unsigned flags : 8;
unsigned nr_in : 8;
unsigned nr_out : 8;
TCGCallReturnKind out_kind : 8;

/* Maximum physical arguments are constrained by TCG_TYPE_I128. */
TCGCallArgumentLoc in[MAX_CALL_IARGS * (128 / TCG_TARGET_REG_BITS)];
} TCGHelperInfo;

extern TCGContext tcg_init_ctx;
extern TCGContext **tcg_ctxs;
extern unsigned int tcg_cur_ctxs;
Expand Down
4 changes: 2 additions & 2 deletions tcg/tcg-op-gvec.c
Expand Up @@ -20,8 +20,8 @@
#include "qemu/osdep.h"
#include "tcg/tcg.h"
#include "tcg/tcg-temp-internal.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "tcg/tcg-op-common.h"
#include "tcg/tcg-op-gvec-common.h"
#include "tcg/tcg-gvec-desc.h"

#define MAX_UNROLL 4
Expand Down
26 changes: 19 additions & 7 deletions tcg/tcg-op-ldst.c
Expand Up @@ -23,20 +23,32 @@
*/

#include "qemu/osdep.h"
#include "exec/exec-all.h"
#include "tcg/tcg.h"
#include "tcg/tcg-temp-internal.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-common.h"
#include "tcg/tcg-mo.h"
#include "exec/translation-block.h"
#include "exec/plugin-gen.h"
#include "tcg-internal.h"


static inline MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st)
static void check_max_alignment(unsigned a_bits)
{
#if defined(CONFIG_SOFTMMU)
/*
* The requested alignment cannot overlap the TLB flags.
* FIXME: Must keep the count up-to-date with "exec/cpu-all.h".
*/
tcg_debug_assert(a_bits + 6 <= tcg_ctx->page_bits);
#endif
}

static MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st)
{
/* Trigger the asserts within as early as possible. */
unsigned a_bits = get_alignment_bits(op);

check_max_alignment(a_bits);

/* Prefer MO_ALIGN+MO_XX over MO_ALIGN_XX+MO_XX */
if (a_bits == (op & MO_SIZE)) {
op = (op & ~MO_AMASK) | MO_ALIGN;
Expand Down Expand Up @@ -104,9 +116,7 @@ static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 v, TCGTemp *addr, MemOpIdx oi)

static void tcg_gen_req_mo(TCGBar type)
{
#ifdef TCG_GUEST_DEFAULT_MO
type &= TCG_GUEST_DEFAULT_MO;
#endif
type &= tcg_ctx->guest_mo;
type &= ~TCG_TARGET_DEFAULT_MO;
if (type) {
tcg_gen_mb(type | TCG_BAR_SC);
Expand Down Expand Up @@ -493,6 +503,7 @@ static void tcg_gen_qemu_ld_i128_int(TCGv_i128 val, TCGTemp *addr,
TCGv_i64 ext_addr = NULL;
TCGOpcode opc;

check_max_alignment(get_alignment_bits(memop));
tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);

/* TODO: For now, force 32-bit hosts to use the helper. */
Expand Down Expand Up @@ -601,6 +612,7 @@ static void tcg_gen_qemu_st_i128_int(TCGv_i128 val, TCGTemp *addr,
TCGv_i64 ext_addr = NULL;
TCGOpcode opc;

check_max_alignment(get_alignment_bits(memop));
tcg_gen_req_mo(TCG_MO_ST_LD | TCG_MO_ST_ST);

/* TODO: For now, force 32-bit hosts to use the helper. */
Expand Down
13 changes: 1 addition & 12 deletions tcg/tcg-op-vec.c
Expand Up @@ -20,21 +20,10 @@
#include "qemu/osdep.h"
#include "tcg/tcg.h"
#include "tcg/tcg-temp-internal.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-common.h"
#include "tcg/tcg-mo.h"
#include "tcg-internal.h"


/* Reduce the number of ifdefs below. This assumes that all uses of
TCGV_HIGH and TCGV_LOW are properly protected by a conditional that
the compiler can eliminate. */
#if TCG_TARGET_REG_BITS == 64
extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64);
extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64);
#define TCGV_LOW TCGV_LOW_link_error
#define TCGV_HIGH TCGV_HIGH_link_error
#endif

/*
* Vector optional opcode tracking.
* Except for the basic logical operations (and, or, xor), and
Expand Down
4 changes: 2 additions & 2 deletions tcg/tcg-op.c
Expand Up @@ -23,10 +23,10 @@
*/

#include "qemu/osdep.h"
#include "exec/exec-all.h"
#include "tcg/tcg.h"
#include "tcg/tcg-temp-internal.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-common.h"
#include "exec/translation-block.h"
#include "exec/plugin-gen.h"
#include "tcg-internal.h"

Expand Down
222 changes: 138 additions & 84 deletions tcg/tcg.c
Expand Up @@ -34,14 +34,9 @@
#include "qemu/cacheflush.h"
#include "qemu/cacheinfo.h"
#include "qemu/timer.h"

/* Note: the long term plan is to reduce the dependencies on the QEMU
CPU definitions. Currently they are used for qemu_ld/st
instructions */
#define NO_CPU_IO_DEFS

#include "exec/exec-all.h"
#include "tcg/tcg-op.h"
#include "exec/translation-block.h"
#include "exec/tlb-common.h"
#include "tcg/tcg-op-common.h"

#if UINTPTR_MAX == UINT32_MAX
# define ELF_CLASS ELFCLASS32
Expand Down Expand Up @@ -407,6 +402,13 @@ static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which)
return (uintptr_t)tcg_splitwx_to_rx(&s->gen_tb->jmp_target_addr[which]);
}

#if defined(CONFIG_SOFTMMU) && !defined(CONFIG_TCG_INTERPRETER)
static int tlb_mask_table_ofs(TCGContext *s, int which)
{
return s->tlb_fast_offset + which * sizeof(CPUTLBDescFast);
}
#endif

/* Signal overflow, starting over with fewer guest insns. */
static G_NORETURN
void tcg_raise_tb_overflow(TCGContext *s)
Expand Down Expand Up @@ -840,13 +842,6 @@ void tcg_pool_reset(TCGContext *s)
s->pool_current = NULL;
}

#include "exec/helper-proto.h"

static TCGHelperInfo all_helpers[] = {
#include "exec/helper-tcg.h"
};
static GHashTable *helper_table;

/*
* Create TCGHelperInfo structures for "tcg/tcg-ldst.h" functions,
* akin to what "exec/helper-tcg.h" does with DEF_HELPER_FLAGS_N.
Expand Down Expand Up @@ -956,57 +951,45 @@ static ffi_type *typecode_to_ffi(int argmask)
g_assert_not_reached();
}

static void init_ffi_layouts(void)
static ffi_cif *init_ffi_layout(TCGHelperInfo *info)
{
/* g_direct_hash/equal for direct comparisons on uint32_t. */
GHashTable *ffi_table = g_hash_table_new(NULL, NULL);

for (int i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
TCGHelperInfo *info = &all_helpers[i];
unsigned typemask = info->typemask;
gpointer hash = (gpointer)(uintptr_t)typemask;
struct {
ffi_cif cif;
ffi_type *args[];
} *ca;
ffi_status status;
int nargs;
ffi_cif *cif;

cif = g_hash_table_lookup(ffi_table, hash);
if (cif) {
info->cif = cif;
continue;
}

/* Ignoring the return type, find the last non-zero field. */
nargs = 32 - clz32(typemask >> 3);
nargs = DIV_ROUND_UP(nargs, 3);
assert(nargs <= MAX_CALL_IARGS);

ca = g_malloc0(sizeof(*ca) + nargs * sizeof(ffi_type *));
ca->cif.rtype = typecode_to_ffi(typemask & 7);
ca->cif.nargs = nargs;

if (nargs != 0) {
ca->cif.arg_types = ca->args;
for (int j = 0; j < nargs; ++j) {
int typecode = extract32(typemask, (j + 1) * 3, 3);
ca->args[j] = typecode_to_ffi(typecode);
}
unsigned typemask = info->typemask;
struct {
ffi_cif cif;
ffi_type *args[];
} *ca;
ffi_status status;
int nargs;

/* Ignoring the return type, find the last non-zero field. */
nargs = 32 - clz32(typemask >> 3);
nargs = DIV_ROUND_UP(nargs, 3);
assert(nargs <= MAX_CALL_IARGS);

ca = g_malloc0(sizeof(*ca) + nargs * sizeof(ffi_type *));
ca->cif.rtype = typecode_to_ffi(typemask & 7);
ca->cif.nargs = nargs;

if (nargs != 0) {
ca->cif.arg_types = ca->args;
for (int j = 0; j < nargs; ++j) {
int typecode = extract32(typemask, (j + 1) * 3, 3);
ca->args[j] = typecode_to_ffi(typecode);
}

status = ffi_prep_cif(&ca->cif, FFI_DEFAULT_ABI, nargs,
ca->cif.rtype, ca->cif.arg_types);
assert(status == FFI_OK);

cif = &ca->cif;
info->cif = cif;
g_hash_table_insert(ffi_table, hash, (gpointer)cif);
}

g_hash_table_destroy(ffi_table);
status = ffi_prep_cif(&ca->cif, FFI_DEFAULT_ABI, nargs,
ca->cif.rtype, ca->cif.arg_types);
assert(status == FFI_OK);

return &ca->cif;
}

#define HELPER_INFO_INIT(I) (&(I)->cif)
#define HELPER_INFO_INIT_VAL(I) init_ffi_layout(I)
#else
#define HELPER_INFO_INIT(I) (&(I)->init)
#define HELPER_INFO_INIT_VAL(I) 1
#endif /* CONFIG_TCG_INTERPRETER */

static inline bool arg_slot_reg_p(unsigned arg_slot)
Expand Down Expand Up @@ -1319,27 +1302,13 @@ static void tcg_context_init(unsigned max_cpus)
args_ct += n;
}

/* Register helpers. */
/* Use g_direct_hash/equal for direct pointer comparisons on func. */
helper_table = g_hash_table_new(NULL, NULL);

for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
init_call_layout(&all_helpers[i]);
g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
(gpointer)&all_helpers[i]);
}

init_call_layout(&info_helper_ld32_mmu);
init_call_layout(&info_helper_ld64_mmu);
init_call_layout(&info_helper_ld128_mmu);
init_call_layout(&info_helper_st32_mmu);
init_call_layout(&info_helper_st64_mmu);
init_call_layout(&info_helper_st128_mmu);

#ifdef CONFIG_TCG_INTERPRETER
init_ffi_layouts();
#endif

tcg_target_init(s);
process_op_defs(s);

Expand Down Expand Up @@ -1521,6 +1490,13 @@ void tcg_func_start(TCGContext *s)

tcg_debug_assert(s->addr_type == TCG_TYPE_I32 ||
s->addr_type == TCG_TYPE_I64);

#if defined(CONFIG_SOFTMMU) && !defined(CONFIG_TCG_INTERPRETER)
tcg_debug_assert(s->tlb_fast_offset < 0);
tcg_debug_assert(s->tlb_fast_offset >= MIN_TLB_MASK_TABLE_OFS);
#endif

tcg_debug_assert(s->insn_start_words > 0);
}

static TCGTemp *tcg_temp_alloc(TCGContext *s)
Expand Down Expand Up @@ -1820,6 +1796,25 @@ TCGv_vec tcg_constant_vec_matching(TCGv_vec match, unsigned vece, int64_t val)
return tcg_constant_vec(t->base_type, vece, val);
}

#ifdef CONFIG_DEBUG_TCG
size_t temp_idx(TCGTemp *ts)
{
ptrdiff_t n = ts - tcg_ctx->temps;
assert(n >= 0 && n < tcg_ctx->nb_temps);
return n;
}

TCGTemp *tcgv_i32_temp(TCGv_i32 v)
{
uintptr_t o = (uintptr_t)v - offsetof(TCGContext, temps);

assert(o < sizeof(TCGTemp) * tcg_ctx->nb_temps);
assert(o % sizeof(TCGTemp) == 0);

return (void *)tcg_ctx + (uintptr_t)v;
}
#endif /* CONFIG_DEBUG_TCG */

/* Return true if OP may appear in the opcode stream.
Test the runtime variable that controls each opcode. */
bool tcg_op_supported(TCGOpcode op)
Expand Down Expand Up @@ -2128,15 +2123,18 @@ bool tcg_op_supported(TCGOpcode op)

static TCGOp *tcg_op_alloc(TCGOpcode opc, unsigned nargs);

void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
static void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args)
{
const TCGHelperInfo *info;
TCGv_i64 extend_free[MAX_CALL_IARGS];
int n_extend = 0;
TCGOp *op;
int i, n, pi = 0, total_args;

info = g_hash_table_lookup(helper_table, (gpointer)func);
if (unlikely(g_once_init_enter(HELPER_INFO_INIT(info)))) {
init_call_layout(info);
g_once_init_leave(HELPER_INFO_INIT(info), HELPER_INFO_INIT_VAL(info));
}

total_args = info->nr_out + info->nr_in + 2;
op = tcg_op_alloc(INDEX_op_call, total_args);

Expand Down Expand Up @@ -2203,7 +2201,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
g_assert_not_reached();
}
}
op->args[pi++] = (uintptr_t)func;
op->args[pi++] = (uintptr_t)info->func;
op->args[pi++] = (uintptr_t)info;
tcg_debug_assert(pi == total_args);

Expand All @@ -2215,6 +2213,58 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
}
}

void tcg_gen_call0(TCGHelperInfo *info, TCGTemp *ret)
{
tcg_gen_callN(info, ret, NULL);
}

void tcg_gen_call1(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1)
{
tcg_gen_callN(info, ret, &t1);
}

void tcg_gen_call2(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1, TCGTemp *t2)
{
TCGTemp *args[2] = { t1, t2 };
tcg_gen_callN(info, ret, args);
}

void tcg_gen_call3(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
TCGTemp *t2, TCGTemp *t3)
{
TCGTemp *args[3] = { t1, t2, t3 };
tcg_gen_callN(info, ret, args);
}

void tcg_gen_call4(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
TCGTemp *t2, TCGTemp *t3, TCGTemp *t4)
{
TCGTemp *args[4] = { t1, t2, t3, t4 };
tcg_gen_callN(info, ret, args);
}

void tcg_gen_call5(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
TCGTemp *t2, TCGTemp *t3, TCGTemp *t4, TCGTemp *t5)
{
TCGTemp *args[5] = { t1, t2, t3, t4, t5 };
tcg_gen_callN(info, ret, args);
}

void tcg_gen_call6(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1, TCGTemp *t2,
TCGTemp *t3, TCGTemp *t4, TCGTemp *t5, TCGTemp *t6)
{
TCGTemp *args[6] = { t1, t2, t3, t4, t5, t6 };
tcg_gen_callN(info, ret, args);
}

void tcg_gen_call7(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
TCGTemp *t2, TCGTemp *t3, TCGTemp *t4,
TCGTemp *t5, TCGTemp *t6, TCGTemp *t7)
{
TCGTemp *args[7] = { t1, t2, t3, t4, t5, t6, t7 };
tcg_gen_callN(info, ret, args);
}

static void tcg_reg_alloc_start(TCGContext *s)
{
int i, n;
Expand Down Expand Up @@ -2391,7 +2441,7 @@ static void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
nb_oargs = 0;
col += ne_fprintf(f, "\n ----");

for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
for (i = 0, k = s->insn_start_words; i < k; ++i) {
col += ne_fprintf(f, " %016" PRIx64,
tcg_get_insn_start_param(op, i));
}
Expand Down Expand Up @@ -5970,7 +6020,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
#ifdef CONFIG_PROFILER
TCGProfile *prof = &s->prof;
#endif
int i, num_insns;
int i, start_words, num_insns;
TCGOp *op;

#ifdef CONFIG_PROFILER
Expand Down Expand Up @@ -6093,6 +6143,10 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
s->pool_labels = NULL;
#endif

start_words = s->insn_start_words;
s->gen_insn_data =
tcg_malloc(sizeof(uint64_t) * s->gen_tb->icount * start_words);

num_insns = -1;
QTAILQ_FOREACH(op, &s->ops, link) {
TCGOpcode opc = op->opc;
Expand All @@ -6118,8 +6172,8 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
assert(s->gen_insn_end_off[num_insns] == off);
}
num_insns++;
for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
s->gen_insn_data[num_insns][i] =
for (i = 0; i < start_words; ++i) {
s->gen_insn_data[num_insns * start_words + i] =
tcg_get_insn_start_param(op, i);
}
break;
Expand Down Expand Up @@ -6165,7 +6219,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
return -2;
}
}
tcg_debug_assert(num_insns >= 0);
tcg_debug_assert(num_insns + 1 == s->gen_tb->icount);
s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);

/* Generate TB finalization at the end of block */
Expand Down
3 changes: 1 addition & 2 deletions tcg/tci.c
Expand Up @@ -18,8 +18,7 @@
*/

#include "qemu/osdep.h"
#include "exec/cpu_ldst.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg.h"
#include "tcg/tcg-ldst.h"
#include <ffi.h>

Expand Down
18 changes: 18 additions & 0 deletions tcg/tci/tcg-target-reg-bits.h
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: MIT */
/*
* Define target-specific register size
* Copyright (c) 2009, 2011 Stefan Weil
*/

#ifndef TCG_TARGET_REG_BITS_H
#define TCG_TARGET_REG_BITS_H

#if UINTPTR_MAX == UINT32_MAX
# define TCG_TARGET_REG_BITS 32
#elif UINTPTR_MAX == UINT64_MAX
# define TCG_TARGET_REG_BITS 64
#else
# error Unknown pointer size for tci target
#endif

#endif
8 changes: 0 additions & 8 deletions tcg/tci/tcg-target.h
Expand Up @@ -44,14 +44,6 @@
#define TCG_TARGET_INSN_UNIT_SIZE 4
#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)

#if UINTPTR_MAX == UINT32_MAX
# define TCG_TARGET_REG_BITS 32
#elif UINTPTR_MAX == UINT64_MAX
# define TCG_TARGET_REG_BITS 64
#else
# error Unknown pointer size for tci target
#endif

/* Optional instructions. */

#define TCG_TARGET_HAS_bswap16_i32 1
Expand Down