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 );