implement cdnot() for AArch64

This commit is contained in:
Walter Bright 2025-01-28 00:24:54 -08:00 committed by The Dlang Bot
parent 9709375650
commit 3b863b9c28
5 changed files with 106 additions and 3 deletions

View file

@ -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)
{ {

View file

@ -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

View file

@ -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
*/ */

View file

@ -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;

View file

@ -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;