mirror of
https://github.com/dlang/dmd.git
synced 2025-04-25 12:40:11 +03:00
fix ldr/str floating point registers (#21235)
This commit is contained in:
parent
d0cf2c7117
commit
c30def82bd
6 changed files with 41 additions and 28 deletions
|
@ -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);
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <Vt>,[<Xn|SP>,#<simm>] 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 <Vt>,[<Xn|SP>,#<simm>] 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ struct CodeBuilder
|
|||
code** pTail;
|
||||
|
||||
enum BADINS = 0x1234_5678;
|
||||
// enum BADINS = 0xF900_0FA0;
|
||||
//enum BADINS = 0xBD00_07A0;
|
||||
|
||||
nothrow:
|
||||
public:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue