pike.git / src / code / amd64.c

version» Context lines:

pike.git/src/code/amd64.c:221:   }      static void mov_mem32_reg( enum amd64_reg from_reg, ptrdiff_t offset, enum amd64_reg to_reg )   {    rex( 0, to_reg, 0, from_reg );    low_mov_mem_reg( from_reg, offset, to_reg );   }      static void mov_mem16_reg( enum amd64_reg from_reg, ptrdiff_t offset, enum amd64_reg to_reg )   { -  /* -  Actually doing a 16-bit read seems slower.. -  */ + #if 0    mov_mem32_reg( from_reg, offset, to_reg );    and_reg_imm(to_reg, 0xffff); -  + #else +  rex( 1,to_reg,0,from_reg ); +  /* movzx r/m16 -> r32. This automatically zero-extends the upper 32-bit */ +  opcode( 0xf ); +  opcode( 0xb7 ); +  offset_modrm_sib(offset, to_reg, from_reg ); + #endif   }    -  + static void mov_mem8_reg( enum amd64_reg from_reg, ptrdiff_t offset, enum amd64_reg to_reg ) + { + #if 0 +  mov_mem32_reg( from_reg, offset, to_reg ); +  and_reg_imm(to_reg, 0xff); + #else +  rex( 0,to_reg,0,from_reg ); +  /* movzx r/m8 -> r32. This automatically zero-extends the upper 32-bit */ +  opcode( 0xf ); +  opcode( 0xb6 ); +  offset_modrm_sib(offset, to_reg, from_reg ); + #endif + } +    static void add_reg_imm( enum amd64_reg src, int imm32);      static void shl_reg_imm( enum amd64_reg from_reg, int shift )   {    rex( 1, from_reg, 0, 0 );    if( shift == 1 )    {    opcode( 0xd1 ); /* SAL */    modrm( 3, 4, from_reg );    }    else    {    opcode( 0xc1 );    modrm( 3, 4, from_reg );    ib( shift );    }   }    -  + static void shr_reg_imm( enum amd64_reg from_reg, int shift ) + { +  rex( 1, from_reg, 0, 0 ); +  if( shift == 1 ) +  { +  opcode( 0xd1 ); /* SAR */ +  modrm( 3, 7, from_reg ); +  } +  else +  { +  opcode( 0xc1 ); +  modrm( 3, 7, from_reg ); +  ib( shift ); +  } + } +    static void clear_reg( enum amd64_reg reg )   {    xor_reg_reg( reg, reg );   }      static void neg_reg( enum amd64_reg reg )   {    rex(1,0,0,reg);    opcode(0xf7);    modrm(3,3,reg);
pike.git/src/code/amd64.c:826:   {    mov_imm_reg(value, ARG2_REG);    /* FIXME: Alloc stack space on NT. */   }      static void amd64_add_sp( int num )   {    amd64_load_sp_reg();    add_reg_imm( sp_reg, sizeof(struct svalue)*num);    dirty_regs |= 1 << PIKE_SP_REG; -  flush_dirty_regs(); /* FIXME: Why is this needed? */ +  flush_dirty_regs(); /* FIXME: Need to change LABEL handling to remove this */   }      static void amd64_add_mark_sp( int num )   {    amd64_load_mark_sp_reg();    add_reg_imm( mark_sp_reg, sizeof(struct svalue*)*num);    dirty_regs |= 1 << PIKE_MARK_SP_REG; -  +  flush_dirty_regs(); /* FIXME: Need to change LABEL handling to remove this */   }      /* Note: Uses RAX and RCX internally. reg MUST not be REG_RAX. */   static void amd64_push_svaluep(int reg)   {    LABELS();       amd64_load_sp_reg();    mov_mem_reg(reg, OFFSETOF(svalue, type), REG_RAX);    mov_mem_reg(reg, OFFSETOF(svalue, u.refs), REG_RCX);
pike.git/src/code/amd64.c:864:   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, type));    mov_imm_mem(value, sp_reg, OFFSETOF(svalue, u.integer));    amd64_add_sp( 1 );   }      static void amd64_push_int_reg(enum amd64_reg reg )   { -  if( reg == REG_RCX ) Pike_fatal( "Source clobbered in push_int_reg\n"); +     amd64_load_sp_reg();    mov_imm_mem( PIKE_T_INT, sp_reg, OFFSETOF(svalue, type));    mov_reg_mem( reg, sp_reg, OFFSETOF(svalue, u.integer));    amd64_add_sp( 1 );   }      static void amd64_mark(int offset)   {    amd64_load_sp_reg();    amd64_load_mark_sp_reg();
pike.git/src/code/amd64.c:886:    add_reg_imm_reg(sp_reg, -offset * sizeof(struct svalue), REG_RAX);    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_mem32_reg( src, OFFSETOF(svalue,type), dst); +  mov_mem8_reg( src, OFFSETOF(svalue,type), dst);    and_reg_imm( dst, 0x1f );   }         static void amd64_call_c_function(void *addr)   {    flush_dirty_regs();    call_imm(addr);   }   
pike.git/src/code/amd64.c:933:   }      /* Type already in RAX */   static void amd64_free_svalue_type(enum amd64_reg src, enum amd64_reg type,    int guaranteed_ref )   {    LABELS();    /* if type > MAX_REF_TYPE+1 */    if( src == REG_RAX )    Pike_fatal("Clobbering RAX for free-svalue\n"); +     cmp_reg_imm(type,MAX_REF_TYPE);    jg( &label_A );       /* Load pointer to refs -> RAX */    mov_mem_reg( src, OFFSETOF(svalue, u.refs), REG_RAX);    /* if( !--*RAX ) */    add_mem32_imm( REG_RAX, OFFSETOF(pike_string,refs), -1);    if( !guaranteed_ref )    {    /* We need to see if refs got to 0. */
pike.git/src/code/amd64.c:1234: Inside #if defined(PIKE_DEBUG)
   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;       addr=instrs[b].address; -  switch(b + F_OFFSET) { +  switch(b + F_OFFSET) +  {    case F_DUP:    amd64_load_sp_reg();    ins_debug_instr_prologue(b, 0, 0);    add_reg_imm_reg(sp_reg, -sizeof(struct svalue), REG_R10 );    amd64_push_svaluep( REG_R10 );    return;    -  +  case F_EXIT_CATCH: +  ins_f_byte( F_ESCAPE_CATCH ); +  amd64_load_sp_reg(); +  amd64_push_int( 0, 1 ); +  return; +     case F_ADD_INTS:    {    amd64_load_sp_reg();    ins_debug_instr_prologue(b, 0, 0); -  mov_mem32_reg( sp_reg, -sizeof(struct svalue)*2, REG_RAX ); +  mov_mem8_reg( sp_reg, -sizeof(struct svalue)*2, REG_RAX );    shl_reg_imm( REG_RAX, 8 ); -  mov_mem32_reg( sp_reg,-sizeof(struct svalue), REG_RBX ); - /* and_reg_imm( REG_RBX, 0x1f );*/ +  mov_mem8_reg( sp_reg,-sizeof(struct svalue), REG_RBX ); +  /* and_reg_imm( REG_RBX, 0x1f );*/    add_reg_reg( REG_RAX, REG_RBX ); -  and_reg_imm( REG_RAX, 0x1f1f ); +  /* and_reg_imm( REG_RAX, 0x1f1f ); */    cmp_reg_imm( REG_RAX, (PIKE_T_INT<<8)|PIKE_T_INT );    jne( &label_A );    /* So. Both are actually integers. */    mov_mem_reg( sp_reg,    -sizeof(struct svalue)+OFFSETOF(svalue,u.integer),    REG_RAX );       add_reg_mem( REG_RAX,    sp_reg,    -sizeof(struct svalue)*2+OFFSETOF(svalue,u.integer)    );       jo( &label_A );    amd64_add_sp( -1 ); -  +  mov_imm_mem( PIKE_T_INT,sp_reg, -sizeof(struct svalue));    mov_reg_mem( REG_RAX, sp_reg,    -sizeof(struct svalue)+OFFSETOF(svalue,u.integer));    jmp( &label_B );       LABEL_A;    /* Fallback version */    update_arg1( 2 );    amd64_call_c_opcode( f_add, I_UPDATE_SP );    amd64_load_sp_reg();    LABEL_B;
pike.git/src/code/amd64.c:1316:    }    return;    case F_CATCH:    {    /* Special argument for the F_CATCH instruction. */    addr = inter_return_opcode_F_CATCH;    mov_rip_imm_reg(0, ARG1_REG); /* Address for the POINTER. */    rel_addr = PIKE_PC;    }    break; +  case F_ZERO_TYPE: +  { +  LABELS(); +  amd64_load_sp_reg(); +  mov_mem32_reg( sp_reg, -sizeof(struct svalue), REG_RAX ); +  /* Rax now has type + subtype. */ +  mov_reg_reg( REG_RAX, REG_RBX ); +  and_reg_imm( REG_RAX, 0x1f ); +  cmp_reg_imm( REG_RAX, PIKE_T_INT ); +  jne( &label_A ); +  /* It is an integer. */ +  shr_reg_imm( REG_RBX, 16 ); +  /* subtype in RBX. */ +  mov_imm_mem( PIKE_T_INT, sp_reg, -sizeof(struct svalue) ); +  mov_reg_mem( REG_RBX, sp_reg, +  -sizeof(struct svalue)+OFFSETOF(svalue,u.integer) ); +  jmp( &label_B ); +  LABEL_A; +  /* not an integer. Use C version for simplicitly.. */ +  amd64_call_c_opcode( addr, flags ); +  LABEL_B; +  } +  return;    case F_UNDEFINED:    ins_debug_instr_prologue(b, 0, 0);    amd64_push_int(0, 1);    return;    case F_CONST0:    ins_debug_instr_prologue(b, 0, 0);    amd64_push_int(0, 0);    return;    case F_CONST1:    ins_debug_instr_prologue(b, 0, 0);
pike.git/src/code/amd64.c:1500:    case F_QUICK_BRANCH_WHEN_ZERO:    case F_QUICK_BRANCH_WHEN_NON_ZERO:    START_JUMP();    amd64_load_sp_reg();    amd64_add_sp( -1 );    mov_mem_reg( sp_reg, 8, REG_RAX );    test_reg(REG_RAX);    if( op == F_QUICK_BRANCH_WHEN_ZERO )    return jz_imm_rel32(0);    return jnz_imm_rel32(0); -  +     case F_BRANCH_WHEN_ZERO:    case F_BRANCH_WHEN_NON_ZERO:    START_JUMP();    amd64_load_sp_reg(); -  mov_mem16_reg( sp_reg, -sizeof(struct svalue), REG_RAX ); +  mov_mem8_reg( sp_reg, -sizeof(struct svalue), REG_RAX );    cmp_reg_imm( REG_RAX, PIKE_T_OBJECT );    je( &label_A ); -  +     amd64_add_sp( -1 ); -  mov_mem_reg( sp_reg, 8, REG_RBX ); -  amd64_free_svalue_type( sp_reg, REG_RAX, 0 ); +  cmp_reg_imm( REG_RAX, PIKE_T_INT ); +  /* The add_sp above is not likely to have the zero-flag set +  * after operation (since pike-sp is seldom 0). +  */ +  jne( &label_C ); +  /* integer */ +  mov_mem_reg( sp_reg, OFFSETOF(svalue,u.integer), REG_RBX );    test_reg( REG_RBX );    jmp( &label_B );       LABEL_A; /* It is an object. Use the C version. */    amd64_call_c_opcode(instrs[F_BRANCH_WHEN_ZERO-F_OFFSET].address,    instrs[F_BRANCH_WHEN_ZERO-F_OFFSET].flags ); -  +  amd64_load_sp_reg();    cmp_reg_imm( REG_RAX, -1 ); -  +  jmp( &label_B ); +  LABEL_C; +  /* not int or object. */ +  amd64_free_svalue_type( sp_reg, REG_RAX, 0 ); +  test_reg( sp_reg ); /* not zero. :) */       LABEL_B; /* Branch or not? */    if( op == F_BRANCH_WHEN_ZERO )    return jz_imm_rel32(0);    return jnz_imm_rel32(0); -  +     case F_LOOP:    /* counter in pike_sp-1 */    /* decrement until 0. */    /* if not 0, branch */    /* otherwise, pop */    START_JUMP();    amd64_load_sp_reg();    mov_mem32_reg( sp_reg, -sizeof(struct svalue), REG_RAX );    /* Is it a normal integer? subtype -> 0, type -> PIKE_T_INT */    cmp_reg_imm( REG_RAX, PIKE_T_INT );
pike.git/src/code/amd64.c:1546:       /* if it is, is it 0? */    mov_mem_reg( sp_reg, -sizeof(struct svalue)+8, REG_RAX );    test_reg(REG_RAX);    jz( &label_B ); /* it is. */       add_reg_imm( REG_RAX, -1 );    mov_reg_mem( REG_RAX, sp_reg, -sizeof(struct svalue)+8);    mov_imm_reg( 1, REG_RAX );    /* decremented. Jump -> true. */ +  +  /* This is where we would really like to have two instances of +  * the target returned from this function... +  */    jmp( &label_C );       LABEL_A; /* Not an integer. */    amd64_call_c_opcode(instrs[F_LOOP-F_OFFSET].address,    instrs[F_LOOP-F_OFFSET].flags );    jmp( &label_C );       /* result in RAX */    LABEL_B; /* loop done, inline. Known to be int, and 0 */    amd64_add_sp( -1 );
pike.git/src/code/amd64.c:1685:    case F_ADD_INT:    {    LABELS();    amd64_load_sp_reg();    mov_mem16_reg( sp_reg, -sizeof(struct svalue), REG_RAX );    cmp_reg_imm( REG_RAX,PIKE_T_INT );    jne( &label_A );    mov_mem_reg(sp_reg,    -sizeof(struct svalue)+OFFSETOF(svalue,u.integer),    REG_RAX ); +  test_reg( REG_RAX ); +  jz( &label_C ); +     add_reg_imm( REG_RAX, b );    jo( &label_A ); /* if overflow, use f_add */    mov_reg_mem( REG_RAX,sp_reg,    -sizeof(struct svalue)+OFFSETOF(svalue,u.integer));    jmp(&label_B); /* all done. */       LABEL_A;    amd64_push_int(b,0);    update_arg1(2);    amd64_call_c_opcode( f_add, I_UPDATE_SP );    amd64_load_sp_reg(); -  +  jmp( &label_B ); +  LABEL_C; +  // int, and 0, we need to set it to b and clear subtype +  mov_imm_mem( PIKE_T_INT, sp_reg, -sizeof(struct svalue ) ); +  mov_imm_mem( b, sp_reg, +  -sizeof(struct svalue )+OFFSETOF(svalue,u.integer) );    LABEL_B;    }    return;       case F_NUMBER:    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_push_int(b, 0);    return;    case F_NEG_NUMBER:    ins_debug_instr_prologue(a-F_OFFSET, b, 0);
pike.git/src/code/amd64.c:1809:       case F_SIZEOF_LOCAL:    {    LABELS();    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,locals), ARG1_REG);    add_reg_imm( ARG1_REG, b*sizeof(struct svalue)); - #if 0 +     mov_sval_type( ARG1_REG, REG_RAX );    /* type in RAX, svalue in ARG1 */    cmp_reg_imm( REG_RAX, PIKE_T_ARRAY );    jne( &label_A );    /* It's an array */    /* move arg to point to the array */    mov_mem_reg( ARG1_REG, OFFSETOF(svalue, u.array ), ARG1_REG);    /* load size -> RAX*/    mov_mem32_reg( ARG1_REG,OFFSETOF(array, size), REG_RAX );    jmp( &label_C );    LABEL_A;    cmp_reg_imm( REG_RAX, PIKE_T_STRING );    jne( &label_B );    /* It's a string */    /* move arg to point to the string */    mov_mem_reg( ARG1_REG, OFFSETOF(svalue, u.string ), ARG1_REG);    /* load size ->RAX*/    mov_mem32_reg( ARG1_REG,OFFSETOF(pike_string, len ), REG_RAX );    jmp( &label_C );    LABEL_B; - #endif +     /* It's something else, svalue already in ARG1. */    amd64_call_c_function( pike_sizeof );    amd64_load_sp_reg();    LABEL_C;/* all done, res in RAX */    /* Store result on stack */    amd64_push_int_reg( REG_RAX );    }    return;       case F_GLOBAL:
pike.git/src/code/amd64.c:2007:    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); -  add_reg_imm(mark_sp_reg, sizeof(struct svalue *)); -  dirty_regs |= 1 << mark_sp_reg; -  /* FIXME: Deferred writing of Pike_mark_sp doen't seem to work reliably yet. */ -  if (dirty_regs & (1 << PIKE_MARK_SP_REG)) { -  mov_reg_mem(PIKE_MARK_SP_REG, Pike_interpreter_reg, -  OFFSETOF(Pike_interpreter_struct, mark_stack_pointer)); -  dirty_regs &= ~(1 << PIKE_MARK_SP_REG); -  } +  amd64_add_mark_sp( 1 );    return;    }    update_arg1(b);    ins_f_byte(a);   }      int amd64_ins_f_jump_with_arg(unsigned int op, INT32 a, int backward_jump)   {    LABELS();    if (!(instrs[op - F_OFFSET].flags & I_BRANCH)) return -1;
pike.git/src/code/amd64.c:2036:    switch( op )    {    case F_BRANCH_IF_NOT_LOCAL:    case F_BRANCH_IF_LOCAL:    ins_debug_instr_prologue(op-F_OFFSET, a, 0);    amd64_load_fp_reg();    mov_mem_reg( fp_reg, OFFSETOF(pike_frame, locals), REG_RAX);    add_reg_imm( REG_RAX, a*sizeof(struct svalue));    /* if( type == PIKE_T_OBJECT )    call c version... -  else +  else if( integer )    u.integer -> RAX -  +  else +  1 -> RAX    */    mov_sval_type( REG_RAX, REG_RCX );    cmp_reg_imm( REG_RCX, PIKE_T_OBJECT );    jne( &label_A ); -  +  cmp_reg_imm( REG_RCX, PIKE_T_INT ); +  jne( &label_B ); /* RAX is already true (pointer to local) */       update_arg1(a);    /* Note: Always call IF_LOCAL, the negation is done below. */    amd64_call_c_opcode( instrs[F_BRANCH_IF_LOCAL-F_OFFSET].address,    instrs[F_BRANCH_IF_LOCAL-F_OFFSET].flags );    jmp( &label_B );    LABEL_A;    mov_mem_reg( REG_RAX, OFFSETOF(svalue, u.integer ), REG_RAX );    LABEL_B;    test_reg( REG_RAX );
pike.git/src/code/amd64.c:2075:    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_ADD_LOCAL_INT: +  amd64_load_sp_reg();    case F_ADD_LOCAL_INT_AND_POP:    {    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_fp_reg();    mov_mem_reg( fp_reg, OFFSETOF(pike_frame, locals), ARG1_REG);    add_reg_imm( ARG1_REG, b*sizeof(struct svalue) );       /* arg1 = dst    arg2 = int    */    mov_sval_type( ARG1_REG, REG_RAX );    cmp_reg_imm( REG_RAX, PIKE_T_INT );    jne(&label_A); /* Fallback */ -  +  mov_imm_mem( PIKE_T_INT, ARG1_REG, OFFSETOF(svalue,type));    add_imm_mem( c, ARG1_REG,OFFSETOF(svalue,u.integer));    jno( &label_B);    add_imm_mem( -c, ARG1_REG,OFFSETOF(svalue,u.integer)); -  +  /* Overflow. Use C version */    LABEL_A;    update_arg2(c);    update_arg1(b); -  ins_f_byte(a); /* Will call C version */ +  ins_f_byte(a); +  /* Push already done by C version. */ +  if( a == F_ADD_LOCAL_INT ) +  jmp( &label_C ); +     LABEL_B; -  +  if( a == F_ADD_LOCAL_INT ) +  { +  /* push the local. */ +  /* We know it's an integer (since we did not use the fallback) */ +  mov_mem_reg( ARG1_REG, OFFSETOF(svalue,u.integer), REG_RAX ); +  amd64_push_int_reg( REG_RAX ); +  } +  LABEL_C;    return;    }    case F_ADD_LOCALS_AND_POP:    {    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_fp_reg();    mov_mem_reg( fp_reg, OFFSETOF(pike_frame, locals), ARG1_REG);    add_reg_imm( ARG1_REG, b*sizeof(struct svalue) );    add_reg_imm_reg( ARG1_REG,(c-b)*sizeof(struct svalue), ARG2_REG );