move instruction length offsets to instruction generation

This commit is contained in:
dzaima 2021-07-02 17:46:29 +03:00
parent 9fbc8203d0
commit 2a7eebad93
2 changed files with 18 additions and 24 deletions

View File

@ -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

View File

@ -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))