mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00
add floatPost() (#21227)
This commit is contained in:
parent
8a8746f318
commit
5fcca3e152
2 changed files with 136 additions and 15 deletions
|
@ -1241,6 +1241,7 @@ void tstresult(ref CodeBuilder cdb, regm_t regm, tym_t tym, bool saveflag)
|
||||||
void fixresult(ref CodeBuilder cdb, elem* e, regm_t retregs, ref regm_t outretregs)
|
void fixresult(ref CodeBuilder cdb, elem* e, regm_t retregs, ref regm_t outretregs)
|
||||||
{
|
{
|
||||||
//printf("arm.fixresult(e = %p, retregs = %s, outretregs = %s)\n",e,regm_str(retregs),regm_str(outretregs));
|
//printf("arm.fixresult(e = %p, retregs = %s, outretregs = %s)\n",e,regm_str(retregs),regm_str(outretregs));
|
||||||
|
//elem_print(e);
|
||||||
if (outretregs == 0) return; // if don't want result
|
if (outretregs == 0) return; // if don't want result
|
||||||
assert(e && retregs); // need something to work with
|
assert(e && retregs); // need something to work with
|
||||||
regm_t forccs = outretregs & mPSW;
|
regm_t forccs = outretregs & mPSW;
|
||||||
|
@ -2068,7 +2069,7 @@ void loaddata(ref CodeBuilder cdb, elem* e, ref regm_t outretregs)
|
||||||
if (tyfloating(tym))
|
if (tyfloating(tym))
|
||||||
{
|
{
|
||||||
const vreg = allocreg(cdb, forregs, tym); // allocate floating point register
|
const vreg = allocreg(cdb, forregs, tym); // allocate floating point register
|
||||||
float value = e.Vfloat;
|
double value = e.Vfloat;
|
||||||
if (sz == 8)
|
if (sz == 8)
|
||||||
value = e.Vdouble;
|
value = e.Vdouble;
|
||||||
loadFloatRegConst(cdb,vreg,value,sz);
|
loadFloatRegConst(cdb,vreg,value,sz);
|
||||||
|
|
|
@ -38,7 +38,7 @@ import dmd.backend.ty;
|
||||||
import dmd.backend.type;
|
import dmd.backend.type;
|
||||||
import dmd.backend.x86.xmm;
|
import dmd.backend.x86.xmm;
|
||||||
import dmd.backend.arm.cod1 : loadFromEA, storeToEA, getlvalue;
|
import dmd.backend.arm.cod1 : loadFromEA, storeToEA, getlvalue;
|
||||||
import dmd.backend.arm.cod3 : conditionCode, genBranch, gentstreg, movregconst, COND;
|
import dmd.backend.arm.cod3 : conditionCode, genBranch, gentstreg, movregconst, COND, loadFloatRegConst;
|
||||||
import dmd.backend.arm.instr;
|
import dmd.backend.arm.instr;
|
||||||
|
|
||||||
nothrow:
|
nothrow:
|
||||||
|
@ -1791,27 +1791,23 @@ void cdpost(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
||||||
cdaddass(cgstate,cdb,e,pretregs);
|
cdaddass(cgstate,cdb,e,pretregs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const tym_t tyml = tybasic(e.E1.Ety);
|
|
||||||
const sz = _tysize[tyml];
|
|
||||||
elem* e2 = e.E2;
|
|
||||||
|
|
||||||
if (0 && tyfloating(tyml)) // TODO AArch64
|
const tym_t tyml = tybasic(e.E1.Ety);
|
||||||
|
if (tyfloating(tyml))
|
||||||
{
|
{
|
||||||
if (config.fpxmmregs && tyxmmreg(tyml) &&
|
floatPost(cg, cdb, e, pretregs);
|
||||||
!tycomplex(tyml) // SIMD code is not set up to deal with complex
|
|
||||||
)
|
|
||||||
{
|
|
||||||
xmmpost(cdb,e,pretregs);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (0 && tyxmmreg(tyml)) // TODO AArch64
|
if (0 && tyxmmreg(tyml)) // TODO AArch64
|
||||||
{
|
{
|
||||||
xmmpost(cdb,e,pretregs);
|
xmmpost(cdb,e,pretregs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sz = _tysize[tyml];
|
||||||
|
elem* e2 = e.E2;
|
||||||
assert(e2.Eoper == OPconst);
|
assert(e2.Eoper == OPconst);
|
||||||
|
|
||||||
regm_t possregs = cg.allregs;
|
regm_t possregs = cg.allregs;
|
||||||
code cs;
|
code cs;
|
||||||
getlvalue(cdb,cs,e.E1,0);
|
getlvalue(cdb,cs,e.E1,0);
|
||||||
|
@ -1915,6 +1911,130 @@ void cdpost(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* Do OPpostinc and OPpostdec on floating point lvalue
|
||||||
|
*/
|
||||||
|
@trusted
|
||||||
|
void floatPost(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
||||||
|
{
|
||||||
|
//printf("floatPost(pretregs = %s)\n", regm_str(pretregs));
|
||||||
|
//elem_print(e);
|
||||||
|
|
||||||
|
// Much similarity to xmmpost()
|
||||||
|
|
||||||
|
elem* e1 = e.E1;
|
||||||
|
elem* e2 = e.E2;
|
||||||
|
const tym_t ty1 = tybasic(e.E1.Ety);
|
||||||
|
const sz = _tysize[ty1];
|
||||||
|
const ftype = INSTR.szToFtype(sz);
|
||||||
|
|
||||||
|
regm_t retregs;
|
||||||
|
reg_t reg;
|
||||||
|
bool regvar = false;
|
||||||
|
if (config.flags4 & CFG4optimized)
|
||||||
|
{
|
||||||
|
// Be careful of cases like (x = x+x+x). We cannot evaluate in
|
||||||
|
// x if x is in a register.
|
||||||
|
reg_t varreg;
|
||||||
|
regm_t varregm;
|
||||||
|
if (isregvar(e1,varregm,varreg) && // if lvalue is register variable
|
||||||
|
doinreg(e1.Vsym,e2) // and we can compute directly into it
|
||||||
|
)
|
||||||
|
{
|
||||||
|
regvar = true;
|
||||||
|
retregs = varregm;
|
||||||
|
reg = varreg; // evaluate directly in target register
|
||||||
|
getregs(cdb,retregs); // destroy these regs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code cs;
|
||||||
|
if (!regvar)
|
||||||
|
{
|
||||||
|
getlvalue(cdb,cs,e1,0,RM.rw); // get EA
|
||||||
|
retregs = INSTR.FLOATREGS & ~pretregs;
|
||||||
|
if (!retregs)
|
||||||
|
retregs = INSTR.FLOATREGS;
|
||||||
|
reg = allocreg(cdb,retregs,ty1);
|
||||||
|
loadFromEA(cs,reg,sz == 8 ? 8 : 4,sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regvar && pretregs == mPSW)
|
||||||
|
{
|
||||||
|
tstresult(cdb, mask(reg),ty1,false);
|
||||||
|
|
||||||
|
// If lvalue is a register variable, mark it as modified
|
||||||
|
getregs(cdb,reg);
|
||||||
|
|
||||||
|
regm_t vretregs = INSTR.FLOATREGS & ~mask(cs.reg);
|
||||||
|
reg_t vreg = allocreg(cdb,vretregs,ty1);
|
||||||
|
double value = sz == 8 ? e2.Vdouble : e2.Vfloat;
|
||||||
|
loadFloatRegConst(cdb,vreg,value,sz); // FMOV vreg,value
|
||||||
|
|
||||||
|
switch (e.Eoper)
|
||||||
|
{
|
||||||
|
case OPpostinc:
|
||||||
|
cdb.gen1(INSTR.fadd_float(ftype,reg,vreg,reg)); // FADD Rd,Rn,Rm
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPpostdec:
|
||||||
|
cdb.gen1(INSTR.fsub_float(ftype,reg,vreg,reg)); // FSUB Rd,Rn,Rm
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
freenode(e2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result register
|
||||||
|
regm_t resultregs = INSTR.FLOATREGS & pretregs & ~retregs;
|
||||||
|
if (!resultregs)
|
||||||
|
resultregs = INSTR.FLOATREGS & ~retregs;
|
||||||
|
const resultreg = allocreg(cdb,resultregs, ty1);
|
||||||
|
|
||||||
|
cdb.gen1(INSTR.fmov(ftype,reg,resultreg)); // FMOV resultreg,reg
|
||||||
|
|
||||||
|
regm_t vretregs = INSTR.FLOATREGS & ~mask(reg) & ~mask(resultreg);
|
||||||
|
reg_t vreg = allocreg(cdb,vretregs,ty1);
|
||||||
|
double value = sz == 8 ? e2.Vdouble : e2.Vfloat;
|
||||||
|
loadFloatRegConst(cdb,vreg,value,sz); // FMOV vreg,value
|
||||||
|
|
||||||
|
switch (e.Eoper)
|
||||||
|
{
|
||||||
|
case OPpostinc:
|
||||||
|
cdb.gen1(INSTR.fadd_float(ftype,reg,vreg,reg)); // FADD Rd,Rn,Rm
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPpostdec:
|
||||||
|
cdb.gen1(INSTR.fsub_float(ftype,reg,vreg,reg)); // FSUB Rd,Rn,Rm
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!regvar)
|
||||||
|
{
|
||||||
|
storeToEA(cs,reg,sz);
|
||||||
|
cdb.gen(&cs); // STR reg,EA
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e1.Ecount || // if lvalue is a CSE or
|
||||||
|
regvar) // rvalue can't be a CSE
|
||||||
|
{
|
||||||
|
getregs_imm(cdb,retregs); // necessary if both lvalue and
|
||||||
|
// rvalue are CSEs (since a reg
|
||||||
|
// can hold only one e at a time)
|
||||||
|
cssave(e1,retregs,!OTleaf(e1.Eoper)); // if lvalue is a CSE
|
||||||
|
}
|
||||||
|
|
||||||
|
fixresult(cdb,e,resultregs,pretregs);
|
||||||
|
freenode(e1);
|
||||||
|
}
|
||||||
|
|
||||||
// cddctor
|
// cddctor
|
||||||
// cdddtor
|
// cdddtor
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue