pike.git / src / code / amd64.c

version» Context lines:

pike.git/src/code/amd64.c:624: Inside #if 0
     #if 0   static void mov_reg_mem16( enum amd64_reg from_reg, enum amd64_reg to_reg, ptrdiff_t offset )   {    opcode( 0x66 );    rex(0, from_reg, 0, to_reg );    low_mov_reg_mem( from_reg, to_reg, offset );   }   #endif    - static void mov_imm_mem16( short imm, enum amd64_reg to_reg, ptrdiff_t offset ) + static void PIKE_UNUSED_ATTRIBUTE mov_imm_mem16( short imm, enum amd64_reg to_reg, +  ptrdiff_t offset )   {    opcode( 0x66 ); /* switch 32/16 */       /* basically copy of mov_imm_mem32 */    rex( 0, 0, 0, to_reg );    opcode( 0xc7 ); /* now: mov imm16 -> r/m16 (sign extend)*/       /* This does not work for rg&7 == 4 or 5. */    offset_modrm_sib( offset, 0, to_reg );    iw( imm );
pike.git/src/code/amd64.c:1206:    amd64_ins_branch_check_threads_etc(1);    func_start = PIKE_PC;   }      /* Called when the current function is done */   void amd64_end_function(int UNUSED(no_pc))   {    branch_check_threads_update_etc = 0;   }    + #ifdef MACHINE_CODE_STACK_FRAMES + static void amd64_pop_internal_c_frame() + { +  /* C.f. amd64_ins_start_function() */ +  mov_reg_reg(P_REG_RBP, P_REG_RSP); +  pop(P_REG_RBP); +  add_reg_imm(P_REG_RSP, 8); + } + #endif /* MACHINE_CODE_STACK_FRAMES */    -  + static void amd64_load_fp_reg(void); + static void amd64_call_c_function(void *addr); +  + void amd64_ins_start_function(void) + { + #ifdef MACHINE_CODE_STACK_FRAMES +  LABELS(); +  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_reg32_imm( P_REG_RAX, PIKE_FRAME_RETURN_INTERNAL); +  jz( &label_A ); +  +  amd64_call_c_function(check_c_stack_margin); +  +  /* This is an internal frame (no entry prologue), so we'll insert a +  minimal frame that can be used to unwind the C stack. */ +  mov_mem_reg(fp_reg, OFFSETOF(pike_frame, next), P_REG_RAX); +  mov_mem_reg(P_REG_RAX, OFFSETOF(pike_frame, return_addr), P_REG_RAX); +  push(P_REG_RAX); +  push(P_REG_RBP); +  mov_reg_reg(P_REG_RSP, P_REG_RBP); +  +  LABEL_A; + #endif /* MACHINE_CODE_STACK_FRAMES */ + } +    /* 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:1740:    }    mov_imm_reg( (ptrdiff_t)branch_check_threads_etc, P_REG_RAX );    jmp_reg(P_REG_RAX); /* ret in BCTE will return to desired point. */    amd64_align();    }    if( !code_only )    {    LABEL_A;    /* Use C-stack for counter. We have padding added in entry */   #ifndef USE_VALGRIND + #ifndef MACHINE_CODE_STACK_FRAMES +  /* FIXME: Counter disabled when internal stack frames are used +  since RSP won't point to the entry-level stack frame with +  padding. Dunno if there should be a counter for every internal +  frame too? But that would double C-stack usage per internal +  frame due to 16 byte alignment. */    add_mem8_imm( P_REG_RSP, 0, 1 );    jno( &label_B );   #endif -  + #endif    call_rel_imm32( branch_check_threads_update_etc );   #ifndef USE_VALGRIND    LABEL_B;   #endif    }   }         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; +    }      static void amd64_return_from_function()   {    if( ret_for_func )    {    jmp_rel_imm( ret_for_func );    }    else    {
pike.git/src/code/amd64.c:1805:    {    mov_mem_reg(sp_reg, SVAL(-1).value, P_REG_RAX );    mov_mem_reg(sp_reg, SVAL(-2).value, P_REG_RBX );    }   }      void ins_f_byte(unsigned int b)   {    int flags;    void *addr; -  INT32 rel_addr = 0; +     LABELS();       b-=F_OFFSET;   #ifdef PIKE_DEBUG    if(b>255)    Pike_error("Instruction too big %d\n",b);   #endif    maybe_update_pc();       flags = instrs[b].flags;
pike.git/src/code/amd64.c:2401:    mov_mem32_reg( ARG1_REG,OFFSETOF(pike_string, len ), P_REG_RAX );    jmp( &label_C );    LABEL_B;    /* It's something else, svalue in RBX. */    mov_reg_reg( P_REG_RBX, ARG1_REG );    amd64_call_c_function( pike_sizeof );       LABEL_C;/* all done, res in RAX */    /* free value, store result */    push( P_REG_RAX ); +  sub_reg_imm(P_REG_RSP, 8); /* Align on 16 bytes. */    amd64_free_svalue( P_REG_RBX, 0 ); -  +  add_reg_imm(P_REG_RSP, 8);    pop( P_REG_RAX );    mov_reg_mem(P_REG_RAX, P_REG_RBX, OFFSETOF(svalue, u.integer));    mov_imm_mem(PIKE_T_INT, P_REG_RBX, OFFSETOF(svalue, tu.t.type));    }    return;       case F_POP_VALUE:    {    ins_debug_instr_prologue(b, 0, 0);    amd64_load_sp_reg();    amd64_add_sp( -1 );    amd64_free_svalue( sp_reg, 0 );    }    return;       case F_CATCH:    { -  /* Special argument for the F_CATCH instruction. */ -  addr = inter_return_opcode_F_CATCH; +  INT32 base_addr = 0; +  +  LABELS();    mov_rip_imm_reg(0, ARG1_REG); /* Address for the POINTER. */ -  rel_addr = PIKE_PC; +  base_addr = PIKE_PC; +  +  amd64_call_c_function (setup_catch_context); +  mov_reg_reg(P_REG_RAX, P_REG_RBX); +  +  /* Pass a pointer to Pike_interpreter.catch_ctx.recovery.recovery to +  LOW_SET_JMP. */ +  mov_mem_reg (Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter_struct, catch_ctx), +  ARG1_REG); +  add_reg_imm_reg (ARG1_REG, +  OFFSETOF(catch_context, recovery) + +  OFFSETOF(JMP_BUF, recovery), +  ARG1_REG); +  +  /* Copy the pointer to Pike_interpreter.catching_eval_jmpbuf +  too, for compliance with F_CATCH conventions. +  FIXME: Just ignore catching_eval_jmpbuf in OPCODE_INLINE_CATCH mode? */ +  mov_reg_mem (ARG1_REG, +  Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter_struct, catching_eval_jmpbuf)); +  +  /* Now, call the actual setjmp function. */ +  amd64_call_c_function (LOW_SETJMP_FUNC); +  +  test_reg (P_REG_RAX); +  jnz (&label_A); +  +  jmp (&label_B); +  +  LABEL_A; // Got exception +  +  amd64_call_c_function (handle_caught_exception); +  mov_reg_reg(P_REG_RAX, P_REG_RBX); +  +  /* Restore catching_eval_jmpbuf from catch_ctx->recovery. +  FIXME: Just ignore catching_eval_jmpbuf in OPCODE_INLINE_CATCH mode? */ +  mov_mem_reg (Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter_struct, catch_ctx), +  P_REG_RAX); +  +  test_reg (P_REG_RAX); +  jz (&label_B); /* Pike_interpreter.catch_ctx == 0 */ +  +  add_reg_imm_reg (P_REG_RAX, +  OFFSETOF(catch_context, recovery), +  P_REG_RAX); +  +  mov_mem_reg (Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter_struct, recoveries), +  P_REG_RCX); +  +  cmp_reg_reg(P_REG_RAX, P_REG_RCX); +  jne (&label_B); /* Pike_interpreter.recoveries != +  Pike_interpreter.catch_ctx->recovery */ +  add_reg_imm_reg (P_REG_RAX, +  OFFSETOF(JMP_BUF, recovery), +  P_REG_RAX); +  mov_reg_mem (P_REG_RAX, +  Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter_struct, catching_eval_jmpbuf)); +  jmp (&label_C); +  LABEL_B; +  /* Zero Pike_interpreter.catching_eval_jmpbuf. */ +  mov_imm_mem(0, +  Pike_interpreter_reg, +  OFFSETOF(Pike_interpreter_struct, catching_eval_jmpbuf)); +  +  LABEL_C; +  /* RBX now contains either the address returned from +  setup_catch_context, or the one from +  handle_caught_exception. */ +  jmp_reg(P_REG_RBX); +  +  upd_pointer(base_addr - 4, PIKE_PC - base_addr);    } -  break; +  return;       /* 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 );
pike.git/src/code/amd64.c:2645:    mov_mem32_reg( fp_reg, OFFSETOF(pike_frame, flags), P_REG_RAX );    and_reg32_imm( P_REG_RAX, PIKE_FRAME_RETURN_POP );    jnz( &label_C );    amd64_call_c_function( low_return );    jmp( &label_D );       LABEL_C;    amd64_call_c_function( low_return_pop );       LABEL_D; + #ifdef MACHINE_CODE_STACK_FRAMES +  /* We know that this is a RETURN_INTERNAL frame, so we must pop +  the C stack. */ +  amd64_pop_internal_c_frame(); + #endif /* MACHINE_CODE_STACK_FRAMES */    fp_reg = -1;    amd64_load_fp_reg();    mov_mem_reg( fp_reg, OFFSETOF(pike_frame, return_addr), P_REG_RAX );    jmp_reg( P_REG_RAX );    }    return;       case F_CLEAR_STRING_SUBTYPE:    ins_debug_instr_prologue(b, 0, 0);    amd64_load_sp_reg();
pike.git/src/code/amd64.c:2666:    P_REG_RAX);    /* NB: We only care about subtype 1! */    cmp_reg32_imm(P_REG_RAX, (1<<16)|PIKE_T_STRING);    jne(&label_A);    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;    return;    } +  +  if (instrs[b].flags & I_RETURN) { + #ifdef MACHINE_CODE_STACK_FRAMES +  amd64_load_fp_reg(); +  /* Load flags prior to calling the C opcode (which typically pops +  the frame in I_RETURN instructions. Note: really mem16, but we +  & with PIKE_FRAME_RETURN_INTERNAL below. */ +  mov_mem32_reg(fp_reg, OFFSETOF(pike_frame, flags), P_REG_RBX); + #endif /* MACHINE_CODE_STACK_FRAMES */ +  } +     amd64_call_c_opcode(addr,flags);       if (instrs[b].flags & I_RETURN) {    LABELS();       if ((b + F_OFFSET) == F_RETURN_IF_TRUE) {    /* Kludge. We must check if the ret addr is    * PC + JUMP_EPILOGUE_SIZE. */    mov_rip_imm_reg(JUMP_EPILOGUE_SIZE, P_REG_RCX);    }    cmp_reg_imm(P_REG_RAX, -1);    jne(&label_A);    amd64_return_from_function();    LABEL_A;       if ((b + F_OFFSET) == F_RETURN_IF_TRUE) {    /* Kludge. We must check if the ret addr is    * orig_addr + JUMP_EPILOGUE_SIZE. */    cmp_reg_reg( P_REG_RAX, P_REG_RCX ); -  je( &label_B ); -  jmp_reg(P_REG_RAX); +  je( &label_C ); +  } +  + #ifdef MACHINE_CODE_STACK_FRAMES +  /* Check if we should pop C stack. The flags word of the frame +  prior to calling the C opcode is loaded into RBX above. */ +  and_reg32_imm(P_REG_RBX, PIKE_FRAME_RETURN_INTERNAL); +  jz( &label_B ); +  amd64_pop_internal_c_frame(); +     LABEL_B; -  + #endif /* MACHINE_CODE_STACK_FRAMES */ +  +  jmp_reg(P_REG_RAX); +  +  LABEL_C;    return;    } -  } +     if (flags & I_JUMP) {    jmp_reg(P_REG_RAX); -  -  if (b + F_OFFSET == F_CATCH) { -  upd_pointer(rel_addr - 4, PIKE_PC - rel_addr); +     }   } - } +       int amd64_ins_f_jump(unsigned int op, int backward_jump)   {    int flags;    void *addr;    int off = op - F_OFFSET;    int ret = -1;    LABELS();      #ifdef PIKE_DEBUG
pike.git/src/code/amd64.c:2813:    shl_reg_imm( P_REG_RAX, 4 );    add_reg_reg( P_REG_RBX, P_REG_RAX );       mov_mem8_reg( sp_reg, -3*sizeof(struct svalue), P_REG_RAX );    cmp_reg_imm( P_REG_RAX,T_SVALUE_PTR);    jne( &label_C );       /* SVALUE_PTR optimization */    mov_mem_reg( sp_reg, -3*sizeof(struct svalue)+8, P_REG_RDX );    push( P_REG_RDX ); +  sub_reg_imm(P_REG_RSP, 8); /* Align on 16 bytes. */    /* Free old value. */    amd64_free_svalue( P_REG_RDX, 0 ); -  +  add_reg_imm(P_REG_RSP, 8);    pop( P_REG_RDX );       /* Assign new value. */    mov_mem_reg( P_REG_RBX, 0, P_REG_RAX );    mov_mem_reg( P_REG_RBX, 8, P_REG_RCX );    mov_reg_mem( P_REG_RAX, P_REG_RDX, 0 );    mov_reg_mem( P_REG_RCX, P_REG_RDX, 8 );       /* inc refs? */    and_reg32_imm( P_REG_RAX, MIN_REF_TYPE );
pike.git/src/code/amd64.c:3190:    amd64_call_c_opcode(instrs[a-F_OFFSET].address,    instrs[a-F_OFFSET].flags);    LABEL_B;    }    return;       case F_MOD_INT:    if( b < 0 )    break;    -  /* FALL_THROUGH */ +  /* FALLTHRU */       case F_DIVIDE_INT:    {    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_sp_reg();       mov_mem8_reg(sp_reg,SVAL(-1).type, P_REG_RAX);    test_reg32(P_REG_RAX);    jnz(&label_A);
pike.git/src/code/amd64.c:3368:    }    if(!b) return;    if( b < 0 )    yyerror(">> with negative constant\n");    break;       case F_SUBTRACT_INT:    case F_ADD_NEG_INT:    b = -b;    -  /* FALL_THROUGH */ +  /* FALLTHRU */       case F_ADD_INT:    {    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_sp_reg();    mov_mem8_reg( sp_reg,SVAL(-1).type, P_REG_RAX );    test_reg32(P_REG_RAX);    jnz( &label_A );    mov_mem_reg(sp_reg, SVAL(-1).value,P_REG_RAX );
pike.git/src/code/amd64.c:3749:    amd64_load_mark_sp_reg();    amd64_load_sp_reg();       mov_mem_reg( mark_sp_reg, -sizeof(struct svalue*), P_REG_RAX );    amd64_add_mark_sp( -1 );    mov_reg_reg( sp_reg, ARG1_REG );    sub_reg_reg( ARG1_REG, P_REG_RAX );    shr_reg_imm( ARG1_REG, 4 );    /* arg1 = (sp_reg - *--mark_sp)/16 (sizeof(svalue)) */    -  /* FALL_THROUGH */ +  /* FALLTHRU */       case F_MARK_CALL_BUILTIN:    if(a == F_MARK_CALL_BUILTIN )    {    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    mov_imm_reg( 0, ARG1_REG );    }    -  /* FALL_THROUGH */ +  /* FALLTHRU */       case F_CALL_BUILTIN1:    if(a == F_CALL_BUILTIN1 )    {    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    mov_imm_reg( 1, ARG1_REG );    }       /* Note: It is not actually possible to do ins_debug_instr_prologue    * here.
pike.git/src/code/amd64.c:3848:    mov_mem_reg( fp_reg, OFFSETOF(pike_frame, locals), P_REG_RAX);    add_reg_imm( P_REG_RAX, b*sizeof(struct svalue));       mov_imm_mem( T_SVALUE_PTR, sp_reg, OFFSETOF(svalue, tu.t.type));    mov_reg_mem( P_REG_RAX, sp_reg, OFFSETOF(svalue,u.lval) );    mov_imm_mem( T_VOID, sp_reg,    OFFSETOF(svalue, tu.t.type)+sizeof(struct svalue));    amd64_add_sp( 2 );    return;    -  case F_PROTECT_STACK: -  ins_debug_instr_prologue(a-F_OFFSET, b, 0); -  amd64_load_fp_reg(); -  mov_imm_mem16(b, fp_reg, OFFSETOF(pike_frame, expendible_offset)); -  return; +     case F_MARK_AT:    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_fp_reg();    amd64_load_mark_sp_reg();    mov_mem_reg(fp_reg, OFFSETOF(pike_frame, locals), ARG1_REG);    if (b) {    add_reg_imm_reg(ARG1_REG, sizeof(struct svalue) * b, ARG1_REG);    }    mov_reg_mem(ARG1_REG, mark_sp_reg, 0x00);    amd64_add_mark_sp( 1 );
pike.git/src/code/amd64.c:3964:    ins_f_byte_with_2_args(F_EXTERNAL, b, c);    return;       case F_CLEAR_N_LOCAL:    {    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, c);    amd64_load_fp_reg();    mov_mem_reg(fp_reg, OFFSETOF(pike_frame, locals), P_REG_RBX);    add_reg_imm(P_REG_RBX, b*sizeof(struct svalue)); -  if( c > 1 ) +  if( c > 1 ) { +  push(P_REG_RBP); +  sub_reg_imm(P_REG_RSP, 8); /* Align on 16 bytes. */    add_reg_imm_reg(P_REG_RBX, c*sizeof(struct svalue), P_REG_RBP ); -  +  }       LABEL_A;    amd64_free_svalue(P_REG_RBX, 0);    mov_imm_mem(PIKE_T_INT, P_REG_RBX, OFFSETOF(svalue, tu.t.type));    mov_imm_mem(0, P_REG_RBX, OFFSETOF(svalue, u.integer));    if( c > 1 )    {    add_reg_imm(P_REG_RBX, sizeof(struct svalue ) );    cmp_reg_reg( P_REG_RBX, P_REG_RBP );    jne(&label_A); -  +  add_reg_imm(P_REG_RSP, 8); +  pop(P_REG_RBP);    }    }    return;       case F_LOCAL_LOCAL_INDEX:    {    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, c);    amd64_load_fp_reg();    mov_mem_reg( fp_reg, OFFSETOF(pike_frame,locals), P_REG_RDX);
pike.git/src/code/amd64.c:4118:    ins_debug_instr_prologue(a-F_OFFSET, b, c);       amd64_get_storage( P_REG_RBX, b );       /* do not assign anything if this object is destructed. */       /* we really only need to redo this check after we have called    some other function. It is sort of hard to know when that    happens while generating the code, however. Simply assigning    the global could in theory actually destruct this object (old -  value includes something with a destroy that calls destruct on +  value includes something with a _destruct that calls destruct on    this object...)       Note that nothing crash if we do the assign. We "just" leak the    variable when the storage is eventually free:d.       The generated code does look sort of silly, however.    */    mov_mem_reg( fp_reg, OFFSETOF(pike_frame,current_object), ARG1_REG );    mov_mem_reg( ARG1_REG, OFFSETOF(object,prog), P_REG_RAX );    test_reg(P_REG_RAX);
pike.git/src/code/amd64.c:4563:    },    /* #5: Bit tests (Opcode 0xba) */    {    NULL, NULL, NULL, NULL,    "bt", "bts", "btr", "btc",    },   };      struct amd64_opcode {    const char *name; -  unsigned INT64 flags; +  UINT64 flags;   };      static struct amd64_opcode amd64_opcodes[4][256] = {    /* Main table. */   {    /* 0x00 */    { "add", RMR8, }, { "add", RMR, }, { "add", RRM8, }, { "add", RRM, },    { "add", ALI8, }, { "add", AI, }, { NULL, 0, }, { NULL, 0, },    { "or", RMR8, }, { "or", RMR, }, { "or", RRM8, }, { "or", RRM, },    { "or", ALI8, }, { "or", AI, }, { NULL, 0, }, { "F", OP_F, },