|
@@ -1331,7 +1331,7 @@ static void on_jit_error( const char *msg, int_val line ) {
|
|
#ifdef HL_WIN
|
|
#ifdef HL_WIN
|
|
MessageBoxA(NULL,buf,"JIT ERROR",MB_OK);
|
|
MessageBoxA(NULL,buf,"JIT ERROR",MB_OK);
|
|
#else
|
|
#else
|
|
- printf("%s\n",buf);
|
|
|
|
|
|
+ printf("JIT ERROR : %s\n",buf);
|
|
#endif
|
|
#endif
|
|
hl_debug_break();
|
|
hl_debug_break();
|
|
hl_throw(NULL);
|
|
hl_throw(NULL);
|
|
@@ -1400,9 +1400,10 @@ static preg *op_binop( jit_ctx *ctx, vreg *dst, vreg *a, vreg *b, hl_opcode *op
|
|
return pa;
|
|
return pa;
|
|
case OSDiv:
|
|
case OSDiv:
|
|
case OUDiv:
|
|
case OUDiv:
|
|
- case OSMod:
|
|
|
|
|
|
+ case OSMod:
|
|
|
|
+ case OUMod:
|
|
{
|
|
{
|
|
- preg *out = op->op == OSMod ? REG_AT(Edx) : PEAX;
|
|
|
|
|
|
+ preg *out = op->op == OSMod || op->op == OUMod ? REG_AT(Edx) : PEAX;
|
|
preg *r = alloc_cpu(ctx,b,true);
|
|
preg *r = alloc_cpu(ctx,b,true);
|
|
int jz, jend;
|
|
int jz, jend;
|
|
// integer div 0 => 0
|
|
// integer div 0 => 0
|
|
@@ -1417,11 +1418,11 @@ static preg *op_binop( jit_ctx *ctx, vreg *dst, vreg *a, vreg *b, hl_opcode *op
|
|
load(ctx,PEAX,a);
|
|
load(ctx,PEAX,a);
|
|
}
|
|
}
|
|
scratch(REG_AT(Edx));
|
|
scratch(REG_AT(Edx));
|
|
- if( op->op == OUDiv )
|
|
|
|
|
|
+ if( op->op == OUDiv || op->op == OUMod )
|
|
op32(ctx, XOR, REG_AT(Edx), REG_AT(Edx));
|
|
op32(ctx, XOR, REG_AT(Edx), REG_AT(Edx));
|
|
else
|
|
else
|
|
op32(ctx, CDQ, UNUSED, UNUSED); // sign-extend Eax into Eax:Edx
|
|
op32(ctx, CDQ, UNUSED, UNUSED); // sign-extend Eax into Eax:Edx
|
|
- op32(ctx, op->op == OUDiv ? DIV : IDIV, fetch(b), UNUSED);
|
|
|
|
|
|
+ op32(ctx, op->op == OUDiv || op->op == OUMod ? DIV : IDIV, fetch(b), UNUSED);
|
|
patch_jump(ctx, jend);
|
|
patch_jump(ctx, jend);
|
|
if( dst ) store(ctx, dst, out, true);
|
|
if( dst ) store(ctx, dst, out, true);
|
|
return out;
|
|
return out;
|
|
@@ -1726,6 +1727,7 @@ static void op_jump( jit_ctx *ctx, vreg *a, vreg *b, hl_opcode *op, int targetPo
|
|
if( hl_get_obj_rt(a->t)->compareFun ) {
|
|
if( hl_get_obj_rt(a->t)->compareFun ) {
|
|
preg *pa = alloc_cpu(ctx,a,true);
|
|
preg *pa = alloc_cpu(ctx,a,true);
|
|
preg *pb = alloc_cpu(ctx,b,true);
|
|
preg *pb = alloc_cpu(ctx,b,true);
|
|
|
|
+ preg p;
|
|
int jeq, ja, jb, jcmp;
|
|
int jeq, ja, jb, jcmp;
|
|
int args[] = { a->stack.id, b->stack.id };
|
|
int args[] = { a->stack.id, b->stack.id };
|
|
switch( op->op ) {
|
|
switch( op->op ) {
|
|
@@ -1764,7 +1766,16 @@ static void op_jump( jit_ctx *ctx, vreg *a, vreg *b, hl_opcode *op, int targetPo
|
|
patch_jump(ctx,jeq);
|
|
patch_jump(ctx,jeq);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
- jit_error("TODO");
|
|
|
|
|
|
+ // if( a && b && cmp(a,b) ?? 0 ) goto
|
|
|
|
+ op64(ctx,TEST,pa,pa);
|
|
|
|
+ XJump_small(JZero,ja);
|
|
|
|
+ op64(ctx,TEST,pb,pb);
|
|
|
|
+ XJump_small(JZero,jb);
|
|
|
|
+ op_call_fun(ctx,NULL,(int)a->t->obj->rt->compareFun,2,args);
|
|
|
|
+ op64(ctx,CMP,PEAX,pconst(&p,0));
|
|
|
|
+ register_jump(ctx,do_jump(ctx,op->op,false),targetPos);
|
|
|
|
+ patch_jump(ctx,ja);
|
|
|
|
+ patch_jump(ctx,jb);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
return;
|
|
return;
|
|
@@ -1935,6 +1946,10 @@ static void *get_dynget( hl_type *t ) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static double uint_to_double( unsigned int v ) {
|
|
|
|
+ return v;
|
|
|
|
+}
|
|
|
|
+
|
|
static void make_dyn_cast( jit_ctx *ctx, vreg *dst, vreg *v ) {
|
|
static void make_dyn_cast( jit_ctx *ctx, vreg *dst, vreg *v ) {
|
|
int size;
|
|
int size;
|
|
preg p;
|
|
preg p;
|
|
@@ -2104,6 +2119,7 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
|
|
case OOr:
|
|
case OOr:
|
|
case OXor:
|
|
case OXor:
|
|
case OSMod:
|
|
case OSMod:
|
|
|
|
+ case OUMod:
|
|
op_binop(ctx, dst, ra, rb, o);
|
|
op_binop(ctx, dst, ra, rb, o);
|
|
break;
|
|
break;
|
|
case ONeg:
|
|
case ONeg:
|
|
@@ -2208,6 +2224,14 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
|
|
} else
|
|
} else
|
|
ASSERT(0);
|
|
ASSERT(0);
|
|
break;
|
|
break;
|
|
|
|
+ case OToUFloat:
|
|
|
|
+ {
|
|
|
|
+ int size;
|
|
|
|
+ size = prepare_call_args(ctx,1,&o->p2,ctx->vregs,true,0);
|
|
|
|
+ call_native(ctx,uint_to_double,size);
|
|
|
|
+ store_native_result(ctx,dst);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
case OToInt:
|
|
case OToInt:
|
|
if( ra->t->kind == HF64 ) {
|
|
if( ra->t->kind == HF64 ) {
|
|
preg *r = alloc_fpu(ctx,ra,true);
|
|
preg *r = alloc_fpu(ctx,ra,true);
|
|
@@ -2281,6 +2305,10 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
|
|
store(ctx,dst,dst->current,false);
|
|
store(ctx,dst,dst->current,false);
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
+ case OBytes:
|
|
|
|
+ op64(ctx,MOV,alloc_cpu(ctx,dst,false),pconst64(&p,(int_val)m->code->strings[o->p2]));
|
|
|
|
+ store(ctx,dst,dst->current,false);
|
|
|
|
+ break;
|
|
case ONull:
|
|
case ONull:
|
|
{
|
|
{
|
|
op64(ctx,XOR,alloc_cpu(ctx, dst, false),alloc_cpu(ctx, dst, false));
|
|
op64(ctx,XOR,alloc_cpu(ctx, dst, false),alloc_cpu(ctx, dst, false));
|
|
@@ -2512,16 +2540,21 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
|
|
# else
|
|
# else
|
|
switch( rb->t->kind ) {
|
|
switch( rb->t->kind ) {
|
|
case HF64:
|
|
case HF64:
|
|
- jit_error("TODO");
|
|
|
|
|
|
+ size = pad_before_call(ctx,HL_WSIZE*2 + sizeof(double));
|
|
|
|
+ push_reg(ctx,rb);
|
|
|
|
+ break;
|
|
|
|
+ case HF32:
|
|
|
|
+ size = pad_before_call(ctx,HL_WSIZE*2 + sizeof(float));
|
|
|
|
+ push_reg(ctx,rb);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
size = pad_before_call(ctx,HL_WSIZE*4);
|
|
size = pad_before_call(ctx,HL_WSIZE*4);
|
|
op64(ctx,PUSH,fetch(rb),UNUSED);
|
|
op64(ctx,PUSH,fetch(rb),UNUSED);
|
|
op64(ctx,MOV,r,pconst64(&p,(int_val)rb->t));
|
|
op64(ctx,MOV,r,pconst64(&p,(int_val)rb->t));
|
|
|
|
+ op64(ctx,PUSH,r,UNUSED);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- op64(ctx,PUSH,r,UNUSED);
|
|
|
|
- op64(ctx,MOV,r,pconst64(&p,(int_val)dst->t->virt->fields[o->p2].hashed_name));
|
|
|
|
|
|
+ op32(ctx,MOV,r,pconst(&p,dst->t->virt->fields[o->p2].hashed_name));
|
|
op64(ctx,PUSH,r,UNUSED);
|
|
op64(ctx,PUSH,r,UNUSED);
|
|
op64(ctx,PUSH,obj,UNUSED);
|
|
op64(ctx,PUSH,obj,UNUSED);
|
|
call_native(ctx,get_dynset(rb->t),size);
|
|
call_native(ctx,get_dynset(rb->t),size);
|
|
@@ -2644,9 +2677,12 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
|
|
if( need_dyn ) {
|
|
if( need_dyn ) {
|
|
if( IS_FLOAT(dst) )
|
|
if( IS_FLOAT(dst) )
|
|
jit_error("TODO");
|
|
jit_error("TODO");
|
|
- else
|
|
|
|
|
|
+ else {
|
|
copy(ctx,PEAX,pmem(&p,Esp,8 - sizeof(vdynamic)),dst->size);
|
|
copy(ctx,PEAX,pmem(&p,Esp,8 - sizeof(vdynamic)),dst->size);
|
|
- }
|
|
|
|
|
|
+ store(ctx, dst, PEAX, true);
|
|
|
|
+ }
|
|
|
|
+ } else
|
|
|
|
+ store(ctx, dst, PEAX, true);
|
|
|
|
|
|
XJump_small(JAlways,jend);
|
|
XJump_small(JAlways,jend);
|
|
patch_jump(ctx,jhasfield);
|
|
patch_jump(ctx,jhasfield);
|
|
@@ -2789,9 +2825,11 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case OUnref:
|
|
case OUnref:
|
|
- BREAK();
|
|
|
|
copy_to(ctx,dst,pmem(&p,alloc_cpu(ctx,ra,true)->id,0));
|
|
copy_to(ctx,dst,pmem(&p,alloc_cpu(ctx,ra,true)->id,0));
|
|
break;
|
|
break;
|
|
|
|
+ case OSetref:
|
|
|
|
+ copy_from(ctx,pmem(&p,alloc_cpu(ctx,dst,true)->id,0),ra);
|
|
|
|
+ break;
|
|
case OToVirtual:
|
|
case OToVirtual:
|
|
{
|
|
{
|
|
# ifdef HL_64
|
|
# ifdef HL_64
|
|
@@ -2879,23 +2917,19 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
|
|
# ifdef HL_64
|
|
# ifdef HL_64
|
|
jit_error("TODO");
|
|
jit_error("TODO");
|
|
# else
|
|
# else
|
|
- switch( dst->t->kind ) {
|
|
|
|
- case HF32:
|
|
|
|
- case HF64:
|
|
|
|
- jit_error("TODO");
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- r = alloc_reg(ctx,RCPU);
|
|
|
|
|
|
+ r = alloc_reg(ctx,RCPU);
|
|
|
|
+ if( IS_FLOAT(dst) ) {
|
|
|
|
+ size = pad_before_call(ctx,HL_WSIZE*2);
|
|
|
|
+ } else {
|
|
size = pad_before_call(ctx,HL_WSIZE*3);
|
|
size = pad_before_call(ctx,HL_WSIZE*3);
|
|
op64(ctx,MOV,r,pconst64(&p,(int_val)dst->t));
|
|
op64(ctx,MOV,r,pconst64(&p,(int_val)dst->t));
|
|
op64(ctx,PUSH,r,UNUSED);
|
|
op64(ctx,PUSH,r,UNUSED);
|
|
- 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);
|
|
|
|
- call_native(ctx,get_dynget(dst->t),size);
|
|
|
|
- store_native_result(ctx,dst);
|
|
|
|
- break;
|
|
|
|
}
|
|
}
|
|
|
|
+ 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);
|
|
|
|
+ call_native(ctx,get_dynget(dst->t),size);
|
|
|
|
+ store_native_result(ctx,dst);
|
|
# endif
|
|
# endif
|
|
}
|
|
}
|
|
break;
|
|
break;
|