diff options
Diffstat (limited to 'tcg/tcg.c')
-rw-r--r-- | tcg/tcg.c | 99 |
1 files changed, 65 insertions, 34 deletions
@@ -27,7 +27,7 @@ #include "config.h" -#ifndef DEBUG_TCG +#ifndef CONFIG_DEBUG_TCG /* define it to suppress various consistency checks (faster) */ #define NDEBUG #endif @@ -46,6 +46,7 @@ #include "qemu-common.h" #include "cache-utils.h" +#include "host-utils.h" /* Note: the long term plan is to reduce the dependancies on the QEMU CPU definitions. Currently they are used for qemu_ld/st @@ -57,12 +58,16 @@ #include "tcg-op.h" #include "elf.h" -static void patch_reloc(uint8_t *code_ptr, int type, +#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE) +#error GUEST_BASE not supported on this host. +#endif + +static void patch_reloc(uint8_t *code_ptr, int type, tcg_target_long value, tcg_target_long addend); static TCGOpDef tcg_op_defs[] = { #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size }, -#define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 }, +#define DEF2(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 }, #include "tcg-opc.h" #undef DEF #undef DEF2 @@ -104,7 +109,7 @@ static inline void tcg_out32(TCGContext *s, uint32_t v) /* label relocation processing */ -void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, +void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, int label_index, long addend) { TCGLabel *l; @@ -113,7 +118,7 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, l = &s->labels[label_index]; if (l->has_value) { /* FIXME: This may break relocations on RISC targets that - modify instruction fields in place. The caller may not have + modify instruction fields in place. The caller may not have written the initial value. */ patch_reloc(code_ptr, type, l->u.value, addend); } else { @@ -127,7 +132,7 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, } } -static void tcg_out_label(TCGContext *s, int label_index, +static void tcg_out_label(TCGContext *s, int label_index, tcg_target_long value) { TCGLabel *l; @@ -167,7 +172,7 @@ void *tcg_malloc_internal(TCGContext *s, int size) { TCGPool *p; int pool_size; - + if (size > TCG_POOL_CHUNK_SIZE) { /* big malloc: insert a new pool (XXX: could optimize) */ p = qemu_malloc(sizeof(TCGPool) + size); @@ -190,7 +195,7 @@ void *tcg_malloc_internal(TCGContext *s, int size) p = qemu_malloc(sizeof(TCGPool) + pool_size); p->size = pool_size; p->next = NULL; - if (s->pool_current) + if (s->pool_current) s->pool_current->next = p; else s->pool_first = p; @@ -221,7 +226,7 @@ void tcg_context_init(TCGContext *s) memset(s, 0, sizeof(*s)); s->temps = s->static_temps; s->nb_globals = 0; - + /* Count total number of arguments and allocate the corresponding space */ total_args = 0; @@ -242,14 +247,14 @@ void tcg_context_init(TCGContext *s) sorted_args += n; args_ct += n; } - + tcg_target_init(s); /* init global prologue and epilogue */ s->code_buf = code_gen_prologue; s->code_ptr = s->code_buf; tcg_target_qemu_prologue(s); - flush_icache_range((unsigned long)s->code_buf, + flush_icache_range((unsigned long)s->code_buf, (unsigned long)s->code_ptr); } @@ -707,7 +712,7 @@ static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size, if (idx < s->nb_globals) { pstrcpy(buf, buf_size, ts->name); } else { - if (ts->temp_local) + if (ts->temp_local) snprintf(buf, buf_size, "loc%d", idx - s->nb_globals); else snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals); @@ -745,7 +750,7 @@ static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val) tcg_target_ulong v; if (unlikely(!s->helpers_sorted)) { - qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), + qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), helper_cmp); s->helpers_sorted = 1; } @@ -804,7 +809,7 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) #else pc = args[0]; #endif - if (!first_insn) + if (!first_insn) fprintf(outfile, "\n"); fprintf(outfile, " ---- 0x%" PRIx64, pc); first_insn = 0; @@ -844,7 +849,7 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i])); } } - } else if (c == INDEX_op_movi_i32 + } else if (c == INDEX_op_movi_i32 #if TCG_TARGET_REG_BITS == 64 || c == INDEX_op_movi_i64 #endif @@ -855,7 +860,7 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) nb_oargs = def->nb_oargs; nb_iargs = def->nb_iargs; nb_cargs = def->nb_cargs; - fprintf(outfile, " %s %s,$", def->name, + fprintf(outfile, " %s %s,$", def->name, tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0])); val = args[1]; th = tcg_find_helper(s, val); @@ -879,7 +884,7 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) nb_iargs = def->nb_iargs; nb_cargs = def->nb_cargs; } - + k = 0; for(i = 0; i < nb_oargs; i++) { if (k != 0) @@ -893,21 +898,29 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) fprintf(outfile, "%s", tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++])); } - if (c == INDEX_op_brcond_i32 + switch (c) { + case INDEX_op_brcond_i32: #if TCG_TARGET_REG_BITS == 32 - || c == INDEX_op_brcond2_i32 + case INDEX_op_brcond2_i32: #elif TCG_TARGET_REG_BITS == 64 - || c == INDEX_op_brcond_i64 + case INDEX_op_brcond_i64: +#endif + case INDEX_op_setcond_i32: +#if TCG_TARGET_REG_BITS == 32 + case INDEX_op_setcond2_i32: +#elif TCG_TARGET_REG_BITS == 64 + case INDEX_op_setcond_i64: #endif - ) { if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) fprintf(outfile, ",%s", cond_name[args[k++]]); else fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]); i = 1; - } - else + break; + default: i = 0; + break; + } for(; i < nb_cargs; i++) { if (k != 0) fprintf(outfile, ","); @@ -977,9 +990,16 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs) op = tdefs->op; assert(op >= 0 && op < NB_OPS); def = &tcg_op_defs[op]; +#if defined(CONFIG_DEBUG_TCG) + /* Duplicate entry in op definitions? */ + assert(!def->used); + def->used = 1; +#endif nb_args = def->nb_iargs + def->nb_oargs; for(i = 0; i < nb_args; i++) { ct_str = tdefs->args_ct_str[i]; + /* Incomplete TCGTargetOpDef entry? */ + assert(ct_str != NULL); tcg_regset_clear(def->args_ct[i].u.regs); def->args_ct[i].ct = 0; if (ct_str[0] >= '0' && ct_str[0] <= '9') { @@ -1014,6 +1034,9 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs) } } + /* TCGTargetOpDef entry with too much information? */ + assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL); + /* sort the constraints (XXX: this is just an heuristic) */ sort_constraints(def, 0, def->nb_oargs); sort_constraints(def, def->nb_oargs, def->nb_iargs); @@ -1031,12 +1054,23 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs) tdefs++; } +#if defined(CONFIG_DEBUG_TCG) + for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) { + if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) { + /* Wrong entry in op definitions? */ + assert(!tcg_op_defs[op].used); + } else { + /* Missing entry in op definitions? */ + assert(tcg_op_defs[op].used); + } + } +#endif } #ifdef USE_LIVENESS_ANALYSIS /* set a nop for an operation using 'nb_args' */ -static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, +static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, TCGArg *args, int nb_args) { if (nb_args == 0) { @@ -1098,9 +1132,8 @@ static void tcg_liveness_analysis(TCGContext *s) nb_ops = gen_opc_ptr - gen_opc_buf; - /* XXX: make it really dynamic */ - s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t)); - + s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t)); + dead_temps = tcg_malloc(s->nb_temps); memset(dead_temps, 1, s->nb_temps); @@ -1129,7 +1162,7 @@ static void tcg_liveness_analysis(TCGContext *s) if (!dead_temps[arg]) goto do_not_remove_call; } - tcg_set_nop(s, gen_opc_buf + op_index, + tcg_set_nop(s, gen_opc_buf + op_index, args - 1, nb_args); } else { do_not_remove_call: @@ -1139,7 +1172,7 @@ static void tcg_liveness_analysis(TCGContext *s) arg = args[i]; dead_temps[arg] = 1; } - + if (!(call_flags & TCG_CALL_CONST)) { /* globals are live (they may be used by the call) */ memset(dead_temps, 0, s->nb_globals); @@ -1920,7 +1953,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) { - qemu_log("OP after la:\n"); + qemu_log("OP after liveness analysis:\n"); tcg_dump_ops(s, logfile); qemu_log("\n"); } @@ -2116,10 +2149,8 @@ void tcg_dump_info(FILE *f, s->restore_count); cpu_fprintf(f, " avg cycles %0.1f\n", s->restore_count ? (double)s->restore_time / s->restore_count : 0); - { - extern void dump_op_count(void); - dump_op_count(); - } + + dump_op_count(); } #else void tcg_dump_info(FILE *f, |