mirror of
https://github.com/dlang/dmd.git
synced 2025-04-27 05:30:13 +03:00
implement cdnot() for AArch64
This commit is contained in:
parent
9709375650
commit
3b863b9c28
5 changed files with 106 additions and 3 deletions
|
@ -321,6 +321,95 @@ void cddiv(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
||||||
fixresult(cdb,e,retregs,pretregs);
|
fixresult(cdb,e,retregs,pretregs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************
|
||||||
|
* Handle OPnot and OPbool.
|
||||||
|
* Generate:
|
||||||
|
* c: [evaluate e1]
|
||||||
|
* cfalse: [save reg code]
|
||||||
|
* clr reg
|
||||||
|
* jmp cnop
|
||||||
|
* ctrue: [save reg code]
|
||||||
|
* clr reg
|
||||||
|
* inc reg
|
||||||
|
* cnop: nop
|
||||||
|
*/
|
||||||
|
|
||||||
|
@trusted
|
||||||
|
void cdnot(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
||||||
|
{
|
||||||
|
//printf("cdnot()\n");
|
||||||
|
reg_t reg;
|
||||||
|
regm_t forflags;
|
||||||
|
elem* e1 = e.E1;
|
||||||
|
|
||||||
|
if (pretregs == 0 ||
|
||||||
|
pretregs == mPSW)
|
||||||
|
{
|
||||||
|
codelem(cgstate,cdb,e1,pretregs,false); // evaluate e1 for cc
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OPER op = e.Eoper;
|
||||||
|
uint sz = tysize(e1.Ety);
|
||||||
|
|
||||||
|
if (tyfloating(e1.Ety))
|
||||||
|
{
|
||||||
|
code* cnop = gen1(null, INSTR.nop);
|
||||||
|
code* ctrue = gen1(null, INSTR.nop);
|
||||||
|
logexp(cdb,e.E1,(op == OPnot) ? false : true,FL.code,ctrue);
|
||||||
|
forflags = pretregs & mPSW;
|
||||||
|
if (I64 && sz == 8)
|
||||||
|
forflags |= 64;
|
||||||
|
assert(tysize(e.Ety) <= REGSIZE); // result better be int
|
||||||
|
CodeBuilder cdbfalse;
|
||||||
|
cdbfalse.ctor();
|
||||||
|
reg = allocreg(cdbfalse,pretregs,e.Ety); // allocate reg for result
|
||||||
|
code* cfalse = cdbfalse.finish();
|
||||||
|
CodeBuilder cdbtrue;
|
||||||
|
cdbtrue.ctor();
|
||||||
|
cdbtrue.append(ctrue);
|
||||||
|
for (code* c1 = cfalse; c1; c1 = code_next(c1))
|
||||||
|
cdbtrue.gen(c1); // duplicate reg save code
|
||||||
|
CodeBuilder cdbfalse2;
|
||||||
|
cdbfalse2.ctor();
|
||||||
|
movregconst(cdbfalse2,reg,0,forflags); // mov 0 into reg
|
||||||
|
cgstate.regcon.immed.mval &= ~mask(reg); // mark reg as unavail
|
||||||
|
movregconst(cdbtrue,reg,1,forflags); // mov 1 into reg
|
||||||
|
cgstate.regcon.immed.mval &= ~mask(reg); // mark reg as unavail
|
||||||
|
genBranch(cdbfalse2,COND.al,FL.code,cast(block*) cnop); // JMP cnop
|
||||||
|
cdb.append(cfalse);
|
||||||
|
cdb.append(cdbfalse2);
|
||||||
|
cdb.append(cdbtrue);
|
||||||
|
cdb.append(cnop);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const posregs = cgstate.allregs;
|
||||||
|
regm_t retregs1 = posregs;
|
||||||
|
codelem(cgstate,cdb,e.E1,retregs1,false);
|
||||||
|
const R1 = findreg(retregs1); // source register
|
||||||
|
|
||||||
|
regm_t retregs = pretregs & cg.allregs;
|
||||||
|
if (retregs == 0) // if no return regs speced
|
||||||
|
// (like if wanted flags only)
|
||||||
|
retregs = ALLREGS & posregs; // give us some
|
||||||
|
const tym = tybasic(e.Ety);
|
||||||
|
reg_t Rd = allocreg(cdb, retregs, tym); // destination register
|
||||||
|
|
||||||
|
uint sf = sz == 8;
|
||||||
|
|
||||||
|
cdb.gen1(INSTR.cmp_imm(sf,0,0,R1)); // CMP R1,#0
|
||||||
|
COND cond = op == OPnot ? COND.ne : COND.eq;
|
||||||
|
cdb.gen1(INSTR.cset(sf,cond,Rd)); // CSET Rd,EQ
|
||||||
|
|
||||||
|
uint N,immr,imms;
|
||||||
|
assert(encodeNImmrImms(0xFF,N,immr,imms));
|
||||||
|
cdb.gen1(INSTR.log_imm(0,0,0,immr,imms,Rd,Rd)); // AND Rd,Rd,#0xFF
|
||||||
|
|
||||||
|
fixresult(cdb,e,retregs,pretregs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
* Complement operator
|
* Complement operator
|
||||||
*/
|
*/
|
||||||
|
@ -328,7 +417,7 @@ void cddiv(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
||||||
@trusted
|
@trusted
|
||||||
void cdcom(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
void cdcom(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
||||||
{
|
{
|
||||||
//printf("cdcom()\n");
|
printf("cdcom()\n");
|
||||||
//elem_print(e);
|
//elem_print(e);
|
||||||
if (pretregs == 0)
|
if (pretregs == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1681,7 +1681,7 @@ void disassemble(uint c) @trusted
|
||||||
if (op * 2 + (op2 & 1) == 1 &&
|
if (op * 2 + (op2 & 1) == 1 &&
|
||||||
Rm == 0x1F && Rn == 0x1F)
|
Rm == 0x1F && Rn == 0x1F)
|
||||||
{
|
{
|
||||||
p1 = "cset";
|
p1 = "cset"; // https://www.scs.stanford.edu/~zyedidia/arm64/cset_csinc.html
|
||||||
p3 = condstring[cond ^ 1];
|
p3 = condstring[cond ^ 1];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -492,7 +492,7 @@ struct INSTR
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Conditional select
|
/* Conditional select
|
||||||
* CSEL/CSINC/CSINV/CSNEG
|
* CSEL/CSINC/CSINV/CSNEG/CSET
|
||||||
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#condsel
|
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#condsel
|
||||||
*/
|
*/
|
||||||
static uint condsel(uint sf, uint op, uint S, ubyte Rm, uint cond, uint o2, ubyte Rn, ubyte Rd)
|
static uint condsel(uint sf, uint op, uint S, ubyte Rm, uint cond, uint o2, ubyte Rn, ubyte Rd)
|
||||||
|
@ -501,6 +501,14 @@ struct INSTR
|
||||||
return (sf << 31) | (op << 30) | (S << 29) | (0xD4 << 21) | (Rm << 16) | (cond << 12) | (o2 << 10) | (Rn << 5) | Rd;
|
return (sf << 31) | (op << 30) | (S << 29) | (0xD4 << 21) | (Rm << 16) | (cond << 12) | (o2 << 10) | (Rn << 5) | Rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CSET Rd,<invcond> https://www.scs.stanford.edu/~zyedidia/arm64/cset_csinc.html
|
||||||
|
*/
|
||||||
|
static uint cset(uint sf, uint cond, reg_t Rd)
|
||||||
|
{
|
||||||
|
assert(cond < 0xE);
|
||||||
|
return condsel(sf, 0, 0, 31, cond, 1, 31, Rd);
|
||||||
|
}
|
||||||
|
|
||||||
/* Data-processing (3 source)
|
/* Data-processing (3 source)
|
||||||
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#dp_3src
|
* https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#dp_3src
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1993,6 +1993,9 @@ void cddiv(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
||||||
@trusted
|
@trusted
|
||||||
void cdnot(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
void cdnot(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
|
||||||
{
|
{
|
||||||
|
if (cg.AArch64)
|
||||||
|
return dmd.backend.arm.cod2.cdnot(cg, cdb, e, pretregs);
|
||||||
|
|
||||||
//printf("cdnot()\n");
|
//printf("cdnot()\n");
|
||||||
reg_t reg;
|
reg_t reg;
|
||||||
regm_t forflags;
|
regm_t forflags;
|
||||||
|
|
|
@ -533,6 +533,9 @@ void cod3_stackadj(ref CodeBuilder cdb, int nbytes)
|
||||||
//printf("cod3_stackadj(%d)\n", nbytes);
|
//printf("cod3_stackadj(%d)\n", nbytes);
|
||||||
if (cgstate.AArch64)
|
if (cgstate.AArch64)
|
||||||
{
|
{
|
||||||
|
if (nbytes == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
// https://www.scs.stanford.edu/~zyedidia/arm64/sub_addsub_imm.html
|
// https://www.scs.stanford.edu/~zyedidia/arm64/sub_addsub_imm.html
|
||||||
// add/sub Xd,Xn,#imm{,shift}
|
// add/sub Xd,Xn,#imm{,shift}
|
||||||
uint sf = 1;
|
uint sf = 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue