diff options
author | David 'Digit' Turner <digit@android.com> | 2011-06-01 17:23:23 +0200 |
---|---|---|
committer | David 'Digit' Turner <digit@android.com> | 2011-06-01 17:24:00 +0200 |
commit | 2e5feede9978fadb969c8cfa82b761a8446bf012 (patch) | |
tree | e9dbb51e71a14aa9118f8e9c980d4722abb04fd8 /tcg/tcg.c | |
parent | a45e3e024836d7fbfb34d0b62f962a706d1b05fd (diff) | |
parent | 406a59bd0a2e7a38cd840a5c08602e3a36bd2df8 (diff) | |
download | external_qemu-2e5feede9978fadb969c8cfa82b761a8446bf012.zip external_qemu-2e5feede9978fadb969c8cfa82b761a8446bf012.tar.gz external_qemu-2e5feede9978fadb969c8cfa82b761a8446bf012.tar.bz2 |
upstream integration
This patch is a merge of a series of 42 upstream integration patches
into the emulator's master branch.
The individual patches come from the 'upstream-integrate'
branch that was uploaded separately on kernel.org.
The reference upstream sources used for this integration come
from http://meego.gitorious.org/qemu-maemo/qemu using the following
hash:
7243fbd089cce3c06ca24ed173a251f32644863c
In a nutshell, the goal is to make our source tree closer to upstream
in order to use various improvement there. Unfortunately, we're not to
the point where we can use the upstream ARMv7-A / NEON translator,
though we're getting close.
Major changes are:
- integrate upstream TCG and softfloat
- target-arm: Move most Android-specific helper functions to helper-android.c
and translate-android.h. This is in preparation of a _major_ integration
of the upstream ARM translator.
- moving various functions to different files (e.g. cpus.c,
qemu-os-posix.c, qemu-os-win32.c, arch_init.c, etc)
- qemu-char-android.c is now gone. We're using qemu-char.c
with slight modifications embedded within CONFIG_ANDROID-guarded
ifdef blocks.
- rename "trace.h" to "android-trace.h". We still need to keep
"trace.h" and "trace_common.h" until we also update
sdk/emulator/tools/qtools/ to use the new header names.
After this, we will integrate in a future integration
the auto-generated trace.h used by upstream.
- remove the OutputChannel hack. Instead, implement a "fake Monitor"
object that can be used with any function that takes a Monitor as
input. The fake Monitor is used to collect output into a dynamic
buffer (e.g. during snapshot save/load).
- convert to upstream QEMUTimer API changes.
- implement physical memory with RAMBlock lists (instead of a single array).
Short log of individual changes:
406a59b trace.h: rename to trace-android.h
288208c target-arm/translate.c: move Android-specific stuff out.
f1d9bf1 tcg: integrate upstream version
280afa0 ramblocks: integrate upstream implementation (sophisticated)
ae3098a vl-android.c: move arch-specific functions to arch_init.c
23ca2ae vl-android.c: move cpu functions to cpus.c
c1ac40a vl-android.c: use os-specific setup routines
e49c3f3 compatfd.c: minor integrate
4276038 cpu-exec.c: minor integrate
3b2846a qemu-char-android.c: rename to qemu-char.c
f645f7d cpu_restore_state: remove un-necessary argument.
f0753ac qjson.c: minor integrate
8354d2d vl-android.c: Move code to iohandler.c
d3d4468 translate-all.c: minor integrate
1f9ec0f qemu-config.c: minor integrate
d09775c monitor.c: minor integrate
9f64011 disas.c: minor integrate
69ed952 device_tree.c: minor integrate
e1c0948 bswap.h + others: minor integrate
6b9236d buffered_file.c: minor integrate
95a83ce savevm: Remove OutputBuffer hack.
986acc9 savevm.c: minor integrate
39373b1 arm-semi.c: minor integrate
fb955c7 README: minor integrate
8ee4e5e trace: simplify code and avoid conflicts
65d1521 acl.c: minor integrate
c98cf7b arm-dis.c: minor integrate
bfec547 fpu: upstream integrate
9bfb3d5 json-lexer.c, json-parser.c: minor integrate
6eaacfb trace.h: minor C compatibility fixes.
17410ee qemu-char.h, console.h: upstream integration
5973c77 qemu-timer.c: rename qemu_timer_new_scale()
317c9d5 qemu-timer.c: upstream integrate
47dc1f4 qerror: minor integrate
488bfd5 qemu-error: minor integrate
1646b4e posix-aio-compat.c: minor integrate
088edf8 os-posix.c + os-win32.c and dependencies
795bb19 qemu-common.h: other intergrates
45c3be0 integrate: qemu-common.h changes
Change-Id: If5771dd4b030c602b99845d7489d1f55406bf159
Diffstat (limited to 'tcg/tcg.c')
-rw-r--r-- | tcg/tcg.c | 156 |
1 files changed, 124 insertions, 32 deletions
@@ -63,15 +63,15 @@ #error GUEST_BASE not supported on this host. #endif +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, 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, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 }, +#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags }, #include "tcg-opc.h" #undef DEF -#undef DEF2 }; static TCGRegSet tcg_target_available_regs[2]; @@ -110,7 +110,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, +static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, int label_index, long addend) { TCGLabel *l; @@ -250,7 +250,10 @@ void tcg_context_init(TCGContext *s) } tcg_target_init(s); +} +void tcg_prologue_init(TCGContext *s) +{ /* init global prologue and epilogue */ s->code_buf = code_gen_prologue; s->code_ptr = s->code_buf; @@ -457,6 +460,10 @@ static inline int tcg_temp_new_internal(TCGType type, int temp_local) s->nb_temps++; } } + +#if defined(CONFIG_DEBUG_TCG) + s->temps_in_use++; +#endif return idx; } @@ -482,6 +489,13 @@ static inline void tcg_temp_free_internal(int idx) TCGTemp *ts; int k; +#if defined(CONFIG_DEBUG_TCG) + s->temps_in_use--; + if (s->temps_in_use < 0) { + fprintf(stderr, "More temporaries freed than allocated!\n"); + } +#endif + assert(idx >= s->nb_globals && idx < s->nb_temps); ts = &s->temps[idx]; assert(ts->temp_allocated != 0); @@ -535,6 +549,27 @@ TCGv_i64 tcg_const_local_i64(int64_t val) return t0; } +#if defined(CONFIG_DEBUG_TCG) +void tcg_clear_temp_count(void) +{ + TCGContext *s = &tcg_ctx; + s->temps_in_use = 0; +} + +int tcg_check_temp_count(void) +{ + TCGContext *s = &tcg_ctx; + if (s->temps_in_use) { + /* Clear the count so that we don't give another + * warning immediately next time around. + */ + s->temps_in_use = 0; + return 1; + } + return 0; +} +#endif + void tcg_register_helper(void *func, const char *name) { TCGContext *s = &tcg_ctx; @@ -560,14 +595,36 @@ void tcg_register_helper(void *func, const char *name) void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, int sizemask, TCGArg ret, int nargs, TCGArg *args) { +#ifdef TCG_TARGET_I386 int call_type; +#endif int i; int real_args; int nb_rets; TCGArg *nparam; + +#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64 + for (i = 0; i < nargs; ++i) { + int is_64bit = sizemask & (1 << (i+1)*2); + int is_signed = sizemask & (2 << (i+1)*2); + if (!is_64bit) { + TCGv_i64 temp = tcg_temp_new_i64(); + TCGv_i64 orig = MAKE_TCGV_I64(args[i]); + if (is_signed) { + tcg_gen_ext32s_i64(temp, orig); + } else { + tcg_gen_ext32u_i64(temp, orig); + } + args[i] = GET_TCGV_I64(temp); + } + } +#endif /* TCG_TARGET_EXTEND_ARGS */ + *gen_opc_ptr++ = INDEX_op_call; nparam = gen_opparam_ptr++; +#ifdef TCG_TARGET_I386 call_type = (flags & TCG_CALL_TYPE_MASK); +#endif if (ret != TCG_CALL_DUMMY_ARG) { #if TCG_TARGET_REG_BITS < 64 if (sizemask & 1) { @@ -591,7 +648,8 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, real_args = 0; for (i = 0; i < nargs; i++) { #if TCG_TARGET_REG_BITS < 64 - if (sizemask & (2 << i)) { + int is_64bit = sizemask & (1 << (i+1)*2); + if (is_64bit) { #ifdef TCG_TARGET_I386 /* REGPARM case: if the third parameter is 64 bit, it is allocated on the stack */ @@ -607,7 +665,17 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, real_args++; } #endif -#ifdef TCG_TARGET_WORDS_BIGENDIAN + /* If stack grows up, then we will be placing successive + arguments at lower addresses, which means we need to + reverse the order compared to how we would normally + treat either big or little-endian. For those arguments + that will wind up in registers, this still works for + HPPA (the only current STACK_GROWSUP target) since the + argument registers are *also* allocated in decreasing + order. If another such target is added, this logic may + have to get more complicated to differentiate between + stack arguments and register arguments. */ +#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP) *gen_opparam_ptr++ = args[i] + 1; *gen_opparam_ptr++ = args[i]; #else @@ -615,13 +683,13 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, *gen_opparam_ptr++ = args[i] + 1; #endif real_args += 2; - } else -#endif - { + continue; + } +#endif /* TCG_TARGET_REG_BITS < 64 */ + *gen_opparam_ptr++ = args[i]; real_args++; } - } *gen_opparam_ptr++ = GET_TCGV_PTR(func); *gen_opparam_ptr++ = flags; @@ -630,6 +698,16 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, /* total parameters, needed to go backward in the instruction stream */ *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3; + +#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64 + for (i = 0; i < nargs; ++i) { + int is_64bit = sizemask & (1 << (i+1)*2); + if (!is_64bit) { + TCGv_i64 temp = MAKE_TCGV_I64(args[i]); + tcg_temp_free_i64(temp); + } + } +#endif /* TCG_TARGET_EXTEND_ARGS */ } #if TCG_TARGET_REG_BITS == 32 @@ -681,6 +759,7 @@ void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, } #endif + static void tcg_reg_alloc_start(TCGContext *s) { int i; @@ -793,7 +872,8 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) const uint16_t *opc_ptr; const TCGArg *args; TCGArg arg; - int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn; + TCGOpcode c; + int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn; const TCGOpDef *def; char buf[128]; @@ -980,16 +1060,16 @@ static void sort_constraints(TCGOpDef *def, int start, int n) void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs) { - int op; + TCGOpcode op; TCGOpDef *def; const char *ct_str; int i, nb_args; for(;;) { - if (tdefs->op < 0) + if (tdefs->op == (TCGOpcode)-1) break; op = tdefs->op; - assert(op >= 0 && op < NB_OPS); + assert((unsigned)op < NB_OPS); def = &tcg_op_defs[op]; #if defined(CONFIG_DEBUG_TCG) /* Duplicate entry in op definitions? */ @@ -1056,15 +1136,27 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs) } #if defined(CONFIG_DEBUG_TCG) + i = 0; 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); + if (tcg_op_defs[op].used) { + fprintf(stderr, "Invalid op definition for %s\n", + tcg_op_defs[op].name); + i = 1; + } } else { /* Missing entry in op definitions? */ - assert(tcg_op_defs[op].used); + if (!tcg_op_defs[op].used) { + fprintf(stderr, "Missing op definition for %s\n", + tcg_op_defs[op].name); + i = 1; + } } } + if (i == 1) { + tcg_abort(); + } #endif } @@ -1116,7 +1208,8 @@ static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps) temporaries are removed. */ static void tcg_liveness_analysis(TCGContext *s) { - int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops; + int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops; + TCGOpcode op; TCGArg *args; const TCGOpDef *def; uint8_t *dead_temps; @@ -1271,7 +1364,7 @@ static void tcg_liveness_analysis(TCGContext *s) } #else /* dummy liveness analysis */ -void tcg_liveness_analysis(TCGContext *s) +static void tcg_liveness_analysis(TCGContext *s) { int nb_ops; nb_ops = gen_opc_ptr - gen_opc_buf; @@ -1532,7 +1625,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs); } if (ts->reg != reg) { - tcg_out_mov(s, reg, ts->reg); + tcg_out_mov(s, ots->type, reg, ts->reg); } } } else if (ts->val_type == TEMP_VAL_MEM) { @@ -1564,7 +1657,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, } static void tcg_reg_alloc_op(TCGContext *s, - const TCGOpDef *def, int opc, + const TCGOpDef *def, TCGOpcode opc, const TCGArg *args, unsigned int dead_iargs) { @@ -1637,7 +1730,7 @@ static void tcg_reg_alloc_op(TCGContext *s, /* allocate a new register matching the constraint and move the temporary register into it */ reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); - tcg_out_mov(s, reg, ts->reg); + tcg_out_mov(s, ts->type, reg, ts->reg); } new_args[i] = reg; const_args[i] = 0; @@ -1719,7 +1812,7 @@ static void tcg_reg_alloc_op(TCGContext *s, ts = &s->temps[args[i]]; reg = new_args[i]; if (ts->fixed_reg && ts->reg != reg) { - tcg_out_mov(s, ts->reg, reg); + tcg_out_mov(s, ts->type, ts->reg, reg); } } } @@ -1731,7 +1824,7 @@ static void tcg_reg_alloc_op(TCGContext *s, #endif static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, - int opc, const TCGArg *args, + TCGOpcode opc, const TCGArg *args, unsigned int dead_iargs) { int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params; @@ -1805,7 +1898,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, tcg_reg_free(s, reg); if (ts->val_type == TEMP_VAL_REG) { if (ts->reg != reg) { - tcg_out_mov(s, reg, ts->reg); + tcg_out_mov(s, ts->type, reg, ts->reg); } } else if (ts->val_type == TEMP_VAL_MEM) { tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); @@ -1834,7 +1927,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, reg = ts->reg; if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) { reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); - tcg_out_mov(s, reg, ts->reg); + tcg_out_mov(s, ts->type, reg, ts->reg); } func_arg = reg; tcg_regset_set_reg(allocated_regs, reg); @@ -1893,7 +1986,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, assert(s->reg_to_temp[reg] == -1); if (ts->fixed_reg) { if (ts->reg != reg) { - tcg_out_mov(s, ts->reg, reg); + tcg_out_mov(s, ts->type, ts->reg, reg); } } else { if (ts->val_type == TEMP_VAL_REG) @@ -1912,7 +2005,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, static int64_t tcg_table_op_count[NB_OPS]; -void dump_op_count(void) +static void dump_op_count(void) { int i; FILE *f; @@ -1928,7 +2021,8 @@ void dump_op_count(void) static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, long search_pc) { - int opc, op_index; + TCGOpcode opc; + int op_index; const TCGOpDef *def; unsigned int dead_iargs; const TCGArg *args; @@ -2109,8 +2203,7 @@ int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset) } #ifdef CONFIG_PROFILER -void tcg_dump_info(FILE *f, - int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) +void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf) { TCGContext *s = &tcg_ctx; int64_t tot; @@ -2154,8 +2247,7 @@ void tcg_dump_info(FILE *f, dump_op_count(); } #else -void tcg_dump_info(FILE *f, - int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) +void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf) { cpu_fprintf(f, "[TCG profiler not compiled]\n"); } |