From 044431bb7d230486c1ba45078904707d3a6cd12b Mon Sep 17 00:00:00 2001 From: dzaima Date: Sat, 16 Oct 2021 13:05:26 +0300 Subject: [PATCH] less bad way of doing JIT jumps --- src/jit/nvm_x86_64.c | 12 ++++++------ src/jit/x86_64.h | 44 +++++++++++--------------------------------- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index 803dc7ea..8586894b 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -580,9 +580,9 @@ Nvm_res m_nvm(Body* body) { #define LSC(R,D) { if(D) MOV8rmo(R,R_SP,VAR8(pscs,D)); else MOV(R,r_SC); } // TODO return r_SC directly without a pointless mov #define INCV(R) INC4mo(R, offsetof(Value,refc)); // ADD4mi(R_A3, 1); CCALL(i_INC); #ifdef __BMI2__ // TODO move to runtime detection maybe - #define INCB(R,T,U) IMM(T,0xfffffffffffffull);ADD(T,R);IMM(U,0x7fffffffffffeull);CMP(T,U);{JA(lI);MOVi1l(U,0x30);BZHI(U,R,U);INCV(U);LBL1(lI);} + #define INCB(R,T,U) IMM(T,0xfffffffffffffull);ADD(T,R);IMM(U,0x7fffffffffffeull);CMP(T,U);{J1(cA,lI);MOVi1l(U,0x30);BZHI(U,R,U);INCV(U);LBL1(lI);} #else - #define INCB(R,T,U) IMM(T,0xfffffffffffffull);ADD(T,R);IMM(U,0x7fffffffffffeull);CMP(T,U);{JA(lI);IMM(U,0xffffffffffffull);AND(U,R);INCV(U);LBL1(lI);} + #define INCB(R,T,U) IMM(T,0xfffffffffffffull);ADD(T,R);IMM(U,0x7fffffffffffeull);CMP(T,U);{J1(cA,lI);IMM(U,0xffffffffffffull);AND(U,R);INCV(U);LBL1(lI);} #endif // #define POS_UPD(R1,R2) IMM(R1, off); MOV8mro(r_ENV, R1, offsetof(Env,pos)); #define POS_UPD(R1,R2) MOV4moi(r_ENV, offsetof(Env,pos), body->bl->map[bcpos + bodyOff]<<1 | 1); @@ -631,7 +631,7 @@ Nvm_res m_nvm(Body* body) { case VARO: TOPs; { u64 d=*bc++; u64 p=*bc++; LSC(R_A1,d); MOV8rmo(R_RES,R_A1,p*8+offsetof(Scope,vars)); // read variable INCB(R_RES,R_A2,R_A3); // increment refcount if one's needed - if (d) { IMM(R_A2, bi_noVar.u); CMP(R_A2,R_RES); JNE(lN); IMM(R_A0,off); INV(1,1,i_NOVAR); LBL1(lN); } // check for error + if (d) { IMM(R_A2, bi_noVar.u); CMP(R_A2,R_RES); J1(cNE,lN); IMM(R_A0,off); INV(1,1,i_NOVAR); LBL1(lN); } // check for error } break; case VARU: TOPs; { u64 d=*bc++; u64 p=*bc++; LSC(R_A1,d); MOV8rmo(R_RES,R_A1,p*8+offsetof(Scope,vars)); // read variable @@ -642,17 +642,17 @@ Nvm_res m_nvm(Body* body) { case EXTU: TOPs; { u64 d=*bc++; IMM(R_A0,*bc++); LSC(R_A1,d); CCALL(i_EXTU); } break; // (u32 p, Scope* sc) case SETHi:TOPp; { u64 v1=L64; u64 v2=L64; if (lGPos!=0) GS_SET(r_CS); lGPos=0; GET(R_A1,1,1); LEAi(R_A2,R_SP,VAR(pscs,0)); IMM(R_A3,off); IMM(R_A4,v1); IMM(R_A5,v2); CCALL(i_SETH); // (B s, B x, Scope** pscs, u32* bc, Body* v1, Body* v2) - IMM(R_A0, bi_okHdr.u); CMP(R_A0,R_RES); JNE4(l); TSADD(retLbls, l); + IMM(R_A0, bi_okHdr.u); CMP(R_A0,R_RES); J4(cNE,l); TSADD(retLbls, l); break; } case PRED1:TOPp; { u64 v1=L64; GET(R_A1,0,2); MOV(R_A1,r_SC); IMM(R_A2,off); IMM(R_A3,v1); CCALL(i_PRED1); // (B x, Scope** pscs, u32* bc, Body* v) - IMM(R_A0, bi_okHdr.u); CMP(R_A0,R_RES); JNE4(l); TSADD(retLbls, l); NORES(1); + IMM(R_A0, bi_okHdr.u); CMP(R_A0,R_RES); J4(cNE,l); TSADD(retLbls, l); NORES(1); break; } case PRED2:TOPp; { u64 v1=L64; u64 v2=L64; GET(R_A1,0,2); MOV(R_A1,r_SC); IMM(R_A2,off); IMM(R_A3,v1); IMM(R_A4,v2); CCALL(i_PRED2); // (B x, Scope** pscs, u32* bc, Body* v1, Body* v2) - IMM(R_A0, bi_okHdr.u); CMP(R_A0,R_RES); JNE4(l); TSADD(retLbls, l); NORES(1); + IMM(R_A0, bi_okHdr.u); CMP(R_A0,R_RES); J4(cNE,l); TSADD(retLbls, l); NORES(1); break; } case SETN: TOPp; GET(R_A1,1,1); LEAi(R_A2,R_SP,VAR(pscs,0)); IMM(R_A3,off); CCALL(i_SETN); break; // (B s, B x, Scope** pscs, u32* bc) diff --git a/src/jit/x86_64.h b/src/jit/x86_64.h index ae493298..e98c01e6 100644 --- a/src/jit/x86_64.h +++ b/src/jit/x86_64.h @@ -423,39 +423,17 @@ static inline void asm_a(TStack* o, u64 len, u8 v[]) { #define CALLi(POS) {AC1(CALLi,(u64)(POS)); TSADD(b_r, ASM_SIZE-4);} // POS must be 32-bit #define RET() {b_o=asm_r(b_o); ASM1(0xC3);} -#define JO(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x70);ASM1(-2);} // -2 comes from the instruction being 2 bytes long and L being defined at the start -#define JNO(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x71);ASM1(-2);} -#define JB(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x72);ASM1(-2);} -#define JAE(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x73);ASM1(-2);} -#define JE(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x74);ASM1(-2);} -#define JNE(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x75);ASM1(-2);} -#define JBE(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x76);ASM1(-2);} -#define JA(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x77);ASM1(-2);} -#define JS(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x78);ASM1(-2);} -#define JNS(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x79);ASM1(-2);} -#define JP(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x7A);ASM1(-2);} -#define JNP(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x7B);ASM1(-2);} -#define JL(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x7C);ASM1(-2);} -#define JGE(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x7D);ASM1(-2);} -#define JLE(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x7E);ASM1(-2);} -#define JG(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x7F);ASM1(-2);} -#define LBL1(L) { i64 t=(i8)b_o->data[L+1] + ASM_SIZE-(i64)L; if(t!=(i8)t) err("x86-64 codegen: jump too long!"); b_o->data[L+1] = t; } -#define JO4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x80);ASM4(-6);} -#define JNO4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x81);ASM4(-6);} -#define JB4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x82);ASM4(-6);} -#define JAE4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x83);ASM4(-6);} -#define JE4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x84);ASM4(-6);} -#define JNE4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x85);ASM4(-6);} -#define JBE4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x86);ASM4(-6);} -#define JA4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x87);ASM4(-6);} -#define JS4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x88);ASM4(-6);} -#define JNS4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x89);ASM4(-6);} -#define JP4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x8A);ASM4(-6);} -#define JNP4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x8B);ASM4(-6);} -#define JL4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x8C);ASM4(-6);} -#define JGE4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x8D);ASM4(-6);} -#define JLE4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x8E);ASM4(-6);} -#define JG4(L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1(0x8F);ASM4(-6);} +static const u8 cO = 0x0; static const u8 cNO = 0x1; +static const u8 cB = 0x2; static const u8 cAE = 0x3; +static const u8 cE = 0x4; static const u8 cNE = 0x5; +static const u8 cBE = 0x6; static const u8 cA = 0x7; +static const u8 cS = 0x8; static const u8 cNS = 0x9; +static const u8 cP = 0xA; static const u8 cNP = 0xB; +static const u8 cL = 0xC; static const u8 cGE = 0xD; +static const u8 cLE = 0xE; static const u8 cG = 0xF; +#define J1(T, L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1((i8)(0x70+(T)));ASM1(-2);} // -2 comes from the instruction being 2 bytes long and L being defined at the start +#define J4(T, L) u64 L=ASM_SIZE; {b_o=asm_r(b_o); ASM1(0x0f);ASM1((i8)(0x80+(T)));ASM4(-6);} +#define LBL1(L) { i64 t= (i8)b_o->data[L+1] + ASM_SIZE-(i64)L; if(t!=(i8 )t) err("x86-64 codegen: jump too long!"); b_o->data[L+1] = t; } #define LBL4(L) { i64 t=asm_r4(b_o->data+(L+2)) + ASM_SIZE-(i64)L; if(t!=(i32)t) err("x86-64 codegen: jump too long!"); asm_w4(b_o->data+(L+2), t); } ASMI(ADD, Reg o, Reg i) { nREX8(o,i); ASM1(0x01); nA_REG(o,i); }