diff --git a/compiler/src/dmd/backend/arm/cod1.d b/compiler/src/dmd/backend/arm/cod1.d index 160f7382b3..585e12d03b 100644 --- a/compiler/src/dmd/backend/arm/cod1.d +++ b/compiler/src/dmd/backend/arm/cod1.d @@ -77,10 +77,10 @@ void loadFromEA(ref code cs, reg_t reg, uint szw, uint szr) // LDR reg,[cs.base, #offset] assert(cs.index == NOREG); uint imm12 = cast(uint)cs.IEV1.Voffset; - if (szw == 4) imm12 >>= 2; - else if (szw == 8) imm12 >>= 3; - else assert(0); - cs.Iop = INSTR.ldr_imm_fpsimd(szw == 8 ? 3 : 2,1,imm12,cs.base,reg); + uint size, opc; + INSTR.szToSizeOpc(szw, size, opc); + imm12 /= szw; + cs.Iop = INSTR.ldr_imm_fpsimd(size,opc,imm12,cs.base,reg); } else assert(0); @@ -150,11 +150,11 @@ void storeToEA(ref code cs, reg_t reg, uint sz) { // STR reg,[cs.base, #offset] assert(cs.index == NOREG); - uint imm12 = cs.Sextend; - if (sz == 4) imm12 >>= 4; - else if (sz == 8) imm12 >>= 8; - else assert(0); - cs.Iop = INSTR.str_imm_fpsimd(sz == 8 ? 3 : 2,0,imm12,cs.base,reg); + uint imm12 = cast(uint)cs.IEV1.Voffset; + uint size, opc; + INSTR.szToSizeOpc(sz, size, opc); + imm12 /= sz; + cs.Iop = INSTR.str_imm_fpsimd(size,opc,imm12,cs.base,reg); } else assert(0); diff --git a/compiler/src/dmd/backend/arm/cod3.d b/compiler/src/dmd/backend/arm/cod3.d index 61d1b648c3..30f5b46a3a 100644 --- a/compiler/src/dmd/backend/arm/cod3.d +++ b/compiler/src/dmd/backend/arm/cod3.d @@ -349,7 +349,7 @@ void prolog_saveregs(ref CGstate cg, ref CodeBuilder cdb, regm_t topush, int cfa int xmmtopush = 0; int gptopush = popcnt(topush); // general purpose registers to save targ_size_t gpoffset = cg.pushoff + cg.BPoff; - reg_t fp; + reg_t fp; // frame pointer if (!cg.hasframe || cg.enforcealign) { gpoffset += cg.EBPtoESP; @@ -365,7 +365,7 @@ void prolog_saveregs(ref CGstate cg, ref CodeBuilder cdb, regm_t topush, int cfa const ins = (mask(reg) & INSTR.FLOATREGS) // https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html - ? INSTR.str_imm_fpsimd(3,0,cast(uint)gpoffset,fp,reg) // STR reg,[fp,#offset] + ? INSTR.str_imm_fpsimd(3,0,cast(uint)gpoffset >> 3,fp,reg) // STR reg,[fp,#offset] : INSTR.str_imm_gen(1, reg, fp, gpoffset); // STR reg,[fp,#offset] cdb.gen1(ins); @@ -416,7 +416,7 @@ private void epilog_restoreregs(ref CGstate cg, ref CodeBuilder cdb, regm_t topo const ins = (mask(reg) & INSTR.FLOATREGS) // https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html - ? INSTR.ldr_imm_fpsimd(3,1,cast(uint)gpoffset,fp,reg) // LDR reg,[fp,#offset] + ? INSTR.ldr_imm_fpsimd(3,0,cast(uint)gpoffset >> 3,fp,reg) // LDR reg,[fp,#offset] : INSTR.ldr_imm_gen(1, reg, fp, gpoffset); // LDR reg,[fp,#offset] cdb.gen1(ins); gpoffset += REGSIZE; @@ -501,11 +501,10 @@ void prolog_genvarargs(ref CGstate cg, ref CodeBuilder cdb, Symbol* sv) { if (!(mask(q) & namedargs)) // unnamed arguments would be the ... ones { + reg_t fp = (!cg.hasframe || cg.enforcealign) ? 31 : 29; // SP : BP uint offset = cast(uint)voff + 8 * 8 + (q & 31) * 16; - if (!cg.hasframe || cg.enforcealign) - cdb.gen1(INSTR.str_imm_fpsimd(0,2,offset,31,q)); // STR q,[sp,#offset] - else - cdb.gen1(INSTR.str_imm_fpsimd(0,2,offset,29,q)); + offset /= 16; // saving 128 bit Q registers + cdb.gen1(INSTR.str_imm_fpsimd(0,2,offset,fp,q)); // STR q,[sp,#offset] } } diff --git a/compiler/src/dmd/backend/arm/instr.d b/compiler/src/dmd/backend/arm/instr.d index 6160f266e0..2d5581ce4b 100644 --- a/compiler/src/dmd/backend/arm/instr.d +++ b/compiler/src/dmd/backend/arm/instr.d @@ -56,6 +56,22 @@ struct INSTR 3; // half-precision } + /* Convert size of floating point type to size,opc + * https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html + */ + static void szToSizeOpc(uint sz, ref uint size, ref uint opc) + { + switch (sz) + { + case 1: size = 0; opc = 0; break; // Bt byte + case 2: size = 1; opc = 0; break; // Ht half + case 4: size = 2; opc = 0; break; // St single + case 8: size = 3; opc = 0; break; // Dt double + case 16: size = 0; opc = 2; break; // Qt quad + default: assert(0); + } + } + /************************************ Reserved ***********************************************/ /* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#reserved */ @@ -986,24 +1002,22 @@ struct INSTR /* https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html * STR ,[,#] Unsigned offset */ - static uint str_imm_fpsimd(uint size, uint opc, uint offset, reg_t Rn, reg_t Vt) + static uint str_imm_fpsimd(uint size, uint opc, uint imm12, reg_t Rn, reg_t Vt) { + assert(imm12 < 0x1000); assert(size < 4); assert(opc < 4); - uint scale = ((opc & 2) << 1) | size; - uint imm12 = (cast(uint)offset >> scale) & 0xFFF; return ldst_pos(size,1,opc,imm12,Rn,Vt); } /* https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html * LDR ,[,#] Unsigned offset */ - static uint ldr_imm_fpsimd(uint size, uint opc, uint offset, reg_t Rn, reg_t Vt) + static uint ldr_imm_fpsimd(uint size, uint opc, uint imm12, reg_t Rn, reg_t Vt) { + assert(imm12 < 0x1000); assert(size < 4); assert(opc < 4); - uint scale = ((opc & 2) << 1) | size; - uint imm12 = (cast(uint)offset >> scale) & 0xFFF; return ldst_pos(size,1,opc,imm12,Rn,Vt); } diff --git a/compiler/src/dmd/backend/codebuilder.d b/compiler/src/dmd/backend/codebuilder.d index 628ecb8cdd..8c2ea83b54 100644 --- a/compiler/src/dmd/backend/codebuilder.d +++ b/compiler/src/dmd/backend/codebuilder.d @@ -35,7 +35,7 @@ struct CodeBuilder code** pTail; enum BADINS = 0x1234_5678; -// enum BADINS = 0xF900_0FA0; + //enum BADINS = 0xBD00_07A0; nothrow: public: diff --git a/compiler/src/dmd/backend/x86/cgcod.d b/compiler/src/dmd/backend/x86/cgcod.d index 145dc866e3..873cb23546 100644 --- a/compiler/src/dmd/backend/x86/cgcod.d +++ b/compiler/src/dmd/backend/x86/cgcod.d @@ -765,6 +765,7 @@ else if (cg.floatreg) { + assert(!cg.AArch64); uint floatregsize = config.fpxmmregs || I32 ? 16 : DOUBLESIZE; cg.Foff = alignsection(cg.regsave.off - floatregsize, STACKALIGN, bias); //printf("Foff = x%x, size = x%x\n", cast(int)cg.Foff, cast(int)floatregsize); diff --git a/compiler/src/dmd/backend/x86/cod3.d b/compiler/src/dmd/backend/x86/cod3.d index 0ab40db4c4..a3360f5e69 100644 --- a/compiler/src/dmd/backend/x86/cod3.d +++ b/compiler/src/dmd/backend/x86/cod3.d @@ -4380,11 +4380,10 @@ void prolog_loadparams(ref CodeBuilder cdb, tym_t tyf, bool pushalloc) if (tyfloating(t.Tty)) { // STR preg,[bp,#offset] - if (sz == 8) - imm >>= 3; - else if (sz == 4) - imm >>= 2; - cdb.gen1(INSTR.str_imm_fpsimd(2 + (sz == 8),0,imm,29,preg)); + uint size, opc; + INSTR.szToSizeOpc(sz, size, opc); + imm /= sz; + cdb.gen1(INSTR.str_imm_fpsimd(size,opc,imm,29,preg)); // https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html } else // STR preg,bp,#offset