Bladeren bron

slight progress for x64 jit

Nicolas Cannasse 8 jaren geleden
bovenliggende
commit
4da118f316
3 gewijzigde bestanden met toevoegingen van 77 en 25 verwijderingen
  1. 3 0
      src/hl.h
  2. 71 25
      src/jit.c
  3. 3 0
      src/std/fun.c

+ 3 - 0
src/hl.h

@@ -382,6 +382,9 @@ typedef struct _vclosure {
 	hl_type *t;
 	void *fun;
 	int hasValue;
+#	ifdef HL_64
+	int __pad;
+#	endif
 	void *value;
 } vclosure;
 

+ 71 - 25
src/jit.c

@@ -263,6 +263,7 @@ struct jit_ctx {
 	int functionPos;
 	int allocOffset;
 	int currentPos;
+	int nativeArgsCount;
 	unsigned char *startBuf;
 	hl_module *m;
 	hl_function *f;
@@ -389,6 +390,7 @@ typedef struct {
 #define GET_RM(op)	(((op) >> ((op) < 0 ? 24 : 8)) & 15)
 #define SBYTE(op) ((op) << 16)
 #define LONG_OP(op)	((op) | 0x80000000)
+#define OP16(op)	LONG_OP((op) | 0x40000000)
 #define LONG_RM(op,id)	LONG_OP(op | (((id) + 1) << 24))
 
 static opform OP_FORMS[_CPU_LAST] = {
@@ -446,8 +448,8 @@ static opform OP_FORMS[_CPU_LAST] = {
 	{ "MOV8", 0x8A, 0x88, 0, 0xB0, RM(0xC6,0) },
 	{ "CMP8", 0x3A, 0x38, 0, RM(0x80,7) },
 	{ "TEST8", 0x84, 0x84, RM(0xF6,0) },
-	{ "MOV16", LONG_OP(0x668B), LONG_OP(0x6689), LONG_OP(0x66B8) },
-	{ "CMP16", LONG_OP(0x663B), LONG_OP(0x6639) },
+	{ "MOV16", OP16(0x668B), OP16(0x6689), OP16(0x66B8) },
+	{ "CMP16", OP16(0x663B), OP16(0x6639) },
 };
 
 #ifdef OP_LOG
@@ -524,7 +526,22 @@ static void log_op( jit_ctx *ctx, CpuOp o, preg *a, preg *b, bool mode64 ) {
 #	define REX()
 #endif
 
-#define	OP(b)	if( (b) & 0xFF0000 ) {  B((b)>>16); if( r64 ) B(r64 | 0x40); B((b)>>8); B(b); } else { REX(); if( (b) < 0 ) B((b)>>8); B(b); }
+#define	OP(b)	\
+	if( (b) & 0xFF0000 ) { \
+		B((b)>>16); \
+		if( r64 ) B(r64 | 0x40); \
+		B((b)>>8); \
+		B(b); \
+	} else { \
+		if( (b) & 0x40000000 ) { \
+			B((b)>>8); \
+			REX(); \
+		} else {\
+			REX(); \
+			if( (b) < 0 ) B((b)>>8); \
+		}\
+		B(b); \
+	}
 
 static void op( jit_ctx *ctx, CpuOp o, preg *a, preg *b, bool mode64 ) {
 	opform *f = &OP_FORMS[o];
@@ -2131,33 +2148,58 @@ static vclosure *alloc_static_closure( jit_ctx *ctx, int fid ) {
 	return c;
 }
 
+static int begin_native_call( jit_ctx *ctx, int nargs ) {
+	ctx->nativeArgsCount = nargs;
+	return pad_before_call(ctx, IS_64 ? 0 : nargs * HL_WSIZE);
+}
+
+static preg *alloc_native_arg( jit_ctx *ctx ) {
+#	ifdef HL_64
+	preg *r = REG_AT(CALL_REGS[ctx->nativeArgsCount - 1]);
+	scratch(r);
+	return r;
+#	else
+	return alloc_reg(ctx, RCPU);
+#	endif
+}
+
+static void set_native_arg( jit_ctx *ctx, preg *r ) {
+#	ifdef HL_64
+	preg *target = REG_AT(CALL_REGS[--ctx->nativeArgsCount]);
+	if( target != r ) {
+		op64(ctx, MOV, target, r);
+		scratch(target);
+	}
+#	else
+	op32(ctx,PUSH,r,UNUSED);
+#	endif
+}
+
 static void make_dyn_cast( jit_ctx *ctx, vreg *dst, vreg *v ) {
 	int size;
 	preg p;
-#ifdef HL_64
-	jit_error("TODO");
-#else
+	preg *tmp;
 	switch( dst->t->kind ) {
 	case HF32:
 	case HF64:
-		size = pad_before_call(ctx, HL_WSIZE*2);
-		op32(ctx,PUSH,pconst64(&p,(int_val)v->t),UNUSED);
+		size = begin_native_call(ctx, 2);
+		set_native_arg(ctx, pconst64(&p,(int_val)v->t));
 		break;
 	default:
-		size = pad_before_call(ctx, HL_WSIZE*3);
-		op32(ctx,PUSH,pconst64(&p,(int_val)dst->t),UNUSED);
-		op32(ctx,PUSH,pconst64(&p,(int_val)v->t),UNUSED);
+		size = begin_native_call(ctx, 3);
+		set_native_arg(ctx, pconst64(&p,(int_val)dst->t));
+		set_native_arg(ctx, pconst64(&p,(int_val)v->t));
 		break;
 	}
-	op32(ctx,MOV,PEAX,REG_AT(Ebp));
+	tmp = alloc_native_arg(ctx);
+	op64(ctx,MOV,tmp,REG_AT(Ebp));
 	if( v->stackPos >= 0 )
-		op32(ctx,ADD,PEAX,pconst(&p,v->stackPos));
+		op32(ctx,ADD,tmp,pconst(&p,v->stackPos));
 	else
-		op32(ctx,SUB,PEAX,pconst(&p,-v->stackPos));
-	op32(ctx,PUSH,PEAX,UNUSED);
+		op32(ctx,SUB,tmp,pconst(&p,-v->stackPos));
+	set_native_arg(ctx,tmp);
 	call_native(ctx,get_dyncast(dst->t),size);
 	store_result(ctx, dst);
-#endif
 }
 
 int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
@@ -2332,7 +2374,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 		case OJNull:
 			{
 				preg *r = alloc_cpu(ctx, dst, true);
-				op32(ctx, dst->t->kind == HBOOL ? TEST8 : TEST, r, r);
+				op64(ctx, dst->t->kind == HBOOL ? TEST8 : TEST, r, r);
 				XJump( o->op == OJFalse || o->op == OJNull ? JZero : JNotZero,jump);
 				register_jump(ctx,jump,(opCount + 1) + o->p2);
 			}
@@ -2602,11 +2644,15 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 						jit_error("TODO");
 					}
 				}
+#				ifdef HL_64
+				jit_error("TODO");
+#				else
 				size = pad_before_call(ctx,HL_WSIZE*2 + sizeof(int) + offset);
 				op64(ctx,PUSH,pconst(&p,o->p3),UNUSED);
 				op64(ctx,PUSH,r,UNUSED);
 				op64(ctx,PUSH,alloc_cpu(ctx,ra,true),UNUSED);
 				call_native(ctx,hl_dyn_call,size);
+#				endif
 				if( dst->t->kind != HVOID ) {
 					store(ctx,dst,PEAX,true);
 					make_dyn_cast(ctx,dst,dst);
@@ -2616,8 +2662,8 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				// ASM for  if( c->hasValue ) c->fun(value,args) else c->fun(args)
 				preg *r = alloc_cpu(ctx,ra,true);
 				preg *tmp = alloc_reg(ctx, RCPU);
-				op64(ctx,MOV,tmp,pmem(&p,r->id,HL_WSIZE*2));
-				op64(ctx,TEST,tmp,tmp);
+				op32(ctx,MOV,tmp,pmem(&p,r->id,HL_WSIZE*2));
+				op32(ctx,TEST,tmp,tmp);
 				scratch(tmp);
 				XJump_small(JNotZero,jhasvalue);
 				save_regs(ctx);
@@ -2627,15 +2673,11 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				op64(ctx,ADD,PESP,pconst(&p,size));
 				XJump_small(JAlways,jend);
 				patch_jump(ctx,jhasvalue);
-#				ifdef HL_64
-				jit_error("TODO");
-#				else
 				restore_regs(ctx);
-				size = prepare_call_args(ctx,o->p3,o->extra,ctx->vregs,false,4);
+				size = prepare_call_args(ctx,o->p3,o->extra,ctx->vregs,false,HL_WSIZE);
 				if( r->holds != ra ) r = alloc_cpu(ctx, ra, true);
 				op64(ctx, PUSH,pmem(&p,r->id,HL_WSIZE*3),UNUSED); // push closure value
 				op64(ctx, CALL, pmem(&p,r->id,HL_WSIZE), UNUSED);
-#				endif
 				discard_regs(ctx,false);
 				op64(ctx,ADD,PESP,pconst(&p,size));
 				patch_jump(ctx,jend);
@@ -2839,6 +2881,9 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 
 					jit_buf(ctx);
 
+#					ifdef HL_64
+					jit_error("TODO");
+#					else
 					size = pad_before_call(ctx,HL_WSIZE*5);
 
 					if( !need_dyn )
@@ -2856,6 +2901,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 					op64(ctx,PUSH,pmem(&p,v->id,HL_WSIZE),UNUSED); // o->value
 
 					call_native(ctx,hl_dyn_call_obj,size + paramsSize);
+#					endif
 					if( need_dyn ) {
 						if( IS_FLOAT(dst) )
 							jit_error("TODO");
@@ -2938,7 +2984,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				preg *base = alloc_cpu(ctx, dst, true);
 				preg *offset = alloc_cpu(ctx, ra, true);
 				preg *value = alloc_cpu(ctx, rb, true);
-				op32(ctx,MOV16,pmem2(&p,base->id,offset->id,1,0),value);
+				op64(ctx,MOV16,pmem2(&p,base->id,offset->id,1,0),value);
 			}
 			break;
 		case OSetMem:

+ 3 - 0
src/std/fun.c

@@ -53,6 +53,9 @@ HL_PRIM vclosure *hl_alloc_closure_ptr( hl_type *fullt, void *fvalue, void *v )
 	c->t = t;
 	c->fun = fvalue;
 	c->hasValue = 1;
+#	ifdef HL_64
+	c->__pad = 0;
+#	endif
 	c->value = v;
 	return c;
 }