mirror of
https://github.com/dlang/dmd.git
synced 2025-04-25 20:50:41 +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]
|
// LDR reg,[cs.base, #offset]
|
||||||
assert(cs.index == NOREG);
|
assert(cs.index == NOREG);
|
||||||
uint imm12 = cast(uint)cs.IEV1.Voffset;
|
uint imm12 = cast(uint)cs.IEV1.Voffset;
|
||||||
if (szw == 4) imm12 >>= 2;
|
uint size, opc;
|
||||||
else if (szw == 8) imm12 >>= 3;
|
INSTR.szToSizeOpc(szw, size, opc);
|
||||||
else assert(0);
|
imm12 /= szw;
|
||||||
cs.Iop = INSTR.ldr_imm_fpsimd(szw == 8 ? 3 : 2,1,imm12,cs.base,reg);
|
cs.Iop = INSTR.ldr_imm_fpsimd(size,opc,imm12,cs.base,reg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -150,11 +150,11 @@ void storeToEA(ref code cs, reg_t reg, uint sz)
|
||||||
{
|
{
|
||||||
// STR reg,[cs.base, #offset]
|
// STR reg,[cs.base, #offset]
|
||||||
assert(cs.index == NOREG);
|
assert(cs.index == NOREG);
|
||||||
uint imm12 = cs.Sextend;
|
uint imm12 = cast(uint)cs.IEV1.Voffset;
|
||||||
if (sz == 4) imm12 >>= 4;
|
uint size, opc;
|
||||||
else if (sz == 8) imm12 >>= 8;
|
INSTR.szToSizeOpc(sz, size, opc);
|
||||||
else assert(0);
|
imm12 /= sz;
|
||||||
cs.Iop = INSTR.str_imm_fpsimd(sz == 8 ? 3 : 2,0,imm12,cs.base,reg);
|
cs.Iop = INSTR.str_imm_fpsimd(size,opc,imm12,cs.base,reg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
|
@ -349,7 +349,7 @@ void prolog_saveregs(ref CGstate cg, ref CodeBuilder cdb, regm_t topush, int cfa
|
||||||
int xmmtopush = 0;
|
int xmmtopush = 0;
|
||||||
int gptopush = popcnt(topush); // general purpose registers to save
|
int gptopush = popcnt(topush); // general purpose registers to save
|
||||||
targ_size_t gpoffset = cg.pushoff + cg.BPoff;
|
targ_size_t gpoffset = cg.pushoff + cg.BPoff;
|
||||||
reg_t fp;
|
reg_t fp; // frame pointer
|
||||||
if (!cg.hasframe || cg.enforcealign)
|
if (!cg.hasframe || cg.enforcealign)
|
||||||
{
|
{
|
||||||
gpoffset += cg.EBPtoESP;
|
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)
|
const ins = (mask(reg) & INSTR.FLOATREGS)
|
||||||
// https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
|
// 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]
|
: INSTR.str_imm_gen(1, reg, fp, gpoffset); // STR reg,[fp,#offset]
|
||||||
cdb.gen1(ins);
|
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)
|
const ins = (mask(reg) & INSTR.FLOATREGS)
|
||||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html
|
// 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]
|
: INSTR.ldr_imm_gen(1, reg, fp, gpoffset); // LDR reg,[fp,#offset]
|
||||||
cdb.gen1(ins);
|
cdb.gen1(ins);
|
||||||
gpoffset += REGSIZE;
|
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
|
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;
|
uint offset = cast(uint)voff + 8 * 8 + (q & 31) * 16;
|
||||||
if (!cg.hasframe || cg.enforcealign)
|
offset /= 16; // saving 128 bit Q registers
|
||||||
cdb.gen1(INSTR.str_imm_fpsimd(0,2,offset,31,q)); // STR q,[sp,#offset]
|
cdb.gen1(INSTR.str_imm_fpsimd(0,2,offset,fp,q)); // STR q,[sp,#offset]
|
||||||
else
|
|
||||||
cdb.gen1(INSTR.str_imm_fpsimd(0,2,offset,29,q));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,22 @@ struct INSTR
|
||||||
3; // half-precision
|
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 ***********************************************/
|
/************************************ Reserved ***********************************************/
|
||||||
/* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#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
|
/* https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
|
||||||
* STR <Vt>,[<Xn|SP>,#<simm>] Unsigned offset
|
* 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(size < 4);
|
||||||
assert(opc < 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);
|
return ldst_pos(size,1,opc,imm12,Rn,Vt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html
|
/* https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html
|
||||||
* LDR <Vt>,[<Xn|SP>,#<simm>] Unsigned offset
|
* 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(size < 4);
|
||||||
assert(opc < 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);
|
return ldst_pos(size,1,opc,imm12,Rn,Vt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ struct CodeBuilder
|
||||||
code** pTail;
|
code** pTail;
|
||||||
|
|
||||||
enum BADINS = 0x1234_5678;
|
enum BADINS = 0x1234_5678;
|
||||||
// enum BADINS = 0xF900_0FA0;
|
//enum BADINS = 0xBD00_07A0;
|
||||||
|
|
||||||
nothrow:
|
nothrow:
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -765,6 +765,7 @@ else
|
||||||
|
|
||||||
if (cg.floatreg)
|
if (cg.floatreg)
|
||||||
{
|
{
|
||||||
|
assert(!cg.AArch64);
|
||||||
uint floatregsize = config.fpxmmregs || I32 ? 16 : DOUBLESIZE;
|
uint floatregsize = config.fpxmmregs || I32 ? 16 : DOUBLESIZE;
|
||||||
cg.Foff = alignsection(cg.regsave.off - floatregsize, STACKALIGN, bias);
|
cg.Foff = alignsection(cg.regsave.off - floatregsize, STACKALIGN, bias);
|
||||||
//printf("Foff = x%x, size = x%x\n", cast(int)cg.Foff, cast(int)floatregsize);
|
//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))
|
if (tyfloating(t.Tty))
|
||||||
{
|
{
|
||||||
// STR preg,[bp,#offset]
|
// STR preg,[bp,#offset]
|
||||||
if (sz == 8)
|
uint size, opc;
|
||||||
imm >>= 3;
|
INSTR.szToSizeOpc(sz, size, opc);
|
||||||
else if (sz == 4)
|
imm /= sz;
|
||||||
imm >>= 2;
|
cdb.gen1(INSTR.str_imm_fpsimd(size,opc,imm,29,preg)); // https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
|
||||||
cdb.gen1(INSTR.str_imm_fpsimd(2 + (sz == 8),0,imm,29,preg));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// STR preg,bp,#offset
|
// STR preg,bp,#offset
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue