示例#1
0
void syn_memsetw( struct machine_ops* mop, struct emitter* e, struct machine* m, operand d, operand v, operand size ){
	operand iter = OP_TARGETREG( acquire_temp( mop, e, m ) );			
	operand dst = OP_TARGETREG( acquire_temp( mop, e, m ) );

	// init iterator
	mop->move( e, m, iter, OP_TARGETIMMED( 0 ) );
	mop->move( e, m, dst, d );
	
	// start loop 
	e->ops->label_local( e, 0 );
	mop->beq( e, m, iter, size, LBL_NEXT( 0 ) );  

	// copy 
	mop->move( e, m, OP_TARGETDADDR( dst.reg, 0 ), v );
	
	// update pointers 
	mop->add( e, m, dst, dst, OP_TARGETIMMED( 4 ) );
	
	// update iterator
	mop->add( e, m, iter, iter, OP_TARGETIMMED( 1 ) );
	
	mop->b( e, m, LBL_PREV( 0 ) );
	e->ops->label_local( e, 0 );
	
	release_tempn( mop, e, m, 2 );
}
示例#2
0
// this function could be inline
void syn_memcpyw( struct machine_ops* mop, struct emitter* e, struct machine* m, operand d, operand s, operand size ){
	operand iter = OP_TARGETREG( acquire_temp( mop, e, m ) );			
	operand src = OP_TARGETREG( acquire_temp( mop, e, m ) );
	operand dst = OP_TARGETREG( acquire_temp( mop, e, m ) );

	// init iterator
	mop->move( e, m, iter, OP_TARGETIMMED( 0 ) );
	mop->move( e, m, src, s );
	mop->move( e, m, dst, d );
	
	// start loop 
	e->ops->label_local( e, 0 );
	mop->beq( e, m, iter, size, LBL_NEXT( 0 ) );  

	// copy 
	mop->move( e, m, OP_TARGETDADDR( dst.reg, 0 ), OP_TARGETDADDR( src.reg, 0 ) );
	
	// update pointers 
	mop->add( e, m, dst, dst, OP_TARGETIMMED( -4 ) );	// TODO: this is incorrect in general but correct for copyargs
	mop->add( e, m, src, src, OP_TARGETIMMED( -4 ) ); 
	
	// update iterator
	mop->add( e, m, iter, iter, OP_TARGETIMMED( 1 ) );
	
	mop->b( e, m, LBL_PREV( 0 ) );
	e->ops->label_local( e, 0 );
	
	release_tempn( mop, e, m, 3 );
}
示例#3
0
void jinit_cpy_arg_res( struct JFunc* jf, struct machine_ops* mop, struct emitter* e, struct machine* m ){
	operand rargs[ RA_SIZE ];
	prefer_nontemp_acquire_reg( mop, e, m, RA_SIZE, rargs );

	syn_min( mop, e, m, rargs[ RA_EXIST ], rargs[ RA_EXIST ], rargs[ RA_EXPECT ] );
	
	// init iterator 
	operand iter = OP_TARGETREG( acquire_temp( mop, e, m ) );			
	mop->move( e, m, iter, OP_TARGETIMMED( 0 ) );
	
	do_copying( mop, e, m, iter, rargs[ RA_EXIST ], rargs[ RA_DST ], rargs[ RA_SRC ] );
	
	/* 
	* TODO: Below logic is incorrect the first is most likely to get spilled. So change enum order. BUT 
	* then you have to think about prefer saved reg and the order there.
	* TODO: add error prefer_nontemps to error when not all live simultenously 
	*
	* RA_EXPECT is last register therefore its the most likely to be spilled. So to stop repeat
	* spill/unspill move it to exist.
	*/
	mop->move( e, m, rargs[ RA_SIZE ], rargs[ RA_EXIST ] );
	do_nilling( mop, e, m, iter, rargs[ RA_EXIST ], rargs[ RA_DST ] );

	release_temp( mop, e, m );	
	prefer_nontemp_release_reg( mop, e, m, RA_SIZE );

	mop->ret( e, m );
}
示例#4
0
/* Grab non temps first then temps */
static void prefer_nontemp_acquire_reg( struct machine_ops* mop, struct emitter* e, struct machine* m, 
					int n, operand reg[n] ){
	// must fit into registers only
	assert( n <= m->nr_reg );

	const int nr_temps = m->nr_temp_regs;
	const int nr_nontemps = m->nr_reg - nr_temps;

	for( int i = 0; i < n; i++ ){
		if( i < nr_nontemps )
			reg[i] = OP_TARGETREG( m->reg[ nr_temps + i ] );
		else
			reg[i] = OP_TARGETREG( acquire_temp( mop, e, m ) );	// ( i - nr_nontemps );	
	}

	// disable spill
	disable_spill( m );
}
示例#5
0
void mips_b( struct emitter* me, struct machine* m, label l ){
	
	if( !ISL_ABS( l ) ){
		EMIT( MI_B( mips_branch( me, l ) ) );
	} else if ( ISL_ABSDIRECT( l ) ){	// TODO: make sure within 256MB region by calling MI_J_SAFE
		EMIT( MI_J( l.abs.k ) );
	} else if ( ISO_REG( l.abs ) ) {
		EMIT( MI_JR( l.abs.reg ) );
	} else { 
		assert( ISO_DADDR( l.abs ) );
		operand t = OP_TARGETREG( acquire_temp( _MOP, me, m ) );
		move( me, m, t, l.abs );
		EMIT( MI_JR( t.reg ) );	
		RELEASE_OR_NOP( me, m );
		return;
	}

	// delay slot
	EMIT( MI_NOP() );
}
示例#6
0
static lua_Number ljc_relational( lua_Number st, lua_Number sv
					, lua_Number tt, lua_Number tv
					, int op ) {
	assert( !( st == LUA_TNUMBER && tt == LUA_TNUMBER ) );
	
	struct TValue s = { .t = st, .v = (union Value)sv };
	struct TValue t = { .t = tt, .v = (union Value)tv };
	
	switch( op ){
		case REL_LT:
			return do_lt( &s, &t ); 
		case REL_LEQ:
			return do_leq( &s, &t );
		case REL_EQ:
			return do_eq( &s, &t );
		default:
			assert( false );	
	}
}


typedef void (*arch_rel)( struct emitter*, struct machine*
					, operand, operand, label );

static void emit_relational( struct emitter *me, struct machine_ops *mop
					, struct frame* f 
					, loperand s, loperand t
					, arch_rel ar, int op
					, bool expect ){

	vreg_operand os = loperand_to_operand( f, s ),
			ot = loperand_to_operand( f, t );

	unsigned int pc = me->ops->pc( me ) + 2;
	label l = LBL_PC( pc );

	// determine if coercion is required 
	operand tag = OP_TARGETREG( acquire_temp( mop, me, f->m ) );
	mop->bor( me, f->m, tag, os.type, ot.type );
	mop->beq( me, f->m, tag, OP_TARGETIMMED( 0 ), LBL_NEXT( 0 ) );

	// do coercion 
	mop->call_static_cfn( me, f, (uintptr_t)&ljc_relational
					, &tag, 5, os.type, os.value 
					, ot.type, ot.value
					, OP_TARGETIMMED( op ) ); 
	mop->beq( me, f->m, tag, OP_TARGETIMMED( expect ), l );
	mop->b( me, f->m, LBL_NEXT( 1 ) );	

	// do primitive relational  
	me->ops->label_local( me, 0 );
	ar( me, f->m, os.value, ot.value, l );
	me->ops->label_local( me, 1 );
	

	release_temp( mop, me, f->m );	

	return;
}

void emit_jmp( struct emitter** mce, struct machine_ops* mop
					, struct frame *f
					, loperand a
					, int offset ){
	assert( a.islocal );

	// if not zero then any upvalues below the vreg need to be closed.
	if( a.index > 0 ){
		vreg_operand op = vreg_to_operand( f, a.index + 1, true );
		operand base = OP_TARGETREG( acquire_temp( mop, REF, f->m ) );
		address_of( mop, REF, f->m, base, op.type );  
		mop->call_static_cfn( REF, f, (uintptr_t)&closure_close, NULL
				, 1
				, base ); 
		release_temp( mop, REF, f->m ); 
	}
	
	unsigned int pc = (int)REF->ops->pc( REF ) + offset + 1;
	mop->b( REF, f->m, LBL_PC( pc ) ); 
}