aboutsummaryrefslogtreecommitdiffstats
path: root/tcg/tcg.c
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-06-01 17:23:23 +0200
committerDavid 'Digit' Turner <digit@android.com>2011-06-01 17:24:00 +0200
commit2e5feede9978fadb969c8cfa82b761a8446bf012 (patch)
treee9dbb51e71a14aa9118f8e9c980d4722abb04fd8 /tcg/tcg.c
parenta45e3e024836d7fbfb34d0b62f962a706d1b05fd (diff)
parent406a59bd0a2e7a38cd840a5c08602e3a36bd2df8 (diff)
downloadexternal_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.c156
1 files changed, 124 insertions, 32 deletions
diff --git a/tcg/tcg.c b/tcg/tcg.c
index a57edb1..5882f00 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -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");
}