void syn_max( struct machine_ops* mop, struct emitter* e, struct machine* m, operand d, operand s, operand t ){ mop->blt( e, m, s, t, LBL_NEXT( 0 ) ); mop->move( e, m, d, t ); mop->b( e, m, LBL_NEXT( 1 ) ); e->ops->label_local( e, 0 ); mop->move( e, m, d, s ); e->ops->label_local( e, 1 ); }
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 ); }
// 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 ); }
static void do_nilling( struct machine_ops* mop, struct emitter* e, struct machine* m, operand iter, operand limit, operand dst ){ // start loop e->ops->label_local( e, 0 ); mop->beq( e, m, iter, limit, LBL_NEXT( 0 ) ); // TODO: bgt is equiv to beq so swap? // copy mop->move( e, m, OP_TARGETDADDR( dst.reg, -4 ), OP_TARGETIMMED( LUA_TNIL ) ); // update pointers mop->add( e, m, dst, dst, OP_TARGETIMMED( -8 ) ); // update iterator mop->add( e, m, iter, iter, OP_TARGETIMMED( 1 ) ); mop->b( e, m, LBL_PREV( 0 ) ); e->ops->label_local( e, 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 ) ); }