pike.git / src / code / amd64.c

version» Context lines:

pike.git/src/code/amd64.c:6:   #include "constants.h"   #include "object.h"   #include "builtin_functions.h"         /* Register encodings */   enum amd64_reg {REG_RAX = 0, REG_RBX = 3, REG_RCX = 1, REG_RDX = 2,    REG_RSP = 4, REG_RBP = 5, REG_RSI = 6, REG_RDI = 7,    REG_R8 = 8, REG_R9 = 9, REG_R10 = 10, REG_R11 = 11,    REG_R12 = 12, REG_R13 = 13, REG_R14 = 14, REG_R15 = 15, -  REG_INVALID = -1}; +  REG_INVALID = -1,    -  +  REG_XMM0 = 0, REG_XMM1 = 1, REG_XMM2 = 2, REG_XMM3 = 3, +  REG_XMM4 = 4, REG_XMM5 = 5, REG_XMM6 = 6, REG_XMM7 = 7, +  REG_XMM8 = 8, REG_XMM9 = 9, REG_XMM10=10, REG_XMM11=11, +  REG_XMM12=12, REG_XMM13=13, REG_XMM14=14, REG_XMM15=15, +  }; +    /* We reserve register r12 and above (as well as RSP, RBP and RBX). */   #define REG_BITMASK ((1 << REG_MAX) - 1)   #define REG_RESERVED (REG_RSP|REG_RBP|REG_RBX)   #define REG_MAX REG_R12   #define PIKE_MARK_SP_REG REG_R12   #define PIKE_SP_REG REG_R13   #define PIKE_FP_REG REG_R14   #define Pike_interpreter_reg REG_R15      #ifdef __NT__
pike.git/src/code/amd64.c:54:   static void label( struct label *l )   {    int i;    if (l->addr >= 0) Pike_fatal("Label reused.\n");    for( i=0; i<l->n_label_uses; i++ )    {    int dist = PIKE_PC - (l->offset[i] + 1);    if( dist > 0x7f || dist < -0x80 )    Pike_fatal("Branch too far\n");    Pike_compiler->new_program->program[l->offset[i]] = dist; -  /* fprintf( stderr, "assigning label @%x[%02x >%02x< %02x] -> %d\n", */ -  /* l->offset[i], */ -  /* Pike_compiler->new_program->program[l->offset[i]-1], */ -  /* Pike_compiler->new_program->program[l->offset[i]], */ -  /* Pike_compiler->new_program->program[l->offset[i]+1], */ -  /* dist ); */ +     }    l->n_label_uses = 0;    l->addr = PIKE_PC;   }      static void ib( char x )   {    add_to_program( x );   }   
pike.git/src/code/amd64.c:371:    }    else    {    rex(1,0,0,reg);    opcode( 0xc7 ); /* mov imm32 -> reg/m 64, SE*/    modrm( 3,0,reg );    id( (int)imm );    }   }    + static void mov_mem128_reg( enum amd64_reg from_reg, int offset, enum amd64_reg to_reg ) + { +  if( from_reg > 7 ) +  Pike_fatal("Not supported\n"); +  rex(0,to_reg,0,from_reg); +  opcode( 0x66 ); +  opcode( 0x0f ); +  opcode( 0x6f ); /* MOVDQA xmm,m128 */ +  offset_modrm_sib( offset, to_reg, from_reg ); + } +  + static void mov_reg_mem128( enum amd64_reg from_reg, enum amd64_reg to_reg, int offset ) + { +  if( from_reg > 7 ) +  Pike_fatal("Not supported\n"); +  rex(0,from_reg,0,to_reg); +  opcode( 0x66 ); +  opcode( 0x0f ); +  opcode( 0x7f ); /* MOVDQA m128,xmm */ +  offset_modrm_sib( offset, from_reg, to_reg ); + } +    static void low_mov_reg_mem(enum amd64_reg from_reg, enum amd64_reg to_reg, ptrdiff_t offset )   {    opcode( 0x89 );    offset_modrm_sib( offset, from_reg, to_reg );   }      static void mov_reg_mem( enum amd64_reg from_reg, enum amd64_reg to_reg, ptrdiff_t offset )   {    rex(1, from_reg, 0, to_reg );    low_mov_reg_mem( from_reg, to_reg, offset );
pike.git/src/code/amd64.c:1014:    mov_reg_mem(REG_RAX, mark_sp_reg, 0);    } else {    mov_reg_mem(sp_reg, mark_sp_reg, 0);    }    amd64_add_mark_sp( 1 );   }      static void mov_sval_type(enum amd64_reg src, enum amd64_reg dst )   {    mov_mem8_reg( src, OFFSETOF(svalue,type), dst); -  and_reg32_imm( dst, 0x1f ); + /* and_reg32_imm( dst, 0x1f );*/   }         static void amd64_call_c_function(void *addr)   {    flush_dirty_regs();    call_imm(addr);   }      static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref )
pike.git/src/code/amd64.c:1248:   static void amd64_call_c_opcode(void *addr, int flags)   {    sync_registers(flags);    call_imm( addr );   }         #ifdef PIKE_DEBUG   static void ins_debug_instr_prologue (PIKE_INSTR_T instr, INT32 arg1, INT32 arg2)   { -  return; +     int flags = instrs[instr].flags;    -  + /* For now: It is very hard to read the disassembled source when +  this is inserted */ +  if( !d_flag ) +  return; +     maybe_update_pc();       if (flags & I_HASARG2)    mov_imm_reg(arg2, ARG3_REG);    if (flags & I_HASARG)    mov_imm_reg(arg1, ARG2_REG);    mov_imm_reg(instr, ARG1_REG);       if (flags & I_HASARG2)    amd64_call_c_function (simple_debug_instr_prologue_2);
pike.git/src/code/amd64.c:1581:    update_arg1( 2 );    amd64_call_c_opcode( f_add, I_UPDATE_SP );    amd64_load_sp_reg();    LABEL_B;    }    return;       case F_SWAP:    /*    pike_sp[-1] = pike_sp[-2] -  -  FIXME: Can be changed to -  use movlq (128-bit mov, sse2) +     */    amd64_load_sp_reg(); -  +  add_reg_imm_reg( sp_reg, -2*sizeof(struct svalue), REG_RCX ); +  mov_mem128_reg( REG_RCX, 0, REG_XMM0 ); +  mov_mem128_reg( REG_RCX, 16, REG_XMM1 ); +  mov_reg_mem128( REG_XMM1, REG_RCX, 0 ); +  mov_reg_mem128( REG_XMM0, REG_RCX, 16 ); + #if 0    add_reg_imm_reg( sp_reg, -2*sizeof(struct svalue), REG_R10);    mov_mem_reg( REG_R10, 0, REG_RAX );    mov_mem_reg( REG_R10, 8, REG_RCX );    mov_mem_reg( REG_R10,16, REG_R8 );    mov_mem_reg( REG_R10,24, REG_R9 );    /* load done. */    mov_reg_mem(REG_R8, REG_R10,0);    mov_reg_mem(REG_R9, REG_R10,8);    mov_reg_mem(REG_RAX, REG_R10,sizeof(struct svalue));    mov_reg_mem(REG_RCX, REG_R10,8+sizeof(struct svalue));    /* save done. */ -  + #endif    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;
pike.git/src/code/amd64.c:1706:    amd64_pop_mark();    mov_mem_reg(mark_sp_reg, 0, REG_RBX);    jmp(&label_A);    LABEL_B;    amd64_add_sp( -1 );    amd64_free_svalue( sp_reg, 0 );    LABEL_A;    cmp_reg_reg(REG_RBX, sp_reg);    jl(&label_B);    return; - #ifndef PIKE_DEBUG +     /* If we are compiling with debug, F_RETURN does extra checks */ -  +     case F_RETURN: - #endif +     case F_DUMB_RETURN:    {    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), REG_RAX );    and_reg_imm( REG_RAX, PIKE_FRAME_RETURN_INTERNAL);    jnz( &label_A );    /* So, it is just a normal return. */    LABEL_B;
pike.git/src/code/amd64.c:1752:    REG_RAX);    /* NB: We only care about subtype 1! */    cmp_reg32_imm(REG_RAX, (1<<16)|PIKE_T_STRING);    jne(&label_A);    and_reg_imm(REG_RAX, 0x1f);    mov_reg_mem32(REG_RAX,    sp_reg, OFFSETOF(svalue, type) - sizeof(struct svalue));    LABEL_A;    return;    } -  +     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, REG_RCX);    }
pike.git/src/code/amd64.c:1975:    START_JUMP();    add_to_program(0xe9);    ret=DO_NOT_WARN( (INT32) PIKE_PC );    PUSH_INT(0);    return ret;    }       maybe_update_pc();    addr=instrs[off].address;    amd64_call_c_opcode(addr, flags); +     amd64_load_sp_reg();    test_reg(REG_RAX);       if (backward_jump) {    INT32 skip;    add_to_program (0x74); /* jz rel8 */    add_to_program (0); /* Bytes to skip. */    skip = (INT32)PIKE_PC;    amd64_ins_branch_check_threads_etc();    /* amd64_call_c_function (branch_check_threads_etc); */
pike.git/src/code/amd64.c:2293:    case F_DEC_LOCAL:    ins_f_byte_with_arg(F_DEC_LOCAL_AND_POP, b);    ins_f_byte_with_arg(F_LOCAL, b);    return;       case F_POST_DEC_LOCAL:    ins_f_byte_with_arg(F_LOCAL, b);    ins_f_byte_with_arg(F_DEC_LOCAL_AND_POP, b);    return;    +  case F_CALL_BUILTIN_AND_POP: +  ins_f_byte_with_arg( F_CALL_BUILTIN, b ); +  ins_f_byte( F_POP_VALUE ); +  return; +  +  case F_MARK_CALL_BUILTIN_AND_RETURN: +  ins_f_byte_with_arg( F_MARK_CALL_BUILTIN, b ); +  ins_f_byte( F_DUMB_RETURN ); +  return; +  +  case F_MARK_CALL_BUILTIN_AND_POP: +  ins_f_byte_with_arg( F_MARK_CALL_BUILTIN, b ); +  ins_f_byte( F_POP_VALUE ); +  return; +  +  case F_CALL_BUILTIN1_AND_POP: +  ins_f_byte_with_arg( F_CALL_BUILTIN1, b ); +  ins_f_byte( F_POP_VALUE ); +  return; +  +  case F_CALL_BUILTIN_AND_RETURN: +  ins_f_byte_with_arg( F_CALL_BUILTIN, b ); +  ins_f_byte( F_DUMB_RETURN ); +  return; +  +  case F_CALL_BUILTIN: +  ins_debug_instr_prologue(a-F_OFFSET, b, 0); +  +  amd64_load_mark_sp_reg(); +  amd64_load_sp_reg(); +  +  mov_mem_reg( mark_sp_reg, -sizeof(struct svalue*), REG_RAX ); +  amd64_add_mark_sp( -1 ); +  mov_reg_reg( sp_reg, ARG1_REG ); +  sub_reg_reg( ARG1_REG, REG_RAX ); +  shr_reg_imm( ARG1_REG, 4 ); +  /* arg1 = (sp_reg - *--mark_sp)/16 (sizeof(svalue)) */ +  +  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 ); +  } +  +  case F_CALL_BUILTIN1: +  if(a == F_CALL_BUILTIN1 ) +  { +  ins_debug_instr_prologue(a-F_OFFSET, b, 0); +  mov_imm_reg( 1, ARG1_REG ); +  } +  /* Get function pointer */ + #if 0 +  amd64_load_fp_reg(); +  /* Ok.. This is.. interresting. +  Let's trust that the efun really is constant, ok? +  */ +  mov_mem_reg( fp_reg, OFFSETOF(pike_frame,context), REG_RAX ); +  mov_mem_reg( REG_RAX, OFFSETOF(inherit,prog), REG_RAX ); +  mov_mem_reg( REG_RAX, OFFSETOF(program,constants), REG_RAX ); +  add_reg_imm( REG_RAX, b*sizeof(struct program_constant) + +  OFFSETOF(program_constant,sval) ); +  mov_mem_reg( REG_RAX, OFFSETOF( svalue, u.efun ), REG_RAX ); +  mov_mem_reg( REG_RAX, OFFSETOF( callable, function), REG_RAX ); +  call_reg( REG_RAX ); +  sp_reg = -1; + #else +  amd64_call_c_opcode(Pike_compiler->new_program->constants[b].sval.u.efun->function, +  I_UPDATE_SP); + #endif +  return; +     case F_CONSTANT:    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_fp_reg();    amd64_load_sp_reg();    mov_mem_reg( fp_reg, OFFSETOF(pike_frame,context), REG_RCX );    mov_mem_reg( REG_RCX, OFFSETOF(inherit,prog), REG_RCX );    mov_mem_reg( REG_RCX, OFFSETOF(program,constants), REG_RCX );    add_reg_imm( REG_RCX, b*sizeof(struct program_constant) +    OFFSETOF(program_constant,sval) );    amd64_push_svaluep( REG_RCX );