diff options
Diffstat (limited to 'tcg/tcg.h')
-rw-r--r-- | tcg/tcg.h | 230 |
1 files changed, 174 insertions, 56 deletions
@@ -29,6 +29,8 @@ #include "qemu/bitops.h" #include "tcg-target.h" +#define CPU_TEMP_BUF_NLONGS 128 + /* Default target word size to pointer size. */ #ifndef TCG_TARGET_REG_BITS # if UINTPTR_MAX == UINT32_MAX @@ -167,7 +169,8 @@ typedef struct TCGRelocation { } TCGRelocation; typedef struct TCGLabel { - int has_value; + unsigned has_value : 1; + unsigned id : 31; union { uintptr_t value; tcg_insn_unit *value_ptr; @@ -183,8 +186,6 @@ typedef struct TCGPool { #define TCG_POOL_CHUNK_SIZE 32768 -#define TCG_MAX_LABELS 512 - #define TCG_MAX_TEMPS 512 /* when the size of the arguments of a called function is smaller than @@ -242,6 +243,19 @@ typedef enum TCGMemOp { MO_TE = MO_LE, #endif + /* MO_UNALN accesses are never checked for alignment. + MO_ALIGN accesses will result in a call to the CPU's + do_unaligned_access hook if the guest address is not aligned. + The default depends on whether the target CPU defines ALIGNED_ONLY. */ + MO_AMASK = 16, +#ifdef ALIGNED_ONLY + MO_ALIGN = 0, + MO_UNALN = MO_AMASK, +#else + MO_ALIGN = MO_AMASK, + MO_UNALN = 0, +#endif + /* Combinations of the above, for ease of use. */ MO_UB = MO_8, MO_UW = MO_16, @@ -418,20 +432,19 @@ static inline TCGCond tcg_high_cond(TCGCond c) } } -#define TEMP_VAL_DEAD 0 -#define TEMP_VAL_REG 1 -#define TEMP_VAL_MEM 2 -#define TEMP_VAL_CONST 3 +typedef enum TCGTempVal { + TEMP_VAL_DEAD, + TEMP_VAL_REG, + TEMP_VAL_MEM, + TEMP_VAL_CONST, +} TCGTempVal; -/* XXX: optimize memory layout */ typedef struct TCGTemp { - TCGType base_type; - TCGType type; - int val_type; - int reg; - tcg_target_long val; - int mem_reg; - intptr_t mem_offset; + unsigned int reg:8; + unsigned int mem_reg:8; + TCGTempVal val_type:8; + TCGType base_type:8; + TCGType type:8; unsigned int fixed_reg:1; unsigned int mem_coherent:1; unsigned int mem_allocated:1; @@ -439,6 +452,9 @@ typedef struct TCGTemp { basic blocks. Otherwise, it is not preserved across basic blocks. */ unsigned int temp_allocated:1; /* never used for code gen */ + + tcg_target_long val; + intptr_t mem_offset; const char *name; } TCGTemp; @@ -448,10 +464,28 @@ typedef struct TCGTempSet { unsigned long l[BITS_TO_LONGS(TCG_MAX_TEMPS)]; } TCGTempSet; +typedef struct TCGOp { + TCGOpcode opc : 8; + + /* The number of out and in parameter for a call. */ + unsigned callo : 2; + unsigned calli : 6; + + /* Index of the arguments for this op, or -1 for zero-operand ops. */ + signed args : 16; + + /* Index of the prex/next op, or -1 for the end of the list. */ + signed prev : 16; + signed next : 16; +} TCGOp; + +QEMU_BUILD_BUG_ON(NB_OPS > 0xff); +QEMU_BUILD_BUG_ON(OPC_BUF_SIZE >= 0x7fff); +QEMU_BUILD_BUG_ON(OPPARAM_BUF_SIZE >= 0x7fff); + struct TCGContext { uint8_t *pool_cur, *pool_end; TCGPool *pool_first, *pool_current, *pool_first_large; - TCGLabel *labels; int nb_labels; int nb_globals; int nb_temps; @@ -469,9 +503,6 @@ struct TCGContext { corresponding output argument needs to be sync to memory. */ - /* tells in which temporary a given register is. It does not take - into account fixed registers */ - int reg_to_temp[TCG_TARGET_NB_REGS]; TCGRegSet reserved_regs; intptr_t current_frame_offset; intptr_t frame_start; @@ -479,8 +510,6 @@ struct TCGContext { int frame_reg; tcg_insn_unit *code_ptr; - TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */ - TCGTempSet free_temps[TCG_TYPE_COUNT * 2]; GHashTable *helpers; @@ -508,14 +537,10 @@ struct TCGContext { int goto_tb_issue_mask; #endif - uint16_t gen_opc_buf[OPC_BUF_SIZE]; - TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE]; - - uint16_t *gen_opc_ptr; - TCGArg *gen_opparam_ptr; - target_ulong gen_opc_pc[OPC_BUF_SIZE]; - uint16_t gen_opc_icount[OPC_BUF_SIZE]; - uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; + int gen_first_op_idx; + int gen_last_op_idx; + int gen_next_op_idx; + int gen_next_parm_idx; /* Code generation. Note that we specifically do not use tcg_insn_unit here, because there's too much arithmetic throughout that relies @@ -533,10 +558,36 @@ struct TCGContext { /* The TCGBackendData structure is private to tcg-target.c. */ struct TCGBackendData *be; + + TCGTempSet free_temps[TCG_TYPE_COUNT * 2]; + TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */ + + /* tells in which temporary a given register is. It does not take + into account fixed registers */ + int reg_to_temp[TCG_TARGET_NB_REGS]; + + TCGOp gen_op_buf[OPC_BUF_SIZE]; + TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE]; + + target_ulong gen_opc_pc[OPC_BUF_SIZE]; + uint16_t gen_opc_icount[OPC_BUF_SIZE]; + uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; }; extern TCGContext tcg_ctx; +/* The number of opcodes emitted so far. */ +static inline int tcg_op_buf_count(void) +{ + return tcg_ctx.gen_next_op_idx; +} + +/* Test for whether to terminate the TB for using too many opcodes. */ +static inline bool tcg_op_buf_full(void) +{ + return tcg_op_buf_count() >= OPC_MAX_SIZE; +} + /* pool based memory allocation */ void *tcg_malloc_internal(TCGContext *s, int size); @@ -610,6 +661,7 @@ int tcg_check_temp_count(void); #endif void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf); +void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf); #define TCG_CT_ALIAS 0x80 #define TCG_CT_IALIAS 0x40 @@ -705,11 +757,8 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs); void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret, int nargs, TCGArg *args); -void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, - int c, int right, int arith); - -TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args, - TCGOpDef *tcg_op_def); +void tcg_op_remove(TCGContext *s, TCGOp *op); +void tcg_optimize(TCGContext *s); /* only used for debugging purposes */ void tcg_dump_ops(TCGContext *s); @@ -720,6 +769,33 @@ TCGv_i64 tcg_const_i64(int64_t val); TCGv_i32 tcg_const_local_i32(int32_t val); TCGv_i64 tcg_const_local_i64(int64_t val); +TCGLabel *gen_new_label(void); + +/** + * label_arg + * @l: label + * + * Encode a label for storage in the TCG opcode stream. + */ + +static inline TCGArg label_arg(TCGLabel *l) +{ + return (uintptr_t)l; +} + +/** + * arg_label + * @i: value + * + * The opposite of label_arg. Retrieve a label from the + * encoding of the TCG opcode stream. + */ + +static inline TCGLabel *arg_label(TCGArg i) +{ + return (TCGLabel *)(uintptr_t)i; +} + /** * tcg_ptr_byte_diff * @a, @b: addresses to be differenced @@ -765,6 +841,44 @@ static inline size_t tcg_current_code_size(TCGContext *s) return tcg_ptr_byte_diff(s->code_ptr, s->code_buf); } +/* Combine the TCGMemOp and mmu_idx parameters into a single value. */ +typedef uint32_t TCGMemOpIdx; + +/** + * make_memop_idx + * @op: memory operation + * @idx: mmu index + * + * Encode these values into a single parameter. + */ +static inline TCGMemOpIdx make_memop_idx(TCGMemOp op, unsigned idx) +{ + tcg_debug_assert(idx <= 15); + return (op << 4) | idx; +} + +/** + * get_memop + * @oi: combined op/idx parameter + * + * Extract the memory operation from the combined value. + */ +static inline TCGMemOp get_memop(TCGMemOpIdx oi) +{ + return oi >> 4; +} + +/** + * get_mmuidx + * @oi: combined op/idx parameter + * + * Extract the mmu index from the combined value. + */ +static inline unsigned get_mmuidx(TCGMemOpIdx oi) +{ + return oi & 15; +} + /** * tcg_qemu_tb_exec: * @env: CPUArchState * for the CPU @@ -800,8 +914,10 @@ static inline size_t tcg_current_code_size(TCGContext *s) * state is correctly synchronised and ready for execution of the next * TB (and in particular the guest PC is the address to execute next). * Otherwise, we gave up on execution of this TB before it started, and - * the caller must fix up the CPU state by calling cpu_pc_from_tb() - * with the next-TB pointer we return. + * the caller must fix up the CPU state by calling the CPU's + * synchronize_from_tb() method with the next-TB pointer we return (falling + * back to calling the CPU's set_pc method with tb->pb if no + * synchronize_from_tb() method exists). * * Note that TCG targets may use a different definition of tcg_qemu_tb_exec * to this default (which just calls the prologue.code emitted by @@ -813,7 +929,9 @@ static inline size_t tcg_current_code_size(TCGContext *s) #define TB_EXIT_ICOUNT_EXPIRED 2 #define TB_EXIT_REQUESTED 3 -#if !defined(tcg_qemu_tb_exec) +#ifdef HAVE_TCG_QEMU_TB_EXEC +uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr); +#else # define tcg_qemu_tb_exec(env, tb_ptr) \ ((uintptr_t (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, tb_ptr) #endif @@ -826,46 +944,46 @@ void tcg_register_jit(void *buf, size_t buf_size); #ifdef CONFIG_SOFTMMU /* Value zero-extended to tcg register size. */ tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); /* Value sign-extended to tcg register size. */ tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, - int mmu_idx, uintptr_t retaddr); + TCGMemOpIdx oi, uintptr_t retaddr); /* Temporary aliases until backends are converted. */ #ifdef TARGET_WORDS_BIGENDIAN |