diff --git a/src/code/amd64.c b/src/code/amd64.c index e883c8273c42600be766c4f3b626179a26be48d0..71368ed8fc8e9a6578ae492cd9110ee480092da7 100644 --- a/src/code/amd64.c +++ b/src/code/amd64.c @@ -45,6 +45,15 @@ #define REG_R14 MISSING_P_ #define REG_R15 MISSING_P_ +struct soff { int off; int type; int value; }; + +static struct soff SVAL(int i) +{ + struct soff res; + res.off = res.type = i*sizeof(struct svalue); + res.value = res.type + 8; + return res; +} /* Register encodings */ enum amd64_reg {P_REG_RAX = 0, P_REG_RBX = 3, P_REG_RCX = 1, P_REG_RDX = 2, @@ -214,6 +223,13 @@ static void mov_reg_reg(enum amd64_reg from_reg, enum amd64_reg to_reg ) modrm( 3, from_reg, to_reg ); } +static void mov_reg32_reg(enum amd64_reg from_reg, enum amd64_reg to_reg ) +{ + rex( 0, from_reg, 0, to_reg ); + opcode( 0x89 ); + modrm( 3, from_reg, to_reg ); +} + #define PUSH_INT(X) ins_int((INT32)(X), (void (*)(char))add_to_program) static void low_mov_mem_reg(enum amd64_reg from_reg, ptrdiff_t offset, enum amd64_reg to_reg) @@ -1078,7 +1094,7 @@ static void amd64_load_mark_sp_reg(void) static void mov_sval_type(enum amd64_reg src, enum amd64_reg dst ) { - mov_mem8_reg( src, OFFSETOF(svalue, tu.t.type), dst); + mov_mem8_reg( src, SVAL(0).type, dst); /* and_reg32_imm( dst, 0x1f );*/ } @@ -1118,7 +1134,7 @@ static void update_arg2(INT32 value) static void amd64_add_sp( int num ) { amd64_load_sp_reg(); - add_reg_imm( sp_reg, sizeof(struct svalue)*num); + add_reg_imm( sp_reg, num * sizeof(struct svalue)); dirty_regs |= 1 << PIKE_SP_REG; flush_dirty_regs(); /* FIXME: Need to change LABEL handling to remove this */ } @@ -1126,7 +1142,7 @@ static void amd64_add_sp( int num ) static void amd64_add_mark_sp( int num ) { amd64_load_mark_sp_reg(); - add_reg_imm( mark_sp_reg, sizeof(struct svalue*)*num); + add_reg_imm( mark_sp_reg, num * sizeof(struct svalue*)); dirty_regs |= 1 << PIKE_MARK_SP_REG; flush_dirty_regs(); /* FIXME: Need to change LABEL handling to remove this */ } @@ -1140,10 +1156,8 @@ static void amd64_push_svaluep_to(int reg, int spoff) amd64_load_sp_reg(); mov_mem_reg(reg, OFFSETOF(svalue, tu.t.type), P_REG_RAX); mov_mem_reg(reg, OFFSETOF(svalue, u.refs), P_REG_RCX); - mov_reg_mem(P_REG_RAX, sp_reg, - spoff*sizeof(struct svalue)+OFFSETOF(svalue, tu.t.type)); - mov_reg_mem(P_REG_RCX, sp_reg, - spoff*sizeof(struct svalue)+OFFSETOF(svalue, u.refs)); + mov_reg_mem(P_REG_RAX, sp_reg, SVAL(spoff).type); + mov_reg_mem(P_REG_RCX, sp_reg, SVAL(spoff).value); and_reg32_imm(P_REG_RAX, MIN_REF_TYPE); jz(&label_A); add_imm_mem( 1, P_REG_RCX, OFFSETOF(pike_string, refs)); @@ -1159,8 +1173,8 @@ static void amd64_push_svaluep(int reg) static void amd64_push_int(INT64 value, int subtype) { amd64_load_sp_reg(); - mov_imm_mem((subtype<<16) + PIKE_T_INT, sp_reg, OFFSETOF(svalue, tu.t.type)); - mov_imm_mem(value, sp_reg, OFFSETOF(svalue, u.integer)); + mov_imm_mem((subtype<<16) + PIKE_T_INT, sp_reg, SVAL(0).type); + mov_imm_mem(value, sp_reg, SVAL(0).value); amd64_add_sp( 1 ); } @@ -1211,19 +1225,18 @@ static void amd64_call_c_function(void *addr) call_imm(addr); } -static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref ) +static void amd64_free_svalue_off(enum amd64_reg src, int off, int guaranteed_ref ) { LABELS(); if( src == P_REG_RAX ) Pike_fatal("Clobbering RAX for free-svalue\n"); /* load type -> RAX */ - mov_sval_type( src, P_REG_RAX ); - + mov_mem8_reg( src, off, P_REG_RAX ); and_reg_imm(P_REG_RAX, MIN_REF_TYPE); jz( &label_A ); /* Load pointer to refs -> RAX */ - mov_mem_reg( src, OFFSETOF(svalue, u.refs), P_REG_RAX); + mov_mem_reg( src,off+OFFSETOF(svalue, u.refs), P_REG_RAX); /* if( !--*RAX ) */ add_mem32_imm( P_REG_RAX, OFFSETOF(pike_string,refs), -1); if( !guaranteed_ref ) @@ -1231,13 +1244,17 @@ static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref ) /* We need to see if refs got to 0. */ jnz( &label_A ); /* if so, call really_free_svalue */ - if( src != ARG1_REG ) - mov_reg_reg( src, ARG1_REG ); + add_reg_imm_reg( src, off, ARG1_REG ); amd64_call_c_function(really_free_svalue); } LABEL_A; } +static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref ) +{ + amd64_free_svalue_off(src,0,guaranteed_ref); +} + /* Type already in register. Note: Clobbers the type register. */ static void amd64_free_svalue_type(enum amd64_reg src, enum amd64_reg type, int guaranteed_ref ) @@ -1536,6 +1553,16 @@ static void amd64_ins_branch_check_threads_etc(int code_only) void amd64_init_interpreter_state(void) { +#ifdef PIKE_DEBUG + if( PIKE_T_INT != 0 ) + Pike_fatal("assumption failed: pike_t_int == 0\n"); + if( sizeof(struct svalue) != 16 ) + Pike_fatal("assumption failed: sizeof svalue != 16\n"); + if( OFFSETOF(svalue,tu.t.type) != 0 ) + Pike_fatal("assumption failed: offsetof(svalue.tu.t.type) != 0\n"); + if( OFFSETOF(svalue,u.integer) != 8 ) + Pike_fatal("assumption failed: offsetof(svalue.u.integer) != 8\n"); +#endif instrs[F_CATCH - F_OFFSET].address = inter_return_opcode_F_CATCH; } @@ -1925,6 +1952,27 @@ void ins_f_byte(unsigned int b) rel_addr = PIKE_PC; } break; + + /* sp-1 = undefinedp(sp-1) */ + case F_UNDEFINEDP: + { + LABELS(); + ins_debug_instr_prologue(b, 0, 0); + amd64_load_sp_reg(); + + mov_mem32_reg( sp_reg, SVAL(-1).type, P_REG_RAX ); + cmp_reg32_imm( P_REG_RAX, 1<<16 | PIKE_T_INT ); + jne( &label_A ); + mov_imm_mem( 1, sp_reg,SVAL(-1).value); + jmp( &label_B ); + LABEL_A; + amd64_free_svalue_off( sp_reg, SVAL(-1).off,0 ); + mov_imm_mem( 0, sp_reg,SVAL(-1).value); + LABEL_B; + mov_imm_mem( PIKE_T_INT, sp_reg,SVAL(-1).type); + } + return; + case F_ZERO_TYPE: { LABELS(); @@ -1932,8 +1980,8 @@ void ins_f_byte(unsigned int b) amd64_load_sp_reg(); mov_mem32_reg( sp_reg, -sizeof(struct svalue), P_REG_RAX ); /* Rax now has type + subtype. */ - mov_reg_reg( P_REG_RAX, P_REG_RBX ); - and_reg_imm( P_REG_RAX, 0x1f ); + mov_reg32_reg( P_REG_RAX, P_REG_RBX ); + and_reg32_imm( P_REG_RAX, 0x1f ); cmp_reg32_imm( P_REG_RAX, PIKE_T_INT ); jne( &label_A ); /* It is an integer. */ @@ -2101,7 +2149,7 @@ void ins_f_byte(unsigned int b) amd64_load_fp_reg(); /* Note: really mem16, but we & with PIKE_FRAME_RETURN_INTERNAL anyway */ mov_mem32_reg( fp_reg, OFFSETOF(pike_frame, flags), P_REG_RAX ); - and_reg_imm( P_REG_RAX, PIKE_FRAME_RETURN_INTERNAL); + and_reg32_imm( P_REG_RAX, PIKE_FRAME_RETURN_INTERNAL); jnz( &label_A ); /* So, it is just a normal return. */ LABEL_B; @@ -2112,7 +2160,7 @@ void ins_f_byte(unsigned int b) LABEL_A; /* We should jump to the given address. */ mov_mem32_reg( fp_reg, OFFSETOF(pike_frame, flags), P_REG_RAX ); - and_reg_imm( P_REG_RAX, PIKE_FRAME_RETURN_POP ); + and_reg32_imm( P_REG_RAX, PIKE_FRAME_RETURN_POP ); jnz( &label_C ); amd64_call_c_function( low_return ); jmp( &label_D ); @@ -2136,7 +2184,7 @@ void ins_f_byte(unsigned int b) /* NB: We only care about subtype 1! */ cmp_reg32_imm(P_REG_RAX, (1<<16)|PIKE_T_STRING); jne(&label_A); - and_reg_imm(P_REG_RAX, 0x1f); + and_reg32_imm(P_REG_RAX, 0x1f); mov_reg_mem32(P_REG_RAX, sp_reg, OFFSETOF(svalue, tu.t.type) - sizeof(struct svalue)); LABEL_A;