From f41e067e986283426759befb9ad0d37e51f645e7 Mon Sep 17 00:00:00 2001 From: Klaus Treichel Date: Sat, 24 May 2008 19:40:43 +0000 Subject: [PATCH] Add support for the param area for x86_64 and enable it by default (It's part of the X86_64 SysV abi). --- ChangeLog | 18 ++++++++++ jit/jit-rules-x86-64.c | 62 ++++++++++++++++++++++++++++---- jit/jit-rules-x86-64.h | 13 +++---- jit/jit-rules-x86-64.ins | 78 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index a4c22b8..5a6b536 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2008-05-24 Klaus Treichel + + * 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 * jit/jit-alloc.c (jit_malloc_exec, jit_free_exec): on win32 use diff --git a/jit/jit-rules-x86-64.c b/jit/jit-rules-x86-64.c index 8bb5e48..a9e2a26 100644 --- a/jit/jit-rules-x86-64.c +++ b/jit/jit-rules-x86-64.c @@ -2167,6 +2167,16 @@ _jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) /* 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; @@ -2178,7 +2188,18 @@ _jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) 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) @@ -2192,6 +2213,12 @@ _jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) } } } +#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); @@ -2233,6 +2260,26 @@ _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) 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; @@ -2282,6 +2329,7 @@ _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) } } } +#endif /* !JIT_USE_PARAM_AREA */ /* Restore stackpointer and frame register */ x86_64_mov_reg_reg_size(inst, X86_64_RSP, X86_64_RBP, 8); @@ -2838,6 +2886,7 @@ _jit_fix_call_stack(jit_param_passing_t *passing) } } +#ifndef JIT_USE_PARAM_AREA /* * Setup the call stack before pushing any parameters. * This is used usually for pushing pad words for alignment. @@ -2867,6 +2916,7 @@ _jit_setup_call_stack(jit_function_t func, jit_param_passing_t *passing) } return 1; } +#endif /* !JIT_USE_PARAM_AREA */ /* * Push a parameter onto the stack. @@ -3473,15 +3523,15 @@ int _jit_create_call_setup_insns 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)) @@ -3596,11 +3646,11 @@ _jit_create_call_return_insns(jit_function_t func, jit_type_t signature, 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; diff --git a/jit/jit-rules-x86-64.h b/jit/jit-rules-x86-64.h index 6256c2c..569d429 100644 --- a/jit/jit-rules-x86-64.h +++ b/jit/jit-rules-x86-64.h @@ -100,7 +100,7 @@ extern "C" { /* * 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 @@ -112,12 +112,13 @@ extern "C" { /* * 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 }; diff --git a/jit/jit-rules-x86-64.ins b/jit/jit-rules-x86-64.ins index f9b6489..3587a6c 100644 --- a/jit/jit-rules-x86-64.ins +++ b/jit/jit-rules-x86-64.ins @@ -429,6 +429,84 @@ JIT_OP_POP_STACK: 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); -- 2.47.3