/* define it to use liveness analysis (better code) */
#define USE_LIVENESS_ANALYSIS
+#define USE_TCG_OPTIMIZATIONS
#include "config.h"
instructions */
#define NO_CPU_IO_DEFS
#include "cpu.h"
-#include "exec-all.h"
#include "tcg-op.h"
#include "elf.h"
#error GUEST_BASE not supported on this host.
#endif
+/* Forward declarations for functions declared in tcg-target.c and used here. */
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[] = {
+/* Forward declarations for functions declared and used in tcg-target.c. */
+static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
+ tcg_target_long arg2);
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
+static void tcg_out_movi(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg);
+static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
+ const int *const_args);
+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
+ tcg_target_long arg2);
+static int tcg_target_const_match(tcg_target_long val,
+ const TCGArgConstraint *arg_ct);
+static int tcg_target_get_call_iarg_regs_count(int flags);
+
+TCGOpDef tcg_op_defs[] = {
#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
#include "tcg-opc.h"
#undef DEF
};
+const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
static TCGRegSet tcg_target_available_regs[2];
static TCGRegSet tcg_target_call_clobber_regs;
if (size > TCG_POOL_CHUNK_SIZE) {
/* big malloc: insert a new pool (XXX: could optimize) */
- p = qemu_malloc(sizeof(TCGPool) + size);
+ p = g_malloc(sizeof(TCGPool) + size);
p->size = size;
if (s->pool_current)
s->pool_current->next = p;
if (!p->next) {
new_pool:
pool_size = TCG_POOL_CHUNK_SIZE;
- p = qemu_malloc(sizeof(TCGPool) + pool_size);
+ p = g_malloc(sizeof(TCGPool) + pool_size);
p->size = pool_size;
p->next = NULL;
if (s->pool_current)
total_args += n;
}
- args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
- sorted_args = qemu_malloc(sizeof(int) * total_args);
+ args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
+ sorted_args = g_malloc(sizeof(int) * total_args);
for(op = 0; op < NB_OPS; op++) {
def = &tcg_op_defs[op];
{
TCGTemp *ts;
+ assert(idx >= 0 && idx < s->nb_temps);
ts = &s->temps[idx];
+ assert(ts);
if (idx < s->nb_globals) {
pstrcpy(buf, buf_size, ts->name);
} else {
#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) {
+ const TCGOpDef *def = &tcg_op_defs[op];
+ if (op < INDEX_op_call
+ || op == INDEX_op_debug_insn_start
+ || (def->flags & TCG_OPF_NOT_PRESENT)) {
/* Wrong entry in op definitions? */
- if (tcg_op_defs[op].used) {
- fprintf(stderr, "Invalid op definition for %s\n",
- tcg_op_defs[op].name);
+ if (def->used) {
+ fprintf(stderr, "Invalid op definition for %s\n", def->name);
i = 1;
}
} else {
/* Missing entry in op definitions? */
- if (!tcg_op_defs[op].used) {
- fprintf(stderr, "Missing op definition for %s\n",
- tcg_op_defs[op].name);
+ if (!def->used) {
+ fprintf(stderr, "Missing op definition for %s\n", def->name);
i = 1;
}
}
{
TCGTemp *ts;
ts = &s->temps[temp];
- s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
- if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
+#ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
+ s->current_frame_offset = (s->current_frame_offset +
+ (tcg_target_long)sizeof(tcg_target_long) - 1) &
+ ~(sizeof(tcg_target_long) - 1);
+#endif
+ if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
+ s->frame_end) {
tcg_abort();
+ }
ts->mem_offset = s->current_frame_offset;
ts->mem_reg = s->frame_reg;
ts->mem_allocated = 1;
- s->current_frame_offset += sizeof(tcg_target_long);
+ s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
}
/* free register 'reg' by spilling the corresponding temporary if necessary */
}
}
-/* save globals to their cannonical location and assume they can be
+/* save globals to their canonical location and assume they can be
modified be the following code. 'allocated_regs' is used in case a
temporary registers needs to be allocated to store a constant. */
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
nb_regs = nb_params;
/* assign stack slots first */
- /* XXX: preallocate call stack */
call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
~(TCG_TARGET_STACK_ALIGN - 1);
allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
if (allocate_args) {
- tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
+ /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
+ preallocate call stack */
+ tcg_abort();
}
stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
}
tcg_out_op(s, opc, &func_arg, &const_func_arg);
-
- if (allocate_args) {
- tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
- }
/* assign output registers and emit moves if needed */
for(i = 0; i < nb_oargs; i++) {
}
#endif
+#ifdef USE_TCG_OPTIMIZATIONS
+ gen_opparam_ptr =
+ tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
+#endif
+
#ifdef CONFIG_PROFILER
s->la_time -= profile_getclock();
#endif
case INDEX_op_end:
goto the_end;
default:
+ /* Sanity check that we've not introduced any unhandled opcodes. */
+ if (def->flags & TCG_OPF_NOT_PRESENT) {
+ tcg_abort();
+ }
/* Note: in order to speed up the code, it would be much
faster to have specialized register allocator functions for
some common argument patterns */