tcg: Put opcodes in a linked list

The previous setup required ops and args to be completely sequential,
and was error prone when it came to both iteration and optimization.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2014-09-19 13:49:15 -07:00
parent fe700adb3d
commit c45cb8bb89
5 changed files with 438 additions and 508 deletions

View file

@ -448,10 +448,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 +487,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 +494,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 +521,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,6 +542,22 @@ 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];
TCGLabel labels[TCG_MAX_LABELS];
};
extern TCGContext tcg_ctx;
@ -540,7 +565,7 @@ extern TCGContext tcg_ctx;
/* The number of opcodes emitted so far. */
static inline int tcg_op_buf_count(void)
{
return tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
return tcg_ctx.gen_next_op_idx;
}
/* Test for whether to terminate the TB for using too many opcodes. */
@ -718,8 +743,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
void tcg_gen_callN(TCGContext *s, void *func,
TCGArg ret, int nargs, TCGArg *args);
TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args,
TCGOpDef *tcg_op_def);
void tcg_optimize(TCGContext *s);
/* only used for debugging purposes */
void tcg_dump_ops(TCGContext *s);