From 2a7eebad932a82ef742705835de8de3369ee63b7 Mon Sep 17 00:00:00 2001 From: dzaima Date: Fri, 2 Jul 2021 17:46:29 +0300 Subject: [PATCH] move instruction length offsets to instruction generation --- src/jit/nvm_x86_64.c | 26 ++++++++++---------------- src/jit/x86_64.h | 16 ++++++++-------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index 99bbb654..fcf7592c 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -85,12 +85,6 @@ INS B i_FN2O(B w, u32* bc GA1) { P(f)P(x) GS_UPD;POS_UPD; dec(f); return r; } -INS B i_FN1Ci(B x, BB2B fi, u32* bc GA1) { GS_UPD;POS_UPD; - return fi(b((u64)0), x); -} -INS B i_FN2Ci(B w, BBB2B fi, u32* bc GA1) { P(x) GS_UPD;POS_UPD; - return fi(b((u64)0), w, x); -} INS B i_FN1Oi(B x, BB2B fm, u32* bc GA1) { GS_UPD;POS_UPD; B r = isNothing(x)? x : fm(b((u64)0), x); return r; @@ -439,7 +433,7 @@ static u32 readBytes4(u8* d) { file_wChars(m_str32(U"asm_off"), o); dec(o); B s = inc(bi_emptyCVec); #define F(X) AFMT("s/%p$/%p # i_" #X "/;", i_##X, i_##X); - F(POPS) F(INC) F(ADDU) F(FN1C) F(FN1O) F(FN2C) F(FN2O) F(FN1Ci) F(FN2Ci) F(FN1Oi) F(FN2Oi) F(ARR_0) F(ARR_p) F(DFND_0) F(DFND_1) F(DFND_2) F(OP1D) F(OP2D) F(OP2H) F(TR2D) F(TR3D) F(TR3O) F(LOCO) F(LOCU) F(EXTO) F(EXTU) F(SETN) F(SETU) F(SETM) F(FLDO) F(NSPM) F(RETD) F(SETNi) F(SETUi) F(SETMi) + F(POPS) F(INC) F(ADDU) F(FN1C) F(FN1O) F(FN2C) F(FN2O) F(FN1Oi) F(FN2Oi) F(ARR_0) F(ARR_p) F(DFND_0) F(DFND_1) F(DFND_2) F(OP1D) F(OP2D) F(OP2H) F(TR2D) F(TR3D) F(TR3O) F(LOCO) F(LOCU) F(EXTO) F(EXTU) F(SETN) F(SETU) F(SETM) F(FLDO) F(NSPM) F(RETD) F(SETNi) F(SETUi) F(SETMi) #undef F file_wChars(m_str32(U"asm_sed"), s); dec(s); } @@ -469,12 +463,12 @@ Nvm_res m_nvm(Body* body) { MOV(r_CS, R_A0); MOV(r_SC, R_A1); - MOV8rp(r_ENV, (u64)&envCurr - 4); + MOV8rp(r_ENV, &envCurr); #define VAR(OFF,N) (OFF##Off + (N)) #define VAR8(OFF,N) VAR(OFF,(N)*8) ADDi(R_A4, 0x12); - MOV8mro(R_SP, R_A1, VAR8(pscs,0)); + MOV8mro(R_SP, R_A1, VAR(pscs,0)); for (i32 i = 1; i < body->maxPSC+1; i++) { MOV8rmo(R_A1, R_A1, offsetof(Scope, psc)); MOV8mro(R_SP, R_A1, VAR8(pscs,i)); @@ -482,7 +476,7 @@ Nvm_res m_nvm(Body* body) { ADDi(R_A4, 0x34); if ((u64)i_RETD > I32_MAX || (u64)&gStack > I32_MAX || (u64)&envEnd > I32_MAX) thrM("JIT: Refusing to run with CBQN code outside of the 32-bit address range"); - #define CCALL(F) { u64 f=(u64)(F); if(f>I32_MAX)thrM("JIT: Function address too large for call"); CALLi(f-4); } + #define CCALL(F) { u64 f=(u64)(F); if(f>I32_MAX)thrM("JIT: Function address too large for call"); CALLi(f); } u32* origBC = body->bc; OptRes optRes = opt(origBC); Block** blocks = body->blocks->a; @@ -497,7 +491,7 @@ Nvm_res m_nvm(Body* body) { // #define LEA0(O,I,OFF) { MOV(O,I); ADDI(O,OFF); } #define LEA0(O,I,OFF,Q) ({ i32 o=(OFF); if (Q||o) LEAi(O,I,o); o?O:I; }) #define SPOSq(N) (maxi32(0, depth+(N)-1) * sizeof(B)) - #define SPOS(R,N,Q) LEA0(R, r_CS, SPOSq(N), Q) // load stack position N in register R; if !Q, then might not write and instead return another register which will have the wanted value + #define SPOS(R,N,Q) LEA0(R, r_CS, SPOSq(N), Q) // load stack position N in register R; if Q==0, then might not write and instead return another register which will have the wanted value #if CSTACK // #define INV(N,D,F) MOV(R_A##N,r_CS); ADDI(r_CS,(D)*sizeof(B)); CCALL(F) #define INV(N,D,F) SPOS(R_A##N, D, 1); CCALL(F) @@ -533,13 +527,13 @@ Nvm_res m_nvm(Body* body) { case FN2O: TOPp; IMM(R_A1,off); INV(2,0,i_FN2O); break; // (B, u32* bc, S) case FN1Ci: { u64 fn = L64; POS_UPD(R_A0,R_A3); MOV(R_A1, R_RES); - MOV8pr((u64)&gStack - 4, SPOS(R_A3, 0, 0)); // GS_UPD + MOV8pr(&gStack, SPOS(R_A3, 0, 0)); // GS_UPD CCALL(fn); } break; case FN2Ci: { u64 fn = L64; POS_UPD(R_A0,R_A3); - Reg r_sp = SPOS(R_A2, -1, 0); - MOV8pr((u64)&gStack - 4, r_sp); // GS_UPD - MOV(R_A1, R_RES); MOV8rm(R_A2, r_sp); // load args + Reg r_p2 = SPOS(R_A2, -1, 0); + MOV8pr(&gStack, r_p2); // GS_UPD + MOV(R_A1, R_RES); MOV8rm(R_A2, r_p2); // load args CCALL(fn); } break; // case FN1Ci:TOPp; IMM(R_A1,L64); IMM(R_A2,off); INV(3,0,i_FN1Ci); break; // (B, BB2B fm, u32* bc, S) @@ -584,7 +578,7 @@ Nvm_res m_nvm(Body* body) { case CHKV: TOPp; IMM(R_A1,off); INV(2,0,i_CHKV); break; // (B, u32* bc, S) case RETD: MOV(R_A0,r_SC); INV(1,1,i_RETD); ret=true; break; // (Scope* sc, S); stack diff 0 is wrong, but updating it is useless // case RETN: IMM(R_A3, &gStack); MOV8mr(R_A3, r_CS); ret=true; break; - case RETN: MOV8pr((u64)&gStack - 4, r_CS); ret=true; break; + case RETN: MOV8pr(&gStack, r_CS); ret=true; break; default: thrF("JIT: Unsupported bytecode %i", *s); } #undef INCB diff --git a/src/jit/x86_64.h b/src/jit/x86_64.h index 603aeef5..dc576b0d 100644 --- a/src/jit/x86_64.h +++ b/src/jit/x86_64.h @@ -401,16 +401,16 @@ static inline void asm_a(TStack* o, u64 len, u8 v[]) { #define MOV8mro(I,O,OFF) AC3(MOV8mro,I,O,OFF) // *(u64*)(nullptr + I + OFF) ← O #define MOV4rmo(O,I,OFF) AC3(MOV4rmo,O,I,OFF) #define MOV4mro(I,O,OFF) AC3(MOV4mro,I,O,OFF) -#define MOV8pr(OFF,I) {AC2(MOV8pr,OFF,I); TSADD(b_r, ASM_SIZE-4);} -#define MOV8rp(I,OFF) {AC2(MOV8rp,OFF,I); TSADD(b_r, ASM_SIZE-4);} +#define MOV8pr(POS,I) {AC2(MOV8pr,(u64)(POS),I); TSADD(b_r, ASM_SIZE-4);} +#define MOV8rp(I,POS) {AC2(MOV8rp,(u64)(POS),I); TSADD(b_r, ASM_SIZE-4);} #define LEAi(O,I,IMM) AC3(LEAi,O,I,IMM) #define BZHI(O,I,N) AC3(BZHI,O,I,N) // requires __BMI2__ #define PUSH(O) AC1(PUSH,O) #define POP(O) AC1(POP,O) -#define CALL(IMM) AC1(CALL,IMM) -#define CALLi(I) {AC1(CALLi,(i64)(I)); TSADD(b_r, ASM_SIZE-4);} // I must be 32-bit +#define CALL(I) AC1(CALL,I) +#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);} @@ -429,7 +429,7 @@ static inline void asm_a(TStack* o, u64 len, u8 v[]) { #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)thrM("x86-64 codegen: jump too long!"); b_o->data[L+1] = t; } +#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; } ASMI(ADD, Reg o, Reg i) { nREX8(o,i); ASM1(0x01); nA_REG(o,i); } ASMI(SUB, Reg o, Reg i) { nREX8(o,i); ASM1(0x29); nA_REG(o,i); } @@ -462,8 +462,8 @@ ASMI(MOV8mr, Reg o, Reg i) { nREX8(o,i); ASM1(0x89); MRM(o,i); } ASMI(MOV8mro, ASMI(MOV8rm, Reg i, Reg o) { nREX8(o,i); ASM1(0x8B); MRM(o,i); } ASMI(MOV8rmo, Reg i, Reg o, i32 off) { nREX8(o,i); ASM1(0x8B); MRMo(o,i, off); } ASMI(MOV4mr, Reg o, Reg i) { nREX4(o,i); ASM1(0x89); MRM(o,i); } ASMI(MOV4mro, Reg o, Reg i, i32 off) { nREX4(o,i); ASM1(0x89); MRMo(o,i, off); } ASMI(MOV4rm, Reg i, Reg o) { nREX4(o,i); ASM1(0x8B); MRM(o,i); } ASMI(MOV4rmo, Reg i, Reg o, i32 off) { nREX4(o,i); ASM1(0x8B); MRMo(o,i, off); } -ASMI(MOV8pr,i32 off, Reg i) { nREX8(0,i); ASM1(0x89); MRMp(off,i); } -ASMI(MOV8rp,i32 off, Reg i) { nREX8(0,i); ASM1(0x8B); MRMp(off,i); } +ASMI(MOV8pr, u64 pos, Reg i) { nREX8(0,i); ASM1(0x89); MRMp(pos-4,i); } +ASMI(MOV8rp, u64 pos, Reg i) { nREX8(0,i); ASM1(0x8B); MRMp(pos-4,i); } ASMI(LEAi, Reg o, Reg i, i32 imm) { if(imm==0) iMOV(b_o,o,i); else { nREX8(i,o); ASM1(0x8D); MRMo(i,o,imm); } } ASMI(BZHI, Reg o, Reg i, Reg n) { ASM1(0xC4); ASM1(0x42+(i<8)*0x20 + (o<8)*0x80); ASM1(0xf8-n*8); ASM1(0xF5); nA_REG(i, o); } @@ -472,6 +472,6 @@ ASMI(PUSH, Reg O) { nREX4(O,0); ASM1(0x50+((O)&7)); } ASMI(POP , Reg O) { nREX4(O,0); ASM1(0x58+((O)&7)); } ASMI(CALL, Reg i) { nREX4(i,0); ASM1(0xFF); nA_REG(i,2); } -ASMI(CALLi, i32 imm) { ASM1(0xE8); if (imm>I32_MAX)err("immediate call outside of 32-bit range!"); ASM4(imm); } +ASMI(CALLi, u64 pos) { ASM1(0xE8); if (pos>I32_MAX)err("immediate call outside of 32-bit range!"); ASM4(pos-4); } #define IMM(A,B) MOVi(A,(u64)(B)) \ No newline at end of file