|
|
|
|
#include "operators.h" |
#include "constants.h" |
#include "object.h" |
#include "builtin_functions.h" |
|
|
|
#ifdef REG_NONE |
#undef REG_NONE |
#endif |
|
|
|
enum amd64_reg {REG_RAX = 0, REG_RBX = 3, REG_RCX = 1, REG_RDX = 2, |
REG_R8 = 8, REG_R9 = 9, REG_10 = 10, REG_R11 = 11, |
REG_R12 = 12, REG_R13 = 13, REG_R14 = 14, REG_R15 = 15, REG_NONE = 4}; |
|
#define CLEAR_REGS() do {} while (0) |
|
#define PUSH_INT(X) ins_int((INT32)(X), (void (*)(char))add_to_program) |
|
|
|
|
|
#define MOV_VAL_TO_RELSTACK(VALUE, OFFSET) do { \ |
INT32 off_ = (OFFSET); \ |
add_to_program(0xc7); \ |
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 CALL_RELATIVE(X) do{ \ |
struct program *p_=Pike_compiler->new_program; \ |
add_to_program(0xe8); \ |
add_to_program(0); \ |
add_to_program(0); \ |
add_to_program(0); \ |
add_to_program(0); \ |
add_to_relocations(p_->num_program-4); \ |
*(INT32 *)(p_->program + p_->num_program - 4)= \ |
((INT32)(X)) - (INT32)(p_->program + p_->num_program); \ |
}while(0) |
|
static void update_arg1(INT32 value) { |
MOV_VAL_TO_RELSTACK(value, 0); |
} |
|
static void update_arg2(INT32 value) { |
MOV_VAL_TO_RELSTACK(value, 4); |
} |
|
|
static enum amd64_reg next_reg; |
static enum amd64_reg sp_reg, fp_reg, mark_sp_reg; |
ptrdiff_t amd64_prev_stored_pc; |
|
|
static void amd64_call_c_function(void *addr) { |
CALL_RELATIVE(addr); |
next_reg = REG_RAX; |
sp_reg = fp_reg = mark_sp_reg = REG_NONE; |
CLEAR_REGS(); |
} |
|
|
void amd64_update_pc(void) { |
INT32 tmp = PIKE_PC, disp; |
|
if (amd64_prev_stored_pc < 0) { |
enum amd64_reg tmp_reg = alloc_reg (1 << fp_reg); |
load_fp_reg (1 << tmp_reg); |
#ifdef PIKE_DEBUG |
if (a_flag >= 60) |
fprintf (stderr, "pc %d update pc absolute\n", tmp); |
#endif |
|
* 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)); |
CHECK_VALID_REG (tmp_reg); |
add_to_program(0xf7); |
add_to_program(0xd8 | tmp_reg); |
MOV_REG_TO_RELADDR (tmp_reg, OFFSETOF (pike_frame, pc), fp_reg); |
DEALLOC_REG (tmp_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_reg (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 |
} |
amd64_prev_stored_pc = tmp; |
} |
|
|
static void maybe_update_pc(void) { |
static int last_prog_id=-1; |
static size_t last_num_linenumbers=-1; |
|
if( |
#ifdef PIKE_DEBUG |
|
d_flag || |
#endif |
(amd64_prev_stored_pc == -1) || |
last_prog_id != Pike_compiler->new_program->id || |
last_num_linenumbers != Pike_compiler->new_program->num_linenumbers |
) { |
last_prog_id=Pike_compiler->new_program->id; |
last_num_linenumbers = Pike_compiler->new_program->num_linenumbers; |
UPDATE_PC(); |
} |
} |
|
void ins_f_byte(unsigned int b) { |
void *addr; |
b-=F_OFFSET; |
#ifdef PIKE_DEBUG |
if(b>255) |
Pike_error("Instruction too big %d\n",b); |
#endif |
maybe_update_pc(); |
addr=instrs[b].address; |
amd64_call_c_function(addr); |
} |
|
void ins_f_byte_with_arg(unsigned int a, INT32 b) { |
maybe_update_pc(); |
update_arg1(b); |
ins_f_byte(a); |
} |
|
void ins_f_byte_with_2_args(unsigned int a, INT32 b, INT32 c) { |
maybe_update_pc(); |
update_arg1(b); |
update_arg2(c); |
ins_f_byte(a); |
} |
|
|
|