part of the X86_64 SysV abi).
+2008-05-24 Klaus Treichel <ktreichel@web.de>
+
+ * jit/jit-rules-x86-64.c (_jit_gen_prolog, _jit_gen_epilog): Add
+ support for the param area.
+ (_jit_setup_call_stack): Define this function only if not using
+ the param area.
+ (_jit_create_call_setup_insns): Call _jit_fix_call_stack with
+ and without usage of the param area.
+ (_jit_create_call_return_insns): Declare the locals abi and
+ current_param only if built without support of the param area to
+ avoid compiler warnings.
+
+ * jit/jit-rules-x86-64.ins: Add the support of the
+ JIT_OP_SET_PARAM_* opcodes for param area support.
+
+ * jit/jit-rules-x86-64.h: Define JIT_USE_PARAM_AREA and do some
+ code cleanup and reformatting.
+
2008-05-23 Juan Jesus Garcia de Soria <juanj.g_soria@grupobbva.com>
* jit/jit-alloc.c (jit_malloc_exec, jit_free_exec): on win32 use
/* add the register save area to the initial frame size */
frame_size += (regs_to_save << 3);
+#ifdef JIT_USE_PARAM_AREA
+ /* Add the param area to the frame_size if the additional offset
+ doesnt cause the offsets in the register saves become 4 bytes */
+ if(func->builder->param_area_size > 0 &&
+ (func->builder->param_area_size <= 0x50 || regs_to_save == 0))
+ {
+ frame_size += func->builder->param_area_size;
+ }
+#endif /* JIT_USE_PARAM_AREA */
+
/* Make sure that the framesize is a multiple of 16 bytes */
/* so that the final RSP will be alligned on a 16byte boundary. */
frame_size = (frame_size + 0xf) & ~0xf;
if(regs_to_save > 0)
{
- int current_offset = 0;
+ int current_offset;
+#ifdef JIT_USE_PARAM_AREA
+ if(func->builder->param_area_size > 0 &&
+ func->builder->param_area_size <= 0x50)
+ {
+ current_offset = func->builder->param_area_size;
+ }
+ else
+#endif /* JIT_USE_PARAM_AREA */
+ {
+ current_offset = 0;
+ }
/* Save registers that we need to preserve */
for(reg = 0; reg <= 14; ++reg)
}
}
}
+#ifdef JIT_USE_PARAM_AREA
+ if(func->builder->param_area_size > 0x50 && regs_to_save > 0)
+ {
+ x86_64_sub_reg_imm_size(inst, X86_64_RSP, func->builder->param_area_size, 8);
+ }
+#endif /* JIT_USE_PARAM_AREA */
/* Copy the prolog into place and return the adjusted entry position */
reg = (int)(inst - prolog);
gen->epilog_fixup = 0;
/* Restore the used callee saved registers */
+#ifdef JIT_USE_PARAM_AREA
+ if(func->builder->param_area_size > 0)
+ {
+ current_offset = func->builder->param_area_size;
+ }
+ else
+ {
+ current_offset = 0;
+ }
+ for(reg = 0; reg <= 14; ++reg)
+ {
+ if(jit_reg_is_used(gen->touched, reg) &&
+ (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
+ {
+ x86_64_mov_reg_membase_size(inst, _jit_reg_info[reg].cpu_reg,
+ X86_64_RSP, current_offset, 8);
+ current_offset += 8;
+ }
+ }
+#else /* !JIT_USE_PARAM_AREA */
if(gen->stack_changed)
{
int frame_size = func->builder->frame_size;
}
}
}
+#endif /* !JIT_USE_PARAM_AREA */
/* Restore stackpointer and frame register */
x86_64_mov_reg_reg_size(inst, X86_64_RSP, X86_64_RBP, 8);
}
}
+#ifndef JIT_USE_PARAM_AREA
/*
* Setup the call stack before pushing any parameters.
* This is used usually for pushing pad words for alignment.
}
return 1;
}
+#endif /* !JIT_USE_PARAM_AREA */
/*
* Push a parameter onto the stack.
passing.params[current_param].value = args[current_param];
}
+ /* Let the backend do final adjustments to the passing area */
+ _jit_fix_call_stack(&passing);
+
#ifdef JIT_USE_PARAM_AREA
if(passing.stack_size > func->builder->param_area_size)
{
func->builder->param_area_size = passing.stack_size;
}
#else
- /* Let the backend do final adjustments to the passing area */
- _jit_fix_call_stack(&passing);
-
/* Flush deferred stack pops from previous calls if too many
parameters have collected up on the stack since last time */
if(!jit_insn_flush_defer_pop(func, 32 - passing.stack_size))
jit_value_t *args, unsigned int num_args,
jit_value_t return_value, int is_nested)
{
- int abi = jit_type_get_abi(signature);
jit_type_t return_type;
int ptr_return;
- int current_param;
#ifndef JIT_USE_PARAM_AREA
+ int abi = jit_type_get_abi(signature);
+ int current_param;
jit_param_passing_t passing;
_jit_param_t param[num_args];
_jit_param_t nested_param;
/*
* Preferred alignment for the start of functions.
*/
-#define JIT_FUNCTION_ALIGNMENT 32
+#define JIT_FUNCTION_ALIGNMENT 32
/*
* Define this to 1 if the platform allows reads and writes on
/*
* Parameter passing rules.
*/
+#define JIT_INITIAL_STACK_OFFSET (2 * sizeof(void *))
+#define JIT_INITIAL_FRAME_SIZE 0
+
/*
-#define JIT_CDECL_WORD_REG_PARAMS {5, 4, 2, 1, 6, 7, -1}
-#define JIT_MAX_WORD_REG_PARAMS 6
-*/
-#define JIT_INITIAL_STACK_OFFSET (2 * sizeof(void *))
-#define JIT_INITIAL_FRAME_SIZE 0
+ * We are using the param area on x86_64
+ */
+#define JIT_USE_PARAM_AREA
#ifdef __cplusplus
};
gen->stack_changed = 1;
}
+/*
+ * Parameter passing via parameter area
+ */
+
+JIT_OP_SET_PARAM_INT: note
+ [imm, imm] -> {
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2, $1, 4);
+ }
+ [reg, imm] -> {
+ x86_64_mov_membase_reg_size(inst, X86_64_RSP, $2, $1, 4);
+ }
+
+JIT_OP_SET_PARAM_LONG: note
+ [imm, imm, if("$1 >= jit_min_int && $1 <= jit_max_int")] -> {
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2, $1, 8);
+ }
+ [imm, imm] -> {
+ jit_int *ptr = (jit_int *)&($1);
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2 + 4, ptr[1], 4);
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2, ptr[0], 4);
+ }
+ [reg, imm] -> {
+ x86_64_mov_membase_reg_size(inst, X86_64_RSP, $2, $1, 8);
+ }
+
+JIT_OP_SET_PARAM_FLOAT32: note
+ [imm, imm] -> {
+ jit_int *ptr = (jit_int *)($1);
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2, ptr[0], 4);
+ }
+ [xreg, imm] -> {
+ x86_64_movss_membase_reg(inst, X86_64_RSP, $2, $1);
+ }
+
+JIT_OP_SET_PARAM_FLOAT64: note
+ [imm, imm] -> {
+ jit_int *ptr = (jit_int *)($1);
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2 + 4, ptr[1], 4);
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2, ptr[0], 4);
+ }
+ [xreg, imm] -> {
+ x86_64_movsd_membase_reg(inst, X86_64_RSP, $2, $1);
+ }
+
+JIT_OP_SET_PARAM_NFLOAT: note
+ [imm, imm] -> {
+ jit_int *ptr = (jit_int *)($1);
+ if(sizeof(jit_nfloat) != sizeof(jit_float64))
+ {
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2 + 8, ptr[2], 4);
+ }
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2 + 4, ptr[1], 4);
+ x86_64_mov_membase_imm_size(inst, X86_64_RSP, $2, ptr[0], 4);
+ }
+ [freg, imm] -> {
+ if(sizeof(jit_nfloat) != sizeof(jit_float64))
+ {
+ x86_64_fstp_membase_size(inst, X86_64_RSP, $2, 10);
+ }
+ else
+ {
+ x86_64_fstp_membase_size(inst, X86_64_RSP, $2, 8);
+ }
+ }
+
+JIT_OP_SET_PARAM_STRUCT: note
+ [reg, imm, clobber(creg), clobber(xreg)] -> {
+ /* Handle arbitrary-sized structures */
+ jit_nint offset = jit_value_get_nint_constant(insn->dest);
+ /* TODO: Maybe we should check for sizes > 2GB? */
+ inst = memory_copy(gen, inst, X86_64_RSP, offset, $1, 0, $2);
+ }
+
+
+/*
+ * Opcodes to handle return values
+ */
+
JIT_OP_FLUSH_SMALL_STRUCT:
[] -> {
inst = flush_return_struct(inst, insn->value1);