pike.git / src / code / amd64.c

version» Context lines:

pike.git/src/code/amd64.c:101:    if (to_reg__ & 0x08) { \    rex__ |= 0x04; \    to_reg__ &= 0x07; \    } \    add_to_program(rex__); \    add_to_program(0x8b); \    add_to_program(0x80|(to_reg__<<3)| from_reg__); \    PUSH_INT(off32__); \    } while(0)    + #define AMD64_MOVE32_RELADDR_TO_REG(FROM_REG, FROM_OFFSET, TO_REG) do { \ +  enum amd64_reg from_reg__ = (FROM_REG); \ +  enum amd64_reg to_reg__ = (TO_REG); \ +  int off32__ = (FROM_OFFSET); \ +  int rex__ = 0x40; \ +  if (from_reg__ & 0x08) { \ +  rex__ |= 0x01; \ +  from_reg__ &= 0x07; \ +  } \ +  if (to_reg__ & 0x08) { \ +  rex__ |= 0x04; \ +  to_reg__ &= 0x07; \ +  } \ +  if (rex__ != 0x40) { \ +  add_to_program(rex__); \ +  } \ +  add_to_program(0x8b); \ +  add_to_program(0x80|(to_reg__<<3)| from_reg__); \ +  PUSH_INT(off32__); \ +  } while(0) +    #define AMD64_MOVE_REG_TO_RELADDR(FROM_REG, TO_REG, TO_OFFSET) do { \    enum amd64_reg from_reg__ = (FROM_REG); \    enum amd64_reg to_reg__ = (TO_REG); \    int off32__ = (TO_OFFSET); \    int rex__ = 0x48; \    if (from_reg__ & 0x08) { \    rex__ |= 0x04; \    from_reg__ &= 0x07; \    } \    if (to_reg__ & 0x08) { \
pike.git/src/code/amd64.c:161:      #define AMD64_AND_IMM32(REG, IMM32) do { \    enum amd64_reg reg__ = (REG); \    int imm32__ = (IMM32); \    if (reg__ & 0x08) { \    add_to_program(0x49); \    reg__ &= 0x07; \    } else { \    add_to_program(0x48); \    } \ -  add_to_program(0x83); \ +     if ((imm32__ >= -0x80) && (imm32__ <= 0x7f)) { \ -  +  add_to_program(0x83); \    add_to_program(0xe0|reg__); \    add_to_program(imm32__); \    } else { \ -  Pike_error("Not supported yet.\n"); \ +  add_to_program(0x81); \ +  add_to_program(0xe0|reg__); \    PUSH_INT(imm32__); \    } \    } while(0)      #define AMD64_ADD_IMM32(REG, IMM32) do { \    enum amd64_reg reg__ = (REG); \    int imm32__ = (IMM32); \    if (reg__ & 0x08) { \    add_to_program(0x49); \    reg__ &= 0x07; \    } else { \    add_to_program(0x48); \    } \ -  add_to_program(0x83); \ +     if ((imm32__ >= -0x80) && (imm32__ <= 0x7f)) { \ -  +  add_to_program(0x83); \    add_to_program(0xc0|reg__); \    add_to_program(imm32__); \    } else { \ -  Pike_error("Not supported yet.\n"); \ +  add_to_program(0x81); \ +  add_to_program(0xc0|reg__); \    PUSH_INT(imm32__); \    } \    } while(0)      #define AMD64_SUB_IMM32(REG, IMM32) do { \    enum amd64_reg reg__ = (REG); \    int imm32__ = (IMM32); \    if (reg__ & 0x08) { \    add_to_program(0x49); \    reg__ &= 0x07; \    } else { \    add_to_program(0x48); \    } \    add_to_program(0x83); \    if ((imm32__ >= -0x80) && (imm32__ <= 0x7f)) { \    add_to_program(0xe8|reg__); \    add_to_program(imm32__); \    } else { \ -  Pike_error("Not supported yet.\n"); \ +  Pike_fatal("Not supported yet.\n"); \    PUSH_INT(imm32__); \    } \    } while(0)      #define AMD64_TEST_REG(REG) do { \    enum amd64_reg reg__ = (REG); \    if (reg__ & 0x08) { \    add_to_program(0x4d); \    reg__ &= 0x07; \    } else { \
pike.git/src/code/amd64.c:235:    add_to_program(0x49); \    reg__ &= 0x07; \    } else { \    add_to_program(0x48); \    } \    add_to_program(0x83); \    if ((imm32__ >= -0x80) && (imm32__ <= 0x7f)) { \    add_to_program(0xf8|reg__); \    add_to_program(imm32__); \    } else { \ -  Pike_error("Not supported yet.\n"); \ +  Pike_fatal("Not supported yet.\n"); \    PUSH_INT(imm32__); \    } \    } while(0)      #define AMD64_CMP_REG(REG1, REG2) do { \    enum amd64_reg reg1__ = (REG1); \    enum amd64_reg reg2__ = (REG2); \    int rex = 0x48; \    if (reg1__ & 0x08) { \    rex |= 0x04; \
pike.git/src/code/amd64.c:465:    } \    } \    } while (0)      #define AMD64_JMP(SKIP) do {\    int skip__ = (SKIP); \    if ((skip__ >= -0x80) && (skip__ <= 0x7f)) { \    add_to_program(0xeb); \    add_to_program(skip__); \    } else { \ -  Pike_error("Not supported yet.\n"); \ +  Pike_fatal("Not supported yet.\n"); \    } \    } while(0)      #define AMD64_JNE(SKIP) do {\    int skip__ = (SKIP); \    if ((skip__ >= -0x80) && (skip__ <= 0x7f)) { \    add_to_program(0x75); \    add_to_program(skip__); \    } else { \ -  Pike_error("Not supported yet.\n"); \ +  Pike_fatal("Not supported yet.\n"); \    } \    } while(0)      #define AMD64_JE(SKIP) do {\    int skip__ = (SKIP); \    if ((skip__ >= -0x80) && (skip__ <= 0x7f)) { \    add_to_program(0x74); \    add_to_program(skip__); \    } else { \ -  Pike_error("Not supported yet.\n"); \ +  Pike_fatal("Not supported yet.\n"); \    } \    } while(0)    -  + #define AMD64_JG(SKIP) do {\ +  int skip__ = (SKIP); \ +  if ((skip__ >= -0x80) && (skip__ <= 0x7f)) { \ +  add_to_program(0x7f); \ +  add_to_program(skip__); \ +  } else { \ +  Pike_fatal("Not supported yet.\n"); \ +  } \ +  } while(0) +    /* Machine code entry prologue.    *    * On entry:    * RDI: Pike_interpreter (ARG1_REG)    *    * During interpreting:    * R15: Pike_interpreter    */   void amd64_ins_entry(void)   {
pike.git/src/code/amd64.c:557:   void amd64_flush_code_generator_state(void)   {    next_reg = 0;    sp_reg = 0;    fp_reg = 0;    mark_sp_reg = 0;    dirty_regs = 0;    amd64_prev_stored_pc = -1;   }    + static void flush_dirty_regs(void) + { +  /* NB: PIKE_FP_REG is currently never dirty. */ +  if (dirty_regs & (1 << PIKE_SP_REG)) { +  AMD64_MOVE_REG_TO_RELADDR(PIKE_SP_REG, Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter, stack_pointer)); +  dirty_regs &= ~(1 << PIKE_SP_REG); +  } +  if (dirty_regs & (1 << PIKE_MARK_SP_REG)) { +  AMD64_MOVE_REG_TO_RELADDR(PIKE_MARK_SP_REG, Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter, mark_stack_pointer)); +  dirty_regs &= ~(1 << PIKE_MARK_SP_REG); +  } + } +    static enum amd64_reg alloc_reg (int avoid_regs)   {    enum amd64_reg reg;    int used_regs = (avoid_regs | REG_RESERVED) & REG_BITMASK;       avoid_regs |= REG_RESERVED;       if (used_regs != REG_BITMASK) {    /* There's a free register. */   
pike.git/src/code/amd64.c:649:    AMD64_LOAD_IMM32(ARG1_REG, value);    /* FIXME: Alloc stack space on NT. */   }      static void update_arg2(INT32 value)   {    AMD64_LOAD_IMM32(ARG2_REG, value);    /* FIXME: Alloc stack space on NT. */   }    + /* Note: Uses RAX and RCX internally. reg MUST not be REG_RAX. */ + static void amd64_push_svaluep(int reg) + { +  INT32 skip; +  amd64_load_sp_reg(); +  AMD64_MOVE_RELADDR_TO_REG(reg, OFFSETOF(svalue, type), REG_RAX); +  AMD64_MOVE_RELADDR_TO_REG(reg, OFFSETOF(svalue, u.refs), REG_RCX); +  AMD64_MOVE_REG_TO_RELADDR(REG_RAX, sp_reg, OFFSETOF(svalue, type)); +  AMD64_AND_IMM32(REG_RAX, 0x1f); +  AMD64_MOVE_REG_TO_RELADDR(REG_RCX, sp_reg, OFFSETOF(svalue, u.refs)); +  AMD64_CMP_REG_IMM32(REG_RAX, MAX_REF_TYPE); +  AMD64_JG(0); +  skip = PIKE_PC; +  AMD64_ADD_VAL_TO_RELADDR(1, OFFSETOF(pike_string, refs), REG_RCX); +  Pike_compiler->new_program->program[skip-1] = ((INT32)PIKE_PC) - skip; +  AMD64_ADD_IMM32(sp_reg, sizeof(struct svalue)); +  dirty_regs |= 1 << sp_reg; +  /* FIXME: Deferred writing of Pike_sp doen't seem to work reliably yet. */ +  if (dirty_regs & (1 << PIKE_SP_REG)) { +  AMD64_MOVE_REG_TO_RELADDR(PIKE_SP_REG, Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter, stack_pointer)); +  dirty_regs &= ~(1 << PIKE_SP_REG); +  } + } +    static void amd64_push_int(INT64 value, int subtype)   {    amd64_load_sp_reg();    AMD64_LOAD_IMM32(REG_RAX, (subtype<<16) + PIKE_T_INT);    AMD64_MOVE_REG_TO_RELADDR(REG_RAX, sp_reg, OFFSETOF(svalue, type));    AMD64_LOAD_IMM(REG_RAX, value);    AMD64_MOVE_REG_TO_RELADDR(REG_RAX, sp_reg, OFFSETOF(svalue, u.integer));    AMD64_ADD_IMM32(sp_reg, sizeof(struct svalue));    dirty_regs |= 1 << sp_reg;    /* FIXME: Deferred writing of Pike_sp doen't seem to work reliably yet. */
pike.git/src/code/amd64.c:724:    AMD64_ADD_VAL_TO_RELADDR(1, OFFSETOF(pike_string, refs), REG_RAX);    dirty_regs |= 1 << sp_reg;    /* FIXME: Deferred writing of Pike_sp doen't seem to work reliably yet. */    if (dirty_regs & (1 << PIKE_SP_REG)) {    AMD64_MOVE_REG_TO_RELADDR(PIKE_SP_REG, Pike_interpreter_reg,    OFFSETOF(Pike_interpreter, stack_pointer));    dirty_regs &= ~(1 << PIKE_SP_REG);    }   }    + static void amd64_push_local_function(int fun) + { +  amd64_load_fp_reg(); +  amd64_load_sp_reg(); +  AMD64_MOVE_RELADDR_TO_REG(fp_reg, OFFSETOF(pike_frame, context), REG_RAX); +  AMD64_MOVE_RELADDR_TO_REG(fp_reg, OFFSETOF(pike_frame, current_object), +  REG_RCX); +  AMD64_MOVE32_RELADDR_TO_REG(REG_RAX, OFFSETOF(inherit, identifier_level), +  REG_RAX); +  AMD64_MOVE_REG_TO_RELADDR(REG_RCX, sp_reg, OFFSETOF(svalue, u.object)); +  AMD64_ADD_IMM32(REG_RAX, fun); +  AMD64_ADD_VAL_TO_RELADDR(1, (INT32)OFFSETOF(object, refs), REG_RCX); +  AMD64_SHL_IMM8(REG_RAX, 16); +  AMD64_ADD_IMM32(REG_RAX, PIKE_T_FUNCTION); +  AMD64_MOVE_REG_TO_RELADDR(REG_RAX, sp_reg, OFFSETOF(svalue, type)); +  AMD64_ADD_IMM32(sp_reg, sizeof(struct svalue)); +  dirty_regs |= 1 << sp_reg; +  /* FIXME: Deferred writing of Pike_sp doen't seem to work reliably yet. */ +  if (dirty_regs & (1 << PIKE_SP_REG)) { +  AMD64_MOVE_REG_TO_RELADDR(PIKE_SP_REG, Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter, stack_pointer)); +  dirty_regs &= ~(1 << PIKE_SP_REG); +  } + } +    static void amd64_call_c_function(void *addr)   {    CALL_ABSOLUTE(addr);    next_reg = REG_RAX;    CLEAR_REGS();   }      static void amd64_stack_error(void)   {    Pike_fatal("Stack error\n");
pike.git/src/code/amd64.c:899:    case F_MARK2:    ins_f_byte(F_MARK);    ins_f_byte(F_MARK);    return;    case F_POP_MARK:    ins_debug_instr_prologue(b, 0, 0);    amd64_pop_mark();    return;    }    -  /* NB: PIKE_FP_REG is currently never dirty. */ -  if (dirty_regs & (1 << PIKE_SP_REG)) { -  AMD64_MOVE_REG_TO_RELADDR(PIKE_SP_REG, Pike_interpreter_reg, -  OFFSETOF(Pike_interpreter, stack_pointer)); -  dirty_regs &= ~(1 << PIKE_SP_REG); -  } -  if (dirty_regs & (1 << PIKE_MARK_SP_REG)) { -  AMD64_MOVE_REG_TO_RELADDR(PIKE_MARK_SP_REG, Pike_interpreter_reg, -  OFFSETOF(Pike_interpreter, mark_stack_pointer)); -  dirty_regs &= ~(1 << PIKE_MARK_SP_REG); -  } +  flush_dirty_regs();    if (flags & I_UPDATE_SP) sp_reg = 0;    if (flags & I_UPDATE_M_SP) mark_sp_reg = 0;    if (flags & I_UPDATE_FP) fp_reg = 0;       amd64_call_c_function(addr);    if (instrs[b].flags & I_RETURN) {    INT32 skip;    if ((b + F_OFFSET) == F_RETURN_IF_TRUE) {    /* Kludge. We must check if the ret addr is    * orig_addr + JUMP_EPILOGUE_SIZE. */
pike.git/src/code/amd64.c:967: Inside #if defined(PIKE_DEBUG)
   int ret = -1;   #ifdef PIKE_DEBUG    if(off>255)    Pike_error("Instruction too big %d\n",off);   #endif    flags = instrs[off].flags;    if (!(flags & I_BRANCH)) return -1;       maybe_update_pc();    -  /* NB: PIKE_FP_REG is currently never dirty. */ -  if (dirty_regs & (1 << PIKE_SP_REG)) { -  amd64_load_fp_reg(); -  AMD64_MOVE_REG_TO_RELADDR(PIKE_SP_REG, Pike_interpreter_reg, -  OFFSETOF(Pike_interpreter, stack_pointer)); -  dirty_regs &= ~(1 << PIKE_SP_REG); -  } -  if (dirty_regs & (1 << PIKE_MARK_SP_REG)) { -  amd64_load_fp_reg(); -  AMD64_MOVE_REG_TO_RELADDR(PIKE_MARK_SP_REG, Pike_interpreter_reg, -  OFFSETOF(Pike_interpreter, mark_stack_pointer)); -  dirty_regs &= ~(1 << PIKE_MARK_SP_REG); -  } +  flush_dirty_regs();       if (flags & I_UPDATE_SP) sp_reg = 0;    if (flags & I_UPDATE_M_SP) mark_sp_reg = 0;    if (flags & I_UPDATE_FP) fp_reg = 0;       if (op == F_BRANCH) {    ins_debug_instr_prologue(off, 0, 0);    if (backward_jump) {    amd64_call_c_function(branch_check_threads_etc);    }
pike.git/src/code/amd64.c:1081:    ins_f_byte_with_arg(F_GLOBAL, b);    return;    case F_MARK_AND_LOCAL:    ins_f_byte(F_MARK);    ins_f_byte_with_arg(F_LOCAL, b);    return;    case F_MARK_X:    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_mark(b);    return; +  case F_LFUN: +  ins_debug_instr_prologue(a-F_OFFSET, b, 0); +  amd64_push_local_function(b); +  return; +  case F_GLOBAL: +  ins_debug_instr_prologue(a-F_OFFSET, b, 0); +  amd64_load_fp_reg(); +  amd64_load_sp_reg(); +  AMD64_MOVE_RELADDR_TO_REG(fp_reg, OFFSETOF(pike_frame, context), ARG3_REG); +  AMD64_MOVE_RELADDR_TO_REG(fp_reg, OFFSETOF(pike_frame, current_object), +  ARG2_REG); +  AMD64_MOV_REG(sp_reg, ARG1_REG); +  AMD64_MOVE32_RELADDR_TO_REG(ARG3_REG, OFFSETOF(inherit, identifier_level), +  ARG3_REG); +  AMD64_AND_IMM32(ARG3_REG, 0xffff); +  AMD64_ADD_IMM32(ARG3_REG, b); +  flush_dirty_regs(); /* In case an error is thrown. */ +  CALL_ABSOLUTE(low_object_index_no_free); +  /* NB: We know that low_object_index_no_free() doesn't +  * mess with the stack pointer. */ +  AMD64_ADD_IMM32(sp_reg, sizeof(struct svalue)); +  dirty_regs |= 1 << sp_reg; +  flush_dirty_regs(); +  return; +  case F_LOCAL: +  ins_debug_instr_prologue(a-F_OFFSET, b, 0); +  amd64_load_fp_reg(); +  amd64_load_sp_reg(); +  AMD64_MOVE_RELADDR_TO_REG(fp_reg, OFFSETOF(pike_frame, locals), REG_RCX); +  AMD64_ADD_IMM32(REG_RCX, b*sizeof(struct svalue)); +  amd64_push_svaluep(REG_RCX); +  return;    }    update_arg1(b);    ins_f_byte(a);   }      int amd64_ins_f_jump_with_arg(unsigned int op, INT32 a, int backward_jump)   {    if (!(instrs[op - F_OFFSET].flags & I_BRANCH)) return -1;    maybe_update_pc();    update_arg1(a);
pike.git/src/code/amd64.c:1106:    maybe_update_pc();    switch(a) {    case F_NUMBER64:    ins_debug_instr_prologue(a-F_OFFSET, b, c);    amd64_push_int((((unsigned INT64)b)<<32)|(unsigned INT32)c, 0);    return;    case F_MARK_AND_EXTERNAL:    ins_f_byte(F_MARK);    ins_f_byte_with_2_args(F_EXTERNAL, b, c);    return; +  case F_2_LOCALS: +  ins_f_byte_with_arg(F_LOCAL, b); +  ins_f_byte_with_arg(F_LOCAL, c); +  return;    }    update_arg2(c);    update_arg1(b);    ins_f_byte(a);   }      int amd64_ins_f_jump_with_2_args(unsigned int op, INT32 a, INT32 b,    int backward_jump)   {    if (!(instrs[op - F_OFFSET].flags & I_BRANCH)) return -1;