Skip to content

Commit

Permalink
tcg: Define tcg_insn_unit for code pointers
Browse files Browse the repository at this point in the history
To be defined by the tcg backend based on the elemental unit of the ISA.
During the transition, allow TCG_TARGET_INSN_UNIT_SIZE to be undefined,
which allows us to default tcg_insn_unit to the current uint8_t.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
  • Loading branch information
rth7680 committed May 12, 2014
1 parent 52a1f64 commit 1813e17
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 56 deletions.
2 changes: 1 addition & 1 deletion include/exec/exec-all.h
Expand Up @@ -145,7 +145,7 @@ struct TranslationBlock {
#define CF_COUNT_MASK 0x7fff
#define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */

uint8_t *tc_ptr; /* pointer to the translated code */
void *tc_ptr; /* pointer to the translated code */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
/* first and second physical page containing code. The lower bit
Expand Down
4 changes: 2 additions & 2 deletions tcg/tcg-be-ldst.h
Expand Up @@ -31,8 +31,8 @@ typedef struct TCGLabelQemuLdst {
TCGReg datalo_reg; /* reg index for low word to be loaded or stored */
TCGReg datahi_reg; /* reg index for high word to be loaded or stored */
int mem_index; /* soft MMU memory index */
uint8_t *raddr; /* gen code addr of the next IR of qemu_ld/st IR */
uint8_t *label_ptr[2]; /* label pointers to be updated */
tcg_insn_unit *raddr; /* gen code addr of the next IR of qemu_ld/st IR */
tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */
} TCGLabelQemuLdst;

typedef struct TCGBackendData {
Expand Down
105 changes: 68 additions & 37 deletions tcg/tcg.c
Expand Up @@ -65,7 +65,7 @@
/* Forward declarations for functions declared in tcg-target.c and used here. */
static void tcg_target_init(TCGContext *s);
static void tcg_target_qemu_prologue(TCGContext *s);
static void patch_reloc(uint8_t *code_ptr, int type,
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend);

/* The CIE and FDE header definitions will be common to all hosts. */
Expand Down Expand Up @@ -117,55 +117,87 @@ const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
static TCGRegSet tcg_target_available_regs[2];
static TCGRegSet tcg_target_call_clobber_regs;

#if TCG_TARGET_INSN_UNIT_SIZE == 1
static inline void tcg_out8(TCGContext *s, uint8_t v)
{
*s->code_ptr++ = v;
}

static inline void tcg_patch8(uint8_t *p, uint8_t v)
static inline void tcg_patch8(tcg_insn_unit *p, uint8_t v)
{
memcpy(p, &v, sizeof(v));
*p = v;
}
#endif

#if TCG_TARGET_INSN_UNIT_SIZE <= 2
static inline void tcg_out16(TCGContext *s, uint16_t v)
{
uint8_t *p = s->code_ptr;
memcpy(p, &v, sizeof(v));
s->code_ptr = p + 2;
if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
*s->code_ptr++ = v;
} else {
tcg_insn_unit *p = s->code_ptr;
memcpy(p, &v, sizeof(v));
s->code_ptr = p + (2 / TCG_TARGET_INSN_UNIT_SIZE);
}
}

static inline void tcg_patch16(uint8_t *p, uint16_t v)
static inline void tcg_patch16(tcg_insn_unit *p, uint16_t v)
{
memcpy(p, &v, sizeof(v));
if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
*p = v;
} else {
memcpy(p, &v, sizeof(v));
}
}
#endif

#if TCG_TARGET_INSN_UNIT_SIZE <= 4
static inline void tcg_out32(TCGContext *s, uint32_t v)
{
uint8_t *p = s->code_ptr;
memcpy(p, &v, sizeof(v));
s->code_ptr = p + 4;
if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
*s->code_ptr++ = v;
} else {
tcg_insn_unit *p = s->code_ptr;
memcpy(p, &v, sizeof(v));
s->code_ptr = p + (4 / TCG_TARGET_INSN_UNIT_SIZE);
}
}

static inline void tcg_patch32(uint8_t *p, uint32_t v)
static inline void tcg_patch32(tcg_insn_unit *p, uint32_t v)
{
memcpy(p, &v, sizeof(v));
if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
*p = v;
} else {
memcpy(p, &v, sizeof(v));
}
}
#endif

#if TCG_TARGET_INSN_UNIT_SIZE <= 8
static inline void tcg_out64(TCGContext *s, uint64_t v)
{
uint8_t *p = s->code_ptr;
memcpy(p, &v, sizeof(v));
s->code_ptr = p + 8;
if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
*s->code_ptr++ = v;
} else {
tcg_insn_unit *p = s->code_ptr;
memcpy(p, &v, sizeof(v));
s->code_ptr = p + (8 / TCG_TARGET_INSN_UNIT_SIZE);
}
}

static inline void tcg_patch64(uint8_t *p, uint64_t v)
static inline void tcg_patch64(tcg_insn_unit *p, uint64_t v)
{
memcpy(p, &v, sizeof(v));
if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
*p = v;
} else {
memcpy(p, &v, sizeof(v));
}
}
#endif

/* label relocation processing */

static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
static void tcg_out_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
int label_index, intptr_t addend)
{
TCGLabel *l;
Expand All @@ -188,23 +220,20 @@ static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
}
}

static void tcg_out_label(TCGContext *s, int label_index, void *ptr)
static void tcg_out_label(TCGContext *s, int label_index, tcg_insn_unit *ptr)
{
TCGLabel *l;
TCGRelocation *r;
TCGLabel *l = &s->labels[label_index];
intptr_t value = (intptr_t)ptr;
TCGRelocation *r;

l = &s->labels[label_index];
if (l->has_value) {
tcg_abort();
}
r = l->u.first_reloc;
while (r != NULL) {
assert(!l->has_value);

for (r = l->u.first_reloc; r != NULL; r = r->next) {
patch_reloc(r->ptr, r->type, value, r->addend);
r = r->next;
}

l->has_value = 1;
l->u.value = value;
l->u.value_ptr = ptr;
}

int gen_new_label(void)
Expand Down Expand Up @@ -359,7 +388,7 @@ void tcg_prologue_init(TCGContext *s)

#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
size_t size = s->code_ptr - s->code_buf;
size_t size = tcg_current_code_size(s);
qemu_log("PROLOGUE: [size=%zu]\n", size);
log_disas(s->code_buf, size);
qemu_log("\n");
Expand Down Expand Up @@ -2538,7 +2567,8 @@ static void dump_op_count(void)
#endif


static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
static inline int tcg_gen_code_common(TCGContext *s,
tcg_insn_unit *gen_code_buf,
long search_pc)
{
TCGOpcode opc;
Expand Down Expand Up @@ -2653,7 +2683,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
}
args += def->nb_args;
next:
if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
if (search_pc >= 0 && search_pc < tcg_current_code_size(s)) {
return op_index;
}
op_index++;
Expand All @@ -2667,7 +2697,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
return -1;
}

int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
{
#ifdef CONFIG_PROFILER
{
Expand All @@ -2686,16 +2716,17 @@ int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
tcg_gen_code_common(s, gen_code_buf, -1);

/* flush instruction cache */
flush_icache_range((uintptr_t)gen_code_buf, (uintptr_t)s->code_ptr);
flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);

return s->code_ptr - gen_code_buf;
return tcg_current_code_size(s);
}

/* Return the index of the micro operation such as the pc after is <
offset bytes from the start of the TB. The contents of gen_code_buf must
not be changed, though writing the same values is ok.
Return -1 if not found. */
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
long offset)
{
return tcg_gen_code_common(s, gen_code_buf, offset);
}
Expand Down
39 changes: 30 additions & 9 deletions tcg/tcg.h
Expand Up @@ -146,17 +146,34 @@ typedef enum TCGOpcode {
#define tcg_regset_andnot(d, a, b) (d) = (a) & ~(b)
#define tcg_regset_not(d, a) (d) = ~(a)

#ifndef TCG_TARGET_INSN_UNIT_SIZE
#define TCG_TARGET_INSN_UNIT_SIZE 1
#endif
#if TCG_TARGET_INSN_UNIT_SIZE == 1
typedef uint8_t tcg_insn_unit;
#elif TCG_TARGET_INSN_UNIT_SIZE == 2
typedef uint16_t tcg_insn_unit;
#elif TCG_TARGET_INSN_UNIT_SIZE == 4
typedef uint32_t tcg_insn_unit;
#elif TCG_TARGET_INSN_UNIT_SIZE == 8
typedef uint64_t tcg_insn_unit;
#else
/* The port better have done this. */
#endif


typedef struct TCGRelocation {
struct TCGRelocation *next;
int type;
uint8_t *ptr;
tcg_insn_unit *ptr;
intptr_t addend;
} TCGRelocation;

typedef struct TCGLabel {
int has_value;
union {
uintptr_t value;
tcg_insn_unit *value_ptr;
TCGRelocation *first_reloc;
} u;
} TCGLabel;
Expand Down Expand Up @@ -464,7 +481,7 @@ struct TCGContext {
int nb_temps;

/* goto_tb support */
uint8_t *code_buf;
tcg_insn_unit *code_buf;
uintptr_t *tb_next;
uint16_t *tb_next_offset;
uint16_t *tb_jmp_offset; /* != NULL if USE_DIRECT_JUMP */
Expand All @@ -485,7 +502,7 @@ struct TCGContext {
intptr_t frame_end;
int frame_reg;

uint8_t *code_ptr;
tcg_insn_unit *code_ptr;
TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
TCGTempSet free_temps[TCG_TYPE_COUNT * 2];

Expand Down Expand Up @@ -524,14 +541,17 @@ struct TCGContext {
uint16_t gen_opc_icount[OPC_BUF_SIZE];
uint8_t gen_opc_instr_start[OPC_BUF_SIZE];

/* Code generation */
/* Code generation. Note that we specifically do not use tcg_insn_unit
here, because there's too much arithmetic throughout that relies
on addition and subtraction working on bytes. Rely on the GCC
extension that allows arithmetic on void*. */
int code_gen_max_blocks;
uint8_t *code_gen_prologue;
uint8_t *code_gen_buffer;
void *code_gen_prologue;
void *code_gen_buffer;
size_t code_gen_buffer_size;
/* threshold to flush the translated code buffer */
size_t code_gen_buffer_max_size;
uint8_t *code_gen_ptr;
void *code_gen_ptr;

TBContext tb_ctx;

Expand Down Expand Up @@ -566,8 +586,9 @@ void tcg_context_init(TCGContext *s);
void tcg_prologue_init(TCGContext *s);
void tcg_func_start(TCGContext *s);

int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf);
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset);
int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf);
int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
long offset);

void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size);

Expand Down
13 changes: 6 additions & 7 deletions translate-all.c
Expand Up @@ -143,7 +143,7 @@ void cpu_gen_init(void)
int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr)
{
TCGContext *s = &tcg_ctx;
uint8_t *gen_code_buf;
tcg_insn_unit *gen_code_buf;
int gen_code_size;
#ifdef CONFIG_PROFILER
int64_t ti;
Expand Down Expand Up @@ -186,8 +186,8 @@ int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr

#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
qemu_log("OUT: [size=%d]\n", *gen_code_size_ptr);
log_disas(tb->tc_ptr, *gen_code_size_ptr);
qemu_log("OUT: [size=%d]\n", gen_code_size);
log_disas(tb->tc_ptr, gen_code_size);
qemu_log("\n");
qemu_log_flush();
}
Expand Down Expand Up @@ -235,7 +235,8 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
s->tb_jmp_offset = NULL;
s->tb_next = tb->tb_next;
#endif
j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr);
j = tcg_gen_code_search_pc(s, (tcg_insn_unit *)tc_ptr,
searched_pc - tc_ptr);
if (j < 0)
return -1;
/* now find start of instruction before */
Expand Down Expand Up @@ -944,7 +945,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
{
CPUArchState *env = cpu->env_ptr;
TranslationBlock *tb;
uint8_t *tc_ptr;
tb_page_addr_t phys_pc, phys_page2;
target_ulong virt_page2;
int code_gen_size;
Expand All @@ -959,8 +959,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
/* Don't forget to invalidate previous TB info. */
tcg_ctx.tb_ctx.tb_invalidated_flag = 1;
}
tc_ptr = tcg_ctx.code_gen_ptr;
tb->tc_ptr = tc_ptr;
tb->tc_ptr = tcg_ctx.code_gen_ptr;
tb->cs_base = cs_base;
tb->flags = flags;
tb->cflags = cflags;
Expand Down

0 comments on commit 1813e17

Please sign in to comment.