Ver código fonte

more x64 support

Nicolas Cannasse 8 anos atrás
pai
commit
724d688bbc
1 arquivos alterados com 106 adições e 12 exclusões
  1. 106 12
      src/jit.c

+ 106 - 12
src/jit.c

@@ -186,7 +186,8 @@ typedef enum {
 	RCONST = 3,
 	RADDR = 4,
 	RMEM = 5,
-	RUNUSED = 6
+	RUNUSED = 6,
+	RCPU_CALL = 1 | 8
 } preg_kind;
 
 typedef struct {
@@ -330,11 +331,14 @@ static preg *pconst64( preg *r, int_val c ) {
 #endif
 }
 
+#ifndef HL_64
+// it is not possible to access direct 64 bit address in x86-64
 static preg *paddr( preg *r, void *p ) {
 	r->kind = RADDR;
 	r->holds = (vreg*)p;
 	return r;
 }
+#endif
 
 static void save_regs( jit_ctx *ctx ) {
 	int i;
@@ -865,11 +869,26 @@ static void patch_jump_to( jit_ctx *ctx, int p, int target ) {
 	}
 }
 
+static bool is_call_reg( preg *p ) {
+#	ifdef HL_64
+	int i;
+	if( p->kind == RFPU )
+		return p->id < CALL_NREGS;
+	for(i=0;i<CALL_NREGS;i++)
+		if( p->kind == RCPU && p->id == CALL_REGS[i] )
+			return true;
+	return false;
+#	else
+	return false;
+#	endif
+}
+
 static preg *alloc_reg( jit_ctx *ctx, preg_kind k ) {
 	int i;
 	preg *p;
 	switch( k ) {
 	case RCPU:
+	case RCPU_CALL:
 		{
 			int off = ctx->allocOffset++;
 			const int count = RCPU_SCRATCH_COUNT;
@@ -877,6 +896,7 @@ static preg *alloc_reg( jit_ctx *ctx, preg_kind k ) {
 				int r = RCPU_SCRATCH_REGS[(i + off)%count];
 				p = ctx->pregs + r;
 				if( p->lock >= ctx->currentPos ) continue;
+				if( k == RCPU_CALL && is_call_reg(p) ) continue;
 				if( p->holds == NULL ) {
 					RLOCK(p);
 					return p;
@@ -885,6 +905,7 @@ static preg *alloc_reg( jit_ctx *ctx, preg_kind k ) {
 			for(i=0;i<count;i++) {
 				preg *p = ctx->pregs + RCPU_SCRATCH_REGS[(i + off)%count];
 				if( p->lock >= ctx->currentPos ) continue;
+				if( k == RCPU_CALL && is_call_reg(p) ) continue;
 				if( p->holds ) {
 					RLOCK(p);
 					p->holds->current = NULL;
@@ -1081,7 +1102,7 @@ static preg *copy( jit_ctx *ctx, preg *to, preg *from, int size ) {
 #	endif
 		{
 			preg *tmp;
-			if( size == 8 && !IS_64 ) {
+			if( size == 8 && (!IS_64 || (to->kind == RSTACK && IS_FLOAT(R(to->id))) || (from->kind == RSTACK && IS_FLOAT(R(from->id)))) ) {
 				tmp = alloc_reg(ctx, RFPU);
 				op64(ctx,MOVSD,tmp,from);
 			} else {
@@ -1262,6 +1283,7 @@ static int prepare_call_args( jit_ctx *ctx, int count, int *args, vreg *vregs, b
 		int index = IS_FLOAT(v) ? nextCpu++ : nextFpu++;
 #		endif
 		preg *r;
+		index += extraSize / HL_WSIZE;
 		if( index == CALL_NREGS )
 			break;
 		r = REG_AT(IS_FLOAT(v) ? XMM(index) : CALL_REGS[index]);
@@ -2204,7 +2226,7 @@ static preg *alloc_native_arg( jit_ctx *ctx ) {
 
 static void set_native_arg( jit_ctx *ctx, preg *r ) {
 #	ifdef HL_64
-	preg *target = REG_AT(CALL_REGS[--ctx->nativeArgsCount]);
+	preg *target = REG_AT(r->kind == RFPU ? XMM(--ctx->nativeArgsCount) : CALL_REGS[--ctx->nativeArgsCount]);
 	if( target != r ) {
 		op64(ctx, MOV, target, r);
 		scratch(target);
@@ -2304,8 +2326,12 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 	if( IS_WINCALL64 ) {
 		for(i=0;i<nargs;i++) {
 			vreg *r = R(i);
+			preg *p;
 			if( i == CALL_NREGS ) break;
-			op64(ctx,MOV,fetch(r),REG_AT(IS_FLOAT(r) ? XMM(i) : CALL_REGS[i]));
+			p = REG_AT(IS_FLOAT(r) ? XMM(i) : CALL_REGS[i]);
+			op64(ctx,MOV,fetch(r),p);
+			p->holds = r;
+			r->current = p;
 		}
 	} else {
 		jit_error("TODO");
@@ -2347,13 +2373,25 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 		case OGetGlobal:
 			{
 				void *addr = m->globals_data + m->globals_indexes[o->p2];
+#				ifdef HL_64
+				preg *tmp = alloc_reg(ctx, RCPU);
+				op64(ctx, MOV, tmp, pconst64(&p,(int_val)addr));
+				copy_to(ctx, dst, pmem(&p,tmp->id,0));
+#				else
 				copy_to(ctx, dst, paddr(&p,addr));
+#				endif
 			}
 			break;
 		case OSetGlobal:
 			{
 				void *addr = m->globals_data + m->globals_indexes[o->p1];
+#				ifdef HL_64
+				preg *tmp = alloc_reg(ctx, RCPU);
+				op64(ctx, MOV, tmp, pconst64(&p,(int_val)addr));
+				copy_from(ctx, pmem(&p,tmp->id,0), ra);
+#				else
 				copy_from(ctx, paddr(&p,addr), ra);
+#				endif
 			}
 			break;
 		case OCall3:
@@ -2573,7 +2611,11 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 					break;
 				case HF32:
 					BREAK();
+#					ifdef HL_64
+					jit_error("TODO");
+#					else
 					op32(ctx,MOVSS,alloc_fpu(ctx,dst,false),paddr(&p,m->code->floats + o->p2));
+#					endif
 					break;
 				default:
 					ASSERT(dst->t->kind);
@@ -2729,7 +2771,11 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				restore_regs(ctx);
 				size = prepare_call_args(ctx,o->p3,o->extra,ctx->vregs,false,HL_WSIZE);
 				if( r->holds != ra ) r = alloc_cpu(ctx, ra, true);
+#				ifdef HL_64
+				op64(ctx, MOV, REG_AT(CALL_REGS[0]), pmem(&p,r->id,HL_WSIZE*3));
+#				else
 				op64(ctx, PUSH,pmem(&p,r->id,HL_WSIZE*3),UNUSED); // push closure value
+#				endif
 				op_call(ctx, pmem(&p,r->id,HL_WSIZE), size);
 				discard_regs(ctx,false);
 				patch_jump(ctx,jend);
@@ -2879,7 +2925,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				int size;
 				preg *r = alloc_cpu(ctx, R(o->extra[0]), true);
 				preg *tmp;
-				tmp = alloc_reg(ctx, RCPU);
+				tmp = alloc_reg(ctx, RCPU_CALL);
 				op64(ctx,MOV,tmp,pmem(&p,r->id,0)); // read type
 				op64(ctx,MOV,tmp,pmem(&p,tmp->id,HL_WSIZE*2)); // read proto
 				size = prepare_call_args(ctx,o->p3,o->extra,ctx->vregs,false,0);
@@ -3228,10 +3274,17 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 		case ODynGet:
 			{
 				int size;
-				preg *r;
 #				ifdef HL_64
-				jit_error("TODO");
+				if( IS_FLOAT(dst) ) {
+					size = begin_native_call(ctx,2);
+				} else {
+					size = begin_native_call(ctx,3);
+					set_native_arg(ctx,pconst64(&p,(int_val)dst->t));
+				}
+				set_native_arg(ctx,pconst64(&p,(int_val)hl_hash_utf8(m->code->strings[o->p3])));
+				set_native_arg(ctx,fetch(ra));
 #				else
+				preg *r;
 				r = alloc_reg(ctx,RCPU);
 				if( IS_FLOAT(dst) ) {
 					size = pad_before_call(ctx,HL_WSIZE*2);
@@ -3243,16 +3296,33 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				op64(ctx,MOV,r,pconst64(&p,(int_val)hl_hash_utf8(m->code->strings[o->p3])));
 				op64(ctx,PUSH,r,UNUSED);
 				op64(ctx,PUSH,fetch(ra),UNUSED);
+#				endif
 				call_native(ctx,get_dynget(dst->t),size);
 				store_result(ctx,dst);
-#				endif
 			}
 			break;
 		case ODynSet:
 			{
 				int size;
 #				ifdef HL_64
-				jit_error("TODO");
+				switch( rb->t->kind ) {
+				case HF32:
+				case HF64:
+					size = begin_native_call(ctx, 3);
+					set_native_arg(ctx,fetch(rb));
+					set_native_arg(ctx,pconst64(&p,hl_hash_gen(hl_get_ustring(m->code,o->p2),true)));
+					set_native_arg(ctx,fetch(dst));
+					call_native(ctx,get_dynset(rb->t),size);
+					break;
+				default:
+					size = begin_native_call(ctx,4);
+					set_native_arg(ctx,fetch(rb));
+					set_native_arg(ctx,pconst64(&p,(int_val)rb->t));
+					set_native_arg(ctx,pconst64(&p,hl_hash_gen(hl_get_ustring(m->code,o->p2),true)));
+					set_native_arg(ctx,fetch(dst));
+					call_native(ctx,get_dynset(rb->t),size);
+					break;
+				}
 #				else
 				switch( rb->t->kind ) {
 				case HF32:
@@ -3285,20 +3355,36 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 			{
 				int size, jenter, jtrap;
 				int trap_size = (sizeof(hl_trap_ctx) + 15) & 0xFFF0;
+				int trap_pad = trap_size - sizeof(hl_trap_ctx);
 				// trap pad
-				op64(ctx,SUB,PESP,pconst(&p,trap_size - sizeof(hl_trap_ctx)));
+				if( trap_pad ) op64(ctx,SUB,PESP,pconst(&p,trap_pad));
+#				ifdef HL_64
+				preg *tmp = alloc_reg(ctx,RCPU);
+				op64(ctx,MOV,tmp,pconst64(&p,(int_val)&hl_current_trap));
+				op64(ctx,MOV,PEAX,pmem(&p,tmp->id,0));
+				op64(ctx,PUSH,PEAX,UNUSED);
+				op64(ctx,SUB,PESP,pconst(&p,sizeof(hl_trap_ctx) - HL_WSIZE));
+				op64(ctx,MOV,PEAX,PESP);
+				op64(ctx,MOV,pmem(&p,tmp->id,0),PEAX);
+#				else
 				op64(ctx,MOV,PEAX,paddr(&p,&hl_current_trap));
 				op64(ctx,PUSH,PEAX,UNUSED);
 				op64(ctx,SUB,PESP,pconst(&p,sizeof(hl_trap_ctx) - HL_WSIZE));
 				op64(ctx,MOV,PEAX,PESP);
 				op64(ctx,MOV,paddr(&p,&hl_current_trap),PEAX);
-				size = pad_before_call(ctx, HL_WSIZE);
-				op64(ctx,PUSH,PEAX,UNUSED);
+#				endif
+				size = begin_native_call(ctx, 1);
+				set_native_arg(ctx,PEAX);
 				call_native(ctx,setjmp,size);
 				op64(ctx,TEST,PEAX,PEAX);
 				XJump_small(JZero,jenter);
 				op64(ctx,ADD,PESP,pconst(&p,trap_size));
+#				ifdef HL_64
+				op64(ctx,MOV,PEAX,pconst64(&p,(int_val)&hl_current_exc));
+				op64(ctx,MOV,PEAX,pmem(&p,Eax,0));
+#				else
 				op64(ctx,MOV,PEAX,paddr(&p,&hl_current_exc));
+#				endif
 				store(ctx,dst,PEAX,false);
 				jtrap = do_jump(ctx,OJAlways,false);
 				register_jump(ctx,jtrap,(opCount + 1) + o->p2);
@@ -3310,9 +3396,17 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				int trap_size = (sizeof(hl_trap_ctx) + 15) & 0xFFF0;
 				preg *r = alloc_reg(ctx, RCPU);
 				hl_trap_ctx *tmp = NULL;
+#				ifdef HL_64
+				preg *addr = alloc_reg(ctx,RCPU);
+				op64(ctx, MOV, addr, pconst64(&p,(int_val)&hl_current_trap));
+				op64(ctx, MOV, r, pmem(&p,addr->id,0));
+				op64(ctx, MOV, r, pmem(&p,r->id,(int)(int_val)&tmp->prev));
+				op64(ctx, MOV, pmem(&p,addr->id,0), r);
+#				else
 				op64(ctx, MOV, r, paddr(&p,&hl_current_trap));
 				op64(ctx, MOV, r, pmem(&p,r->id,(int)(int_val)&tmp->prev));
 				op64(ctx, MOV, paddr(&p,&hl_current_trap), r);
+#				endif
 				op64(ctx,ADD,PESP,pconst(&p,trap_size));
 			}
 			break;