From 8fa0990bf15f0e834e2a8041cc564056c9d3e895 Mon Sep 17 00:00:00 2001 From: Martin Stjernholm <mast@lysator.liu.se> Date: Sat, 22 Mar 2003 14:39:37 +0100 Subject: [PATCH] Some cleanup and improved register allocation. Inlined a couple more opcodes. Rev: src/code/ia32.c:1.31 Rev: src/code/ia32.h:1.20 --- src/code/ia32.c | 701 +++++++++++++++++++++++++++++------------------- src/code/ia32.h | 62 +---- 2 files changed, 440 insertions(+), 323 deletions(-) diff --git a/src/code/ia32.c b/src/code/ia32.c index 396757d043..a5eebc2fca 100644 --- a/src/code/ia32.c +++ b/src/code/ia32.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: ia32.c,v 1.30 2003/03/21 14:36:01 mast Exp $ +|| $Id: ia32.c,v 1.31 2003/03/22 13:39:37 mast Exp $ */ /* @@ -11,48 +11,221 @@ #include "operators.h" #include "constants.h" +#include "object.h" + +enum ia32_reg {REG_EAX = 0, REG_EBX = 3, REG_ECX = 1, REG_EDX = 2, REG_NONE = 4}; #define PUSH_INT(X) ins_int((INT32)(X), (void (*)(char))add_to_program) #define PUSH_ADDR(X) PUSH_INT((X)) #define NOP() add_to_program(0x90); /* for alignment */ -/* This is ugly, but since the code may be moved we cannot use - * relative addressing :( - */ -#define CALL_ABSOLUTE(X) do{ \ - add_to_program(0xb8); /* mov $xxx,%eax */ \ - PUSH_INT(X); \ - add_to_program(0xff); /* jsr *(%eax) */ \ - add_to_program(0xd0); \ -}while(0) - -#define ADDB_EAX(X) do { \ - add_to_program(0x83); \ - add_to_program(0xc0); \ - add_to_program(X); \ -}while(0) - -#define MOVEAX2(ADDR) do { \ - add_to_program(0xa3 /* mov %eax, $xxxxx */); \ - PUSH_INT( (INT32)&(ADDR) ); \ -}while(0) - -#define INC_MEM(ADDR, HOWMUCH) do { \ - int h_=(HOWMUCH); \ - if(h_ == 1) \ - { \ - add_to_program(0xff); /* incl 0xXXXXXXXX */ \ - add_to_program(0x05); \ - PUSH_INT( (INT32) (ADDR) ); \ - }else{ \ - add_to_program(0x83); /* addl $0xXX, 0xXXXXXXXX */ \ - add_to_program(0x05); \ - PUSH_INT( (INT32) (ADDR) ); \ - add_to_program(HOWMUCH); \ - } \ -}while(0) - +#define MOV_VAL32_TO_REG(VAL, REG) do { \ + add_to_program (0xb8 | (REG)); /* Move imm32 to r32. */ \ + PUSH_INT (VAL); /* Assumed to be added last. */ \ + } while (0) + +#define MOV_ABSADDR_TO_REG(ADDR, REG) do { \ + if ((REG) == REG_EAX) \ + add_to_program (0xa1); /* Move dword at address to EAX. */ \ + else { \ + add_to_program (0x8b); /* Move r/m32 to r32. */ \ + add_to_program (0x5 | ((REG) << 3)); \ + } \ + PUSH_ADDR (&(ADDR)); \ + } while (0) + +#define MOV_REG_TO_ABSADDR(REG, ADDR) do { \ + if ((REG) == REG_EAX) \ + add_to_program (0xa3); /* Move EAX to dword at address. */ \ + else { \ + add_to_program (0x89); /* Move r32 to r/m32. */ \ + add_to_program (0x5 | ((REG) << 3)); \ + } \ + PUSH_ADDR (&(ADDR)); \ + } while (0) + +#define MOV_RELADDR_TO_REG(OFFSET, REG, DSTREG) do { \ + INT32 off_ = (OFFSET); \ + add_to_program (0x8b); /* Move r/m32 to r32. */ \ + if (off_ < -128 || off_ > 127) { \ + add_to_program (0x80 | ((DSTREG) << 3) | (REG)); \ + PUSH_INT (off_); \ + } \ + else if (off_) { \ + add_to_program (0x40 | ((DSTREG) << 3) | (REG)); \ + add_to_program (off_); \ + } \ + else \ + add_to_program (((DSTREG) << 3) | (REG)); \ + } while (0) + +#define MOV_RELADDR16_TO_REG(OFFSET, REG, DSTREG) do { \ + INT32 off_ = (OFFSET); \ + add_to_program (0x0f); /* Move r/m16 to r32, sign-extension. */ \ + add_to_program (0xbf); \ + if (off_ < -128 || off_ > 127) { \ + add_to_program (0x80 | ((DSTREG) << 3) | (REG)); \ + PUSH_INT (off_); \ + } \ + else if (off_) { \ + add_to_program (0x40 | ((DSTREG) << 3) | (REG)); \ + add_to_program (off_); \ + } \ + else \ + add_to_program (((DSTREG) << 3) | (REG)); \ + } while (0) + +#define MOV_REG_TO_RELADDR(SRCREG, OFFSET, REG) do { \ + INT32 off_ = (OFFSET); \ + add_to_program (0x89); /* Move r32 to r/m32. */ \ + if (off_ < -128 || off_ > 127) { \ + add_to_program (0x80 | ((SRCREG) << 3) | (REG)); \ + PUSH_INT (off_); \ + } \ + else if (off_) { \ + add_to_program (0x40 | ((SRCREG) << 3) | (REG)); \ + add_to_program (off_); \ + } \ + else \ + add_to_program (((SRCREG) << 3) | (REG)); \ + } while (0) + +#define MOV_VAL_TO_RELADDR(VALUE, OFFSET, REG) do { \ + INT32 off_ = (OFFSET); \ + add_to_program(0xc7); /* Move imm32 to r/m32. */ \ + if (off_ < -128 || off_ > 127) { \ + add_to_program (0x80 | (REG)); \ + PUSH_INT (off_); \ + } \ + else if (off_) { \ + add_to_program(0x40 | (REG)); \ + add_to_program(off_); \ + }else \ + add_to_program(REG); \ + PUSH_INT (VALUE); \ + }while(0) + +#define MOV_VAL_TO_RELSTACK(VALUE, OFFSET) do { \ + INT32 off_ = (OFFSET); \ + add_to_program (0xc7); /* Move imm32 to r/m32. */ \ + if (off_ < -128 || off_ > 127) { \ + add_to_program (0x84); \ + add_to_program (0x24); \ + PUSH_INT (off_); \ + } \ + else if (off_) { \ + add_to_program (0x44); \ + add_to_program (0x24); \ + add_to_program (off_); \ + } \ + else { \ + add_to_program (0x04); \ + add_to_program (0x24); \ + } \ + PUSH_INT (VALUE); \ + } while (0) + +#define MOV_REG_TO_RELSTACK(REG, OFFSET) do { \ + INT32 off_ = (OFFSET); \ + add_to_program (0x89); /* Move r32 to r/m32. */ \ + if (off_ < -128 || off_ > 127) { \ + add_to_program (0x84 | ((REG) << 3)); \ + add_to_program (0x24); \ + PUSH_INT (off_); \ + } \ + else if (off_) { \ + add_to_program (0x44 | ((REG) << 3)); \ + add_to_program (0x24); \ + add_to_program (off_); \ + } \ + else { \ + add_to_program (0x04 | ((REG) << 3)); \ + add_to_program (0x24); \ + } \ + } while (0) + +#define ADD_VAL_TO_REG(VAL, REG) do { \ + INT32 val_ = (VAL); \ + if (val_ == 1) \ + add_to_program (0x40 | (REG)); /* Increment r32. */ \ + else if (val_ == -1) \ + add_to_program (0x48 | (REG)); /* Decrement r32. */ \ + else if (val_ < -128 || val_ > 127) { \ + if ((REG) == REG_EAX) \ + add_to_program (0x05); /* Add imm32 to EAX. */ \ + else { \ + add_to_program (0x81); /* Add imm32 to r/m32. */ \ + add_to_program (0xc0 | (REG)); \ + } \ + PUSH_INT (val_); \ + } \ + else if (val_) { \ + add_to_program (0x83); /* Add sign-extended imm8 to r/m32. */ \ + add_to_program (0xc0 | (REG)); \ + add_to_program (val_); \ + } \ + } while (0) + +#define ADD_VAL_TO_RELADDR(VAL, OFFSET, REG) do { \ + INT32 val_ = (VAL); \ + INT32 off_ = (OFFSET); \ + if (val_) { \ + int opcode_extra_ = 0; \ + if (val_ == 1) \ + add_to_program (0xff); /* Increment r/m32 */ \ + else if (val_ == -1) { \ + add_to_program (0xff); /* Decrement r/m32 */ \ + opcode_extra_ = 1 << 3; \ + } \ + else if (-128 <= val_ && val_ <= 127) \ + add_to_program (0x83); /* Add sign-extended imm8 to r/m32. */ \ + else \ + add_to_program (0x81); /* Add imm32 to r/m32. */ \ + if (off_ < -128 || off_ > 127) { \ + add_to_program (0x80 | opcode_extra_ | (REG)); \ + PUSH_INT (off_); \ + } \ + else if (off_) { \ + add_to_program (0x40 | opcode_extra_ | (REG)); \ + add_to_program (off_); \ + } \ + else \ + add_to_program (opcode_extra_ | (REG)); \ + if (val_ != 1 && val_ != -1) { \ + if (-128 <= val_ && val_ <= 127) \ + add_to_program (val_); \ + else \ + PUSH_INT (val_); \ + } \ + } \ + } while (0) + +#define ADD_VAL_TO_ABSADDR(VAL, ADDR) do { \ + int val_ = (VAL); \ + if (val_ == 1) { \ + add_to_program (0xff); /* Increment r/m32. */ \ + add_to_program (0x05); \ + PUSH_ADDR (&(ADDR)); \ + } \ + else if (val_ == -1) { \ + add_to_program (0xff); /* Decrement r/m32. */ \ + add_to_program (0x0d); \ + PUSH_ADDR (&(ADDR)); \ + } \ + else if (val_) { \ + if (-128 <= val_ && val_ < 127) \ + add_to_program (0x83); /* Add sign-extended imm8 to r/m32. */ \ + else \ + add_to_program (0x81); /* Add imm32 to r/m32. */ \ + add_to_program (0x05); \ + PUSH_ADDR (&(ADDR)); \ + if (-128 <= val_ && val_ <= 127) \ + add_to_program (val_); \ + else \ + PUSH_INT (val_); \ + } \ + } while (0) #define CALL_RELATIVE(X) do{ \ struct program *p_=Pike_compiler->new_program; \ @@ -68,291 +241,200 @@ static void update_arg1(INT32 value) { - add_to_program(0xc7); /* movl $xxxx, (%esp) */ - add_to_program(0x04); - add_to_program(0x24); - PUSH_INT(value); + MOV_VAL_TO_RELSTACK (value, 0); } static void update_arg2(INT32 value) { - add_to_program(0xc7); /* movl $xxxx, 4(%esp) */ - add_to_program(0x44); - add_to_program(0x24); - add_to_program(0x04); - PUSH_INT(value); + MOV_VAL_TO_RELSTACK (value, 4); } -int ia32_reg_eax=REG_IS_UNKNOWN; -int ia32_reg_ecx=REG_IS_UNKNOWN; -int ia32_reg_edx=REG_IS_UNKNOWN; -ptrdiff_t ia32_prev_stored_pc = -1; /* PROG_PC at the last point - * Pike_fp->pc was updated. */ +static enum ia32_reg first_free_reg; +static enum ia32_reg sp_reg, fp_reg, mark_sp_reg; +ptrdiff_t ia32_prev_stored_pc; /* PROG_PC at the last point Pike_fp->pc was updated. */ void ia32_flush_code_generator(void) { - ia32_reg_eax=REG_IS_UNKNOWN; - ia32_reg_ecx=REG_IS_UNKNOWN; - ia32_reg_edx=REG_IS_UNKNOWN; + first_free_reg = REG_EAX; + sp_reg = fp_reg = mark_sp_reg = REG_NONE; ia32_prev_stored_pc = -1; } -void ia32_update_pc(void) +static enum ia32_reg alloc_reg (int avoid_regs) { - INT32 tmp = PIKE_PC, disp; - - if (ia32_prev_stored_pc < 0) { - if(ia32_reg_eax != REG_IS_FP) { - MOV2EAX(Pike_interpreter.frame_pointer); - ia32_reg_eax=REG_IS_FP; - } - -#ifdef PIKE_DEBUG - if (a_flag >= 60) - fprintf (stderr, "pc %d update pc absolute\n", tmp); -#endif + enum ia32_reg reg; - /* Store the negated pointer to make the relocation displacements - * work in the right direction. */ - ia32_reg_edx = REG_IS_UNKNOWN; - add_to_program(0xba); /* mov $xxxxxxxx, %edx */ - ins_pointer(0); - add_to_relocations(PIKE_PC - 4); - upd_pointer(PIKE_PC - 4, - (INT32) (tmp + Pike_compiler->new_program->program)); - add_to_program(0xf7); /* neg %edx */ - add_to_program(0xda); - add_to_program(0x89); /* mov %edx, yy(%eax) */ - if (OFFSETOF(pike_frame, pc)) { - add_to_program(0x50); - add_to_program(OFFSETOF(pike_frame, pc)); - } - else - add_to_program(0x10); - } + do { + reg = first_free_reg; + /* If we get more things to hold than there are registers then this + * should probably be replaced with an LRU strategy. */ + first_free_reg = (first_free_reg + 1) % REG_NONE; + } while ((1 << reg) & avoid_regs); - else if ((disp = tmp - ia32_prev_stored_pc)) { - if(ia32_reg_eax != REG_IS_FP) { - MOV2EAX(Pike_interpreter.frame_pointer); - ia32_reg_eax=REG_IS_FP; - } + if (sp_reg == reg) sp_reg = REG_NONE; + else if (fp_reg == reg) fp_reg = REG_NONE; + else if (mark_sp_reg == reg) mark_sp_reg = REG_NONE; -#ifdef PIKE_DEBUG - if (a_flag >= 60) - fprintf (stderr, "pc %d update pc relative: %d\n", tmp, disp); -#endif - - if (-128 <= disp && disp <= 127) - /* Add sign-extended imm8 to r/m32. */ - add_to_program(0x83); /* addl $nn, yy(%eax) */ - else - /* Add imm32 to r/m32. */ - add_to_program(0x81); /* addl $nn, yy(%eax) */ - if (OFFSETOF(pike_frame, pc)) { - add_to_program(0x40); - add_to_program(OFFSETOF(pike_frame, pc)); - } - else - add_to_program(0x0); - if (-128 <= disp && disp <= 127) - add_to_program(disp); - else - PUSH_INT(disp); - } + return reg; +} - else { -#ifdef PIKE_DEBUG - if (a_flag >= 60) - fprintf (stderr, "pc %d update pc - already up-to-date\n", tmp); -#endif - } +#define LOAD_SP(AVOID_REGS) do { \ + if (sp_reg == REG_NONE) { \ + sp_reg = alloc_reg (AVOID_REGS); \ + MOV_ABSADDR_TO_REG (Pike_interpreter.stack_pointer, sp_reg); \ + } \ + } while (0) + +#define LOAD_FP(AVOID_REGS) do { \ + if (fp_reg == REG_NONE) { \ + fp_reg = alloc_reg (AVOID_REGS); \ + MOV_ABSADDR_TO_REG (Pike_interpreter.frame_pointer, fp_reg); \ + } \ + } while (0) + +#define LOAD_MARK_SP(AVOID_REGS) do { \ + if (mark_sp_reg == REG_NONE) { \ + mark_sp_reg = alloc_reg (AVOID_REGS); \ + MOV_ABSADDR_TO_REG (Pike_interpreter.mark_stack_pointer, mark_sp_reg); \ + } \ + } while (0) - ia32_prev_stored_pc = tmp; +static void ia32_call_c_function(void *addr) +{ + CALL_RELATIVE(addr); + first_free_reg = REG_EAX; + sp_reg = fp_reg = mark_sp_reg = REG_NONE; } static void ia32_push_constant(struct svalue *tmp) { int e; if(tmp->type <= MAX_REF_TYPE) - INC_MEM(tmp->u.refs, 1); + ADD_VAL_TO_ABSADDR (1, tmp->u.refs); - if(ia32_reg_eax != REG_IS_SP) - MOV2EAX(Pike_interpreter.stack_pointer); + LOAD_SP (0); for(e=0;e<(int)sizeof(*tmp)/4;e++) - SET_MEM_REL_EAX(e*4, ((INT32 *)tmp)[e]); - ADDB_EAX(sizeof(*tmp)); - MOVEAX2(Pike_interpreter.stack_pointer); + MOV_VAL_TO_RELADDR (((INT32 *)tmp)[e], e*4, sp_reg); - ia32_reg_eax = REG_IS_SP; + ADD_VAL_TO_REG (sizeof(*tmp), sp_reg); + MOV_REG_TO_ABSADDR (sp_reg, Pike_interpreter.stack_pointer); } -/* This expects %edx to point to the svalue we wish to push */ -static void ia32_push_svalue(void) +/* The given register holds the address of the svalue we wish to push. */ +static void ia32_push_svalue (enum ia32_reg svalue_ptr_reg) { - int e; - if(ia32_reg_eax != REG_IS_SP) - MOV2EAX(Pike_interpreter.stack_pointer); + enum ia32_reg tmp_reg = alloc_reg ((1 << svalue_ptr_reg) | (1 << sp_reg)); + + LOAD_SP ((1 << svalue_ptr_reg) | (1 << tmp_reg)); if(sizeof(struct svalue) > 8) { - for(e=4;e<(int)sizeof(struct svalue);e++) + size_t e; + for(e=4;e<sizeof(struct svalue);e += 4) { if( e == OFFSETOF(svalue,u.refs)) continue; - - add_to_program(0x8b); /* mov 0x4(%edx), %ecx */ - add_to_program(0x4a); - add_to_program(e); - - add_to_program(0x89); /* mov %ecx,4(%eax) */ - add_to_program(0x48); - add_to_program(e); + MOV_RELADDR_TO_REG (e, svalue_ptr_reg, tmp_reg); + MOV_REG_TO_RELADDR (tmp_reg, e, sp_reg); } } + MOV_RELADDR_TO_REG (OFFSETOF (svalue, u.refs), svalue_ptr_reg, tmp_reg); + MOV_REG_TO_RELADDR (tmp_reg, OFFSETOF (svalue, u.refs), sp_reg); + /* tmp_reg now holds the pointer if it's a ref type. */ - add_to_program(0x8b); /* mov 0x4(%edx), %ecx */ - add_to_program(0x4a); - add_to_program(OFFSETOF(svalue,u.refs)); + MOV_RELADDR_TO_REG (0, svalue_ptr_reg, svalue_ptr_reg); + MOV_REG_TO_RELADDR (svalue_ptr_reg, 0, sp_reg); + /* svalue_ptr_reg now holds the type and subtype. */ - add_to_program(0x8b); /* mov (%edx),%edx */ - add_to_program(0x12); - - add_to_program(0x89); /* mov %edx,(%eax) */ - add_to_program(0x10); - - add_to_program(0x89); /* mov %ecx,4(%eax) */ - add_to_program(0x48); - add_to_program(OFFSETOF(svalue,u.refs)); - - add_to_program(0x66); /* cmp $0x7,%dx */ - add_to_program(0x83); - add_to_program(0xfa); - add_to_program(0x07); + /* Compare the type which is in the lower 16 bits of svalue_ptr_reg. */ + add_to_program(0x66); /* Switch to 16 bit operand mode. */ + add_to_program(0x83); /* cmp $xx,svalue_ptr_reg */ + add_to_program(0xf8 | svalue_ptr_reg); + add_to_program(MAX_REF_TYPE); add_to_program(0x77); /* ja bork */ add_to_program(0x02); - add_to_program(0xff); /* incl (%ecx) */ - add_to_program(0x01); + add_to_program(0xff); /* incl (tmp_reg) */ + add_to_program(tmp_reg); /* bork: */ - ADDB_EAX(sizeof(struct svalue)); - MOVEAX2(Pike_interpreter.stack_pointer); - - ia32_reg_eax = REG_IS_SP; - ia32_reg_ecx = REG_IS_UNKNOWN; - ia32_reg_edx = REG_IS_UNKNOWN; + ADD_VAL_TO_REG (sizeof(struct svalue), sp_reg); + MOV_REG_TO_ABSADDR (sp_reg, Pike_interpreter.stack_pointer); } -static void ia32_get_local_addr(INT32 arg) +/* A register holding &Pike_fp->locals[arg] is returned. */ +static enum ia32_reg ia32_get_local_addr(INT32 arg) { -#if 1 - if(ia32_reg_edx == REG_IS_FP) - { - add_to_program(0x8b); /* movl $XX(%edx), %edx */ - add_to_program(0x52); - }else{ - switch(ia32_reg_eax) - { - case REG_IS_SP: /* use %edx */ - MOV2EDX(Pike_interpreter.frame_pointer); - - add_to_program(0x8b); /* movl $XX(%edx), %edx */ - add_to_program(0x52); - break; - - default: /* use %eax */ - MOV2EAX(Pike_interpreter.frame_pointer); - ia32_reg_eax=REG_IS_FP; - - case REG_IS_FP: - add_to_program(0x8b); /* movl $XX(%eax), %edx */ - add_to_program(0x50); - } - } -#else - MOV2EAX(Pike_interpreter.frame_pointer); - add_to_program(0x8b); /* movl $XX(%eax), %edx */ - add_to_program(0x50); - ia32_reg_eax = REG_IS_UNKNOWN; -#endif - add_to_program(OFFSETOF(pike_frame, locals)); - /* EDX is now fp->locals */ + enum ia32_reg result_reg = alloc_reg (1 << fp_reg); + LOAD_FP (1 << result_reg); + MOV_RELADDR_TO_REG (OFFSETOF (pike_frame, locals), fp_reg, result_reg); + /* result_reg is now fp->locals */ - add_to_program(0x81); /* add $xxxxx,%edx */ - add_to_program(0xc2); - PUSH_INT(arg * sizeof(struct svalue)); - - /* EDX is now & ( fp->locals[arg] ) */ - ia32_reg_edx=REG_IS_UNKNOWN; + ADD_VAL_TO_REG (arg * sizeof (struct svalue), result_reg); + return result_reg; } static void ia32_push_local(INT32 arg) { - ia32_get_local_addr(arg); - ia32_push_svalue(); + ia32_push_svalue (ia32_get_local_addr (arg)); } static void ia32_local_lvalue(INT32 arg) { - int e; + size_t e; struct svalue tmp[2]; - ia32_get_local_addr(arg); + enum ia32_reg addr_reg = ia32_get_local_addr(arg); MEMSET(tmp, 0, sizeof(tmp)); tmp[0].type=T_SVALUE_PTR; - tmp[0].u.lval=(struct svalue *)4711; tmp[1].type=T_VOID; - if(ia32_reg_eax != REG_IS_SP) - { - MOV2EAX(Pike_interpreter.stack_pointer); - ia32_reg_eax=REG_IS_SP; - } - for(e=0;e<(int)sizeof(tmp)/4;e++) + LOAD_SP (1 << addr_reg); + + for(e=0;e<sizeof(tmp)/4;e++) { - INT32 t2=((INT32 *)&tmp)[e]; - if(t2 == 4711) + if(((INT32 *)tmp) + e == (INT32 *) &tmp[0].u.lval) { - add_to_program(0x89); /* movl %edx, xxx(%eax) */ - add_to_program(0x50); - add_to_program(e*4); + MOV_REG_TO_RELADDR (addr_reg, e*4, sp_reg); }else{ - SET_MEM_REL_EAX(e*4,t2); + MOV_VAL_TO_RELADDR (((INT32 *)tmp)[e], e*4, sp_reg); } } - ADDB_EAX(sizeof(struct svalue)*2); - MOVEAX2(Pike_interpreter.stack_pointer); + ADD_VAL_TO_REG (sizeof(struct svalue)*2, sp_reg); + MOV_REG_TO_ABSADDR (sp_reg, Pike_interpreter.stack_pointer); } -static void ia32_mark(void) +static void ia32_push_global (INT32 arg) { - if(ia32_reg_eax != REG_IS_SP) - { - MOV2EAX(Pike_interpreter.stack_pointer); - ia32_reg_eax=REG_IS_SP; - } + enum ia32_reg tmp_reg = alloc_reg ((1 << fp_reg) | (1 << sp_reg)); + LOAD_FP ((1 << tmp_reg) | (1 << sp_reg)); -#if 0 - /* who keeps changing edx?? -Hubbe */ - if(ia32_reg_edx == REG_IS_MARK_SP) -#endif - { - MOV2EDX(Pike_interpreter.mark_stack_pointer); - ia32_reg_edx=REG_IS_MARK_SP; - } + MOV_RELADDR16_TO_REG (OFFSETOF (pike_frame, context.identifier_level), fp_reg, tmp_reg); + ADD_VAL_TO_REG (arg, tmp_reg); + MOV_REG_TO_RELSTACK (tmp_reg, 8); - add_to_program(0x89); /* movl %eax,(%edx) */ - add_to_program(0x02); + MOV_RELADDR_TO_REG (OFFSETOF (pike_frame, current_object), fp_reg, tmp_reg); + MOV_REG_TO_RELSTACK (tmp_reg, 4); - add_to_program(0x83); /* addl $4, %edx */ - add_to_program(0xc2); - add_to_program(sizeof(struct svalue *)); /*4*/ - - add_to_program(0x89); /* movl %edx, mark_sp */ - add_to_program(0x15); - PUSH_ADDR( & Pike_interpreter.mark_stack_pointer ); + LOAD_SP (0); + MOV_REG_TO_RELSTACK (sp_reg, 0); + + ia32_call_c_function (low_object_index_no_free); + + ADD_VAL_TO_ABSADDR (sizeof (struct svalue), Pike_interpreter.stack_pointer); +} + +static void ia32_mark(void) +{ + LOAD_SP (1 << mark_sp_reg); + LOAD_MARK_SP (1 << sp_reg); + + MOV_REG_TO_RELADDR (sp_reg, 0, mark_sp_reg); + ADD_VAL_TO_REG (sizeof (struct svalue *), mark_sp_reg); + MOV_REG_TO_ABSADDR (mark_sp_reg, Pike_interpreter.mark_stack_pointer); } INT32 ins_f_jump(unsigned int b) @@ -384,13 +466,78 @@ static void ia32_push_int(INT32 x) ia32_push_constant(&tmp); } -static void ia32_call_c_function(void *addr) +static void ia32_push_string (INT32 x, int subtype) { -/* CALL_ABSOLUTE(instrs[b].address); */ - CALL_RELATIVE(addr); - ia32_reg_eax=REG_IS_UNKNOWN; - ia32_reg_ecx=REG_IS_UNKNOWN; - ia32_reg_edx=REG_IS_UNKNOWN; + enum ia32_reg tmp_reg; + + struct svalue tmp = {PIKE_T_STRING, subtype, +#ifdef HAVE_UNION_INIT + {0} +#endif + }; + size_t e; + + LOAD_FP (1 << sp_reg); + tmp_reg = alloc_reg ((1 << fp_reg) | (1 << sp_reg)); + + MOV_RELADDR_TO_REG (OFFSETOF (pike_frame, context.prog), fp_reg, tmp_reg); + MOV_RELADDR_TO_REG (OFFSETOF (program, strings), tmp_reg, tmp_reg); + MOV_RELADDR_TO_REG (x * sizeof (struct pike_string *), tmp_reg, tmp_reg); + /* tmp_reg is now Pike_fp->context.prog->strings[x] */ + + LOAD_SP (1 << tmp_reg); + + for (e = 0; e < sizeof (tmp) / 4; e++) { + if (((INT32 *) &tmp) + e == (INT32 *) &tmp.u.string) + MOV_REG_TO_RELADDR (tmp_reg, e * 4, sp_reg); + else + MOV_VAL_TO_RELADDR (((INT32 *) &tmp)[e], e * 4, sp_reg); + } + + ADD_VAL_TO_RELADDR (1, 0, tmp_reg); + + ADD_VAL_TO_REG (sizeof (struct svalue), sp_reg); + MOV_REG_TO_ABSADDR (sp_reg, Pike_interpreter.stack_pointer); +} + +void ia32_update_pc(void) +{ + INT32 tmp = PIKE_PC, disp; + + if (ia32_prev_stored_pc < 0) { + enum ia32_reg tmp_reg = alloc_reg (1 << fp_reg); +#ifdef PIKE_DEBUG + if (a_flag >= 60) + fprintf (stderr, "pc %d update pc absolute\n", tmp); +#endif + LOAD_FP (1 << tmp_reg); + /* Store the negated pointer to make the relocation displacements + * work in the right direction. */ + MOV_VAL32_TO_REG (0, tmp_reg); + add_to_relocations(PIKE_PC - 4); + upd_pointer(PIKE_PC - 4, - (INT32) (tmp + Pike_compiler->new_program->program)); + add_to_program(0xf7); /* neg tmp_reg */ + add_to_program(0xd8 | tmp_reg); + MOV_REG_TO_RELADDR (tmp_reg, OFFSETOF (pike_frame, pc), fp_reg); + } + + else if ((disp = tmp - ia32_prev_stored_pc)) { +#ifdef PIKE_DEBUG + if (a_flag >= 60) + fprintf (stderr, "pc %d update pc relative: %d\n", tmp, disp); +#endif + LOAD_FP (0); + ADD_VAL_TO_RELADDR (disp, OFFSETOF (pike_frame, pc), fp_reg); + } + + else { +#ifdef PIKE_DEBUG + if (a_flag >= 60) + fprintf (stderr, "pc %d update pc - already up-to-date\n", tmp); +#endif + } + + ia32_prev_stored_pc = tmp; } static void maybe_update_pc(void) @@ -416,24 +563,11 @@ static void ins_debug_instr_prologue (PIKE_INSTR_T instr, INT32 arg1, INT32 arg2 { int flags = instrs[instr].flags; - if (flags & I_HASARG2) { - add_to_program (0xc7); /* movl $xxxx, 0x8(%esp) */ - add_to_program (0x44); - add_to_program (0x24); - add_to_program (0x08); - PUSH_INT (arg2); - } - if (flags & I_HASARG) { - add_to_program (0xc7); /* movl $xxxx, 0x4(%esp) */ - add_to_program (0x44); - add_to_program (0x24); - add_to_program (0x04); - PUSH_INT (arg1); - } - add_to_program (0xc7); /* movl $xxxx, (%esp) */ - add_to_program (0x04); - add_to_program (0x24); - PUSH_INT (instr); + if (flags & I_HASARG2) + MOV_VAL_TO_RELSTACK (arg2, 8); + if (flags & I_HASARG) + MOV_VAL_TO_RELSTACK (arg1, 4); + MOV_VAL_TO_RELSTACK (instr, 0); if (flags & I_HASARG2) ia32_call_c_function (simple_debug_instr_prologue_2); @@ -443,7 +577,7 @@ static void ins_debug_instr_prologue (PIKE_INSTR_T instr, INT32 arg1, INT32 arg2 ia32_call_c_function (simple_debug_instr_prologue_0); } #else /* !PIKE_DEBUG */ -#define ins_debug_instr_prologue(instr, arg1, arg2) 0 +#define ins_debug_instr_prologue(instr, arg1, arg2) #endif void ins_f_byte(unsigned int b) @@ -553,6 +687,33 @@ void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b) ia32_local_lvalue(b); return; + case F_MARK_AND_GLOBAL: + ins_debug_instr_prologue (a - F_OFFSET, b, 0); + ia32_mark(); + ia32_push_global (b); + return; + + case F_GLOBAL: + ins_debug_instr_prologue (a - F_OFFSET, b, 0); + ia32_push_global (b); + return; + + case F_MARK_AND_STRING: + ins_debug_instr_prologue (a - F_OFFSET, b, 0); + ia32_mark(); + ia32_push_string (b, 0); + return; + + case F_STRING: + ins_debug_instr_prologue (a - F_OFFSET, b, 0); + ia32_push_string (b, 0); + return; + + case F_ARROW_STRING: + ins_debug_instr_prologue (a - F_OFFSET, b, 0); + ia32_push_string (b, 1); + return; + case F_NUMBER: ins_debug_instr_prologue (a - F_OFFSET, b, 0); ia32_push_int(b); diff --git a/src/code/ia32.h b/src/code/ia32.h index 46ed14dce4..f0bcc3541b 100644 --- a/src/code/ia32.h +++ b/src/code/ia32.h @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: ia32.h,v 1.19 2003/03/20 16:29:09 mast Exp $ +|| $Id: ia32.h,v 1.20 2003/03/22 13:39:37 mast Exp $ */ /* #define ALIGN_PIKE_JUMPS 8 */ @@ -23,59 +23,12 @@ #define ins_byte(VAL) add_to_program(VAL) #define ins_data(VAL) ins_int((VAL), (void (*)(char))add_to_program) - -#define MOV2EAX(ADDR) do { \ - add_to_program(0xa1 /* mov $xxxxx, %eax */); \ - ins_pointer( (INT32)&(ADDR)); \ -}while(0) - -#define MOV2EDX(ADDR) do { \ - add_to_program(0x8b); /* mov $xxxxx, %edx */ \ - add_to_program(0x15); \ - ins_pointer( (INT32)&(ADDR)); \ -}while(0) - - -#define SET_MEM_REL_EAX(OFFSET, VALUE) do { \ - INT32 off_ = (OFFSET); \ - add_to_program(0xc7); /* movl $xxxxx, yy%(eax) */ \ - if(off_) \ - { \ - add_to_program(0x40); \ - add_to_program(off_); \ - }else{ \ - add_to_program(0x0); \ - } \ - ins_pointer(VALUE); /* Assumed to be added last. */ \ -}while(0) - -#define SET_MEM_REL_EDX(OFFSET, VALUE) do { \ - INT32 off_ = (OFFSET); \ - add_to_program(0xc7); /* movl $xxxxx, yy%(edx) */ \ - if(off_) \ - { \ - add_to_program(0x42); \ - add_to_program(off_); \ - }else{ \ - add_to_program(0x02); \ - } \ - ins_pointer(VALUE); /* Assumed to be added last. */ \ -}while(0) - -#define REG_IS_SP 1 -#define REG_IS_FP 2 -#define REG_IS_MARK_SP 3 -#define REG_IS_UNKNOWN -1 - -extern int ia32_reg_eax; -extern int ia32_reg_ecx; -extern int ia32_reg_edx; -extern ptrdiff_t ia32_prev_stored_pc; - void ia32_update_pc(void); #define UPDATE_PC() ia32_update_pc() +extern ptrdiff_t ia32_prev_stored_pc; + #define ADJUST_PIKE_PC(pc) do { \ ia32_prev_stored_pc = pc; \ DO_IF_DEBUG( \ @@ -124,11 +77,14 @@ void ia32_flush_code_generator(void); #define FLUSH_CODE_GENERATOR_STATE ia32_flush_code_generator #define CALL_MACHINE_CODE(pc) \ - /* This code does not clobber %eax, %ecx & %edx, but \ + /* This code does not clobber %eax, %ebx, %ecx & %edx, but \ * the code jumped to does. \ */ \ - __asm__ __volatile__( " sub $8,%%esp\n" \ + __asm__ __volatile__( " sub $12,%%esp\n" \ " jmp *%0" \ : "=m" (pc) \ : \ - : "cc", "memory", "eax", "ecx", "edx" ) + : "cc", "memory", "eax", "ebx", "ecx", "edx" ) + +#define EXIT_MACHINE_CODE() \ + __asm__ __volatile__( "add $12,%%esp\n" : : ) -- GitLab