Skip to content

cdmemset() for AArch64 #21508

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
287 changes: 287 additions & 0 deletions compiler/src/dmd/backend/arm/cod2.d
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,293 @@
fixresult(cdb,e,retregs,pretregs);
}

/*********************************
* Generate code for memset(s,value,numbytes) intrinsic.
* (s OPmemset (numbytes OPparam value))
*/

@trusted
void cdmemset(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
{
//printf("cdmemset(pretregs = %s)\n", regm_str(pretregs));
elem* e2 = e.E2;
assert(e2.Eoper == OPparam);

Check warning on line 1176 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1175-L1176

Added lines #L1175 - L1176 were not covered by tests

elem* evalue = e2.E2;
elem* enumbytes = e2.E1;

Check warning on line 1179 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1178-L1179

Added lines #L1178 - L1179 were not covered by tests

const sz = tysize(evalue.Ety);
if (sz > 1)

Check warning on line 1182 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1181-L1182

Added lines #L1181 - L1182 were not covered by tests
{
cdmemsetn(cg, cdb, e, pretregs);
return;

Check warning on line 1185 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1184-L1185

Added lines #L1184 - L1185 were not covered by tests
}

bool valueIsConst = false;
targ_size_t value;
if (evalue.Eoper == OPconst)

Check warning on line 1190 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1188-L1190

Added lines #L1188 - L1190 were not covered by tests
{
value = el_tolong(evalue) & 0xFF;
value |= value << 8;
value |= value << 16;
value |= value << 32;
valueIsConst = true;

Check warning on line 1196 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1192-L1196

Added lines #L1192 - L1196 were not covered by tests
}
else if (evalue.Eoper == OPstrpar) // happens if evalue is a struct of 0 size

Check warning on line 1198 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1198

Added line #L1198 was not covered by tests
{
value = 0;
valueIsConst = true;

Check warning on line 1201 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1200-L1201

Added lines #L1200 - L1201 were not covered by tests
}
else
value = 0xDEADBEEF; // stop annoying false positives that value is not inited

Check warning on line 1204 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1204

Added line #L1204 was not covered by tests

// Get nbytes into CX
regm_t nbytesregs = 0;
if (enumbytes.Eoper != OPconst)

Check warning on line 1208 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1207-L1208

Added lines #L1207 - L1208 were not covered by tests
{
nbytesregs = cgstate.allregs & ~pretregs;
if (!nbytesregs)
nbytesregs = cgstate.allregs;
codelem(cgstate,cdb,enumbytes,nbytesregs,false);

Check warning on line 1213 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1210-L1213

Added lines #L1210 - L1213 were not covered by tests
}

// Get value into valuereg
regm_t valueregs;
reg_t valuereg;
if (valueIsConst)

Check warning on line 1219 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1217-L1219

Added lines #L1217 - L1219 were not covered by tests
{
if (value == 0)

Check warning on line 1221 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1221

Added line #L1221 was not covered by tests
{
valueregs = 0;
valuereg = 0x1F; // xzr

Check warning on line 1224 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1223-L1224

Added lines #L1223 - L1224 were not covered by tests
}
else
{
valueregs = cgstate.allregs & ~(pretregs | nbytesregs);
if (!valueregs)
valueregs = cgstate.allregs & ~nbytesregs;
regwithvalue(cdb, valueregs, value, 64);
getregs(cdb, valueregs);
valuereg = findreg(valueregs);
cgstate.regimmed_set(valuereg, value);

Check warning on line 1234 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1228-L1234

Added lines #L1228 - L1234 were not covered by tests
}
freenode(evalue);

Check warning on line 1236 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1236

Added line #L1236 was not covered by tests
}
else
{
scodelem(cgstate,cdb,evalue,valueregs,nbytesregs,false);

Check warning on line 1240 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1240

Added line #L1240 was not covered by tests

valuereg = findreg(valueregs);
getregs(cdb,valueregs);

Check warning on line 1243 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1242-L1243

Added lines #L1242 - L1243 were not covered by tests

regm_t regm = cgstate.allregs & ~(valueregs | nbytesregs);
const r = regwithvalue(cdb,regm,cast(targ_size_t)0x01010101_01010101,64); // MOV r,0x01010101_01010101
cdb.gen2(0x0FAF,modregrmx(3,valuereg,r)); // IMUL valuereg,r

Check warning on line 1247 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1245-L1247

Added lines #L1245 - L1247 were not covered by tests
}
freenode(e2);

Check warning on line 1249 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1249

Added line #L1249 was not covered by tests

// Get destination into dstreg
regm_t dstregs = cgstate.allregs & ~(nbytesregs | valueregs);
scodelem(cgstate,cdb,e.E1,dstregs,nbytesregs | valueregs,false);
reg_t dstreg = findreg(dstregs);

Check warning on line 1254 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1252-L1254

Added lines #L1252 - L1254 were not covered by tests

regm_t retregs;
if (pretregs) // if need return value

Check warning on line 1257 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1256-L1257

Added lines #L1256 - L1257 were not covered by tests
{
retregs = pretregs & ~(nbytesregs | valueregs | dstregs);
if (!retregs)
retregs = cgstate.allregs & ~(nbytesregs | valueregs | dstregs);
reg_t retreg = allocreg(cdb,retregs,TYnptr);
genmovreg(cdb,retreg,dstreg); // MOV retreg,dstreg

Check warning on line 1263 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1259-L1263

Added lines #L1259 - L1263 were not covered by tests
}

if (enumbytes.Eoper == OPconst)

Check warning on line 1266 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1266

Added line #L1266 was not covered by tests
{
uint numbytes = cast(uint)el_tolong(enumbytes);
if (const n = numbytes & ~(REGSIZE - 1))

Check warning on line 1269 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1268-L1269

Added lines #L1268 - L1269 were not covered by tests
{
regm_t limits = cgstate.allregs & ~(nbytesregs | valueregs | dstregs | retregs);
reg_t limit = regwithvalue(cdb,limits,n / REGSIZE,64); // MOV limit,#n / REGSIZE
cdb.gen1(INSTR.addsub_ext(1,0,0,0,limit,6,3,dstreg,limit)); // ADD limit,dstreg,limit,UXTW #3

Check warning on line 1273 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1271-L1273

Added lines #L1271 - L1273 were not covered by tests

code* cnop = gen1(null, INSTR.nop);
cdb.append(cnop);

Check warning on line 1276 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1275-L1276

Added lines #L1275 - L1276 were not covered by tests

cdb.gen1(INSTR.ldst_immpost(3,0,0,8,dstreg,valuereg)); // STR valuereg,[dstreg],#8 // *dstreg++ = valuereg
cdb.gen1(INSTR.cmp_shift(1,dstreg,0,0,limit)); // CMP limit,dstreg
genBranch(cdb,COND.ne,FL.code,cast(block*)cnop); // JNE cnop

Check warning on line 1280 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1278-L1280

Added lines #L1278 - L1280 were not covered by tests
}

auto remainder = numbytes & (REGSIZE - 1);
if (remainder >= 4)

Check warning on line 1284 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1283-L1284

Added lines #L1283 - L1284 were not covered by tests
{
cdb.gen1(INSTR.ldst_immpost(3,0,0,4,dstreg,valuereg)); // STR valuereg,[dstreg],#4 // *dstreg++ = valuereg
remainder -= 4;

Check warning on line 1287 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1286-L1287

Added lines #L1286 - L1287 were not covered by tests
}
for (; remainder; --remainder)
cdb.gen1(INSTR.ldst_immpost(3,0,0,1,dstreg,valuereg)); // STR valuereg,[dstreg],#0 // *dstreg++ = valuereg
fixresult(cdb,e,retregs,pretregs);
return;

Check warning on line 1292 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1289-L1292

Added lines #L1289 - L1292 were not covered by tests
}

// TODO AArch64

getregs(cdb,mDI | mCX);

Check warning on line 1297 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1297

Added line #L1297 was not covered by tests

/* MOV sreg,ECX
SHR ECX,n
REP
STOSD/Q

ADC ECX,ECX
REP
STOSD

MOV ECX,sreg
AND ECX,3
REP
STOSB
*/
regm_t regs = cgstate.allregs & (pretregs ? ~(mAX|mBX|mCX|mDI) : ~(mAX|mCX|mDI));
const sreg = allocreg(cdb,regs,TYint);
genregs(cdb,0x89,CX,sreg); // MOV sreg,ECX (32 bits only)

Check warning on line 1315 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1313-L1315

Added lines #L1313 - L1315 were not covered by tests

const n = I64 ? 3 : 2;
cdb.genc2(0xC1, modregrm(3,5,CX), n); // SHR ECX,n

Check warning on line 1318 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1317-L1318

Added lines #L1317 - L1318 were not covered by tests

cdb.gen1(0xF3); // REP
cdb.gen1(STOS); // STOSD/Q
if (I64)
code_orrex(cdb.last(), REX_W);

Check warning on line 1323 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1320-L1323

Added lines #L1320 - L1323 were not covered by tests

if (I64)

Check warning on line 1325 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1325

Added line #L1325 was not covered by tests
{
cdb.gen2(0x11,modregrm(3,CX,CX)); // ADC ECX,ECX
cdb.gen1(0xF3); // REP
cdb.gen1(STOS); // STOSD

Check warning on line 1329 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1327-L1329

Added lines #L1327 - L1329 were not covered by tests
}

genregs(cdb,0x89,sreg,CX); // MOV ECX,sreg (32 bits only)
cdb.genc2(0x81, modregrm(3,4,CX), 3); // AND ECX,3
cdb.gen1(0xF3); // REP
cdb.gen1(STOSB); // STOSB

Check warning on line 1335 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1332-L1335

Added lines #L1332 - L1335 were not covered by tests

cgstate.regimmed_set(CX, 0); // CX is now 0
fixresult(cdb,e,mES|mBX,pretregs);

Check warning on line 1338 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1337-L1338

Added lines #L1337 - L1338 were not covered by tests
}

/***********************************************
* Do memset for values larger than a byte.
* Has many similarities to cod4.cdeq().
* Doesn't work for 16 bit code.
*/
@trusted
private void cdmemsetn(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
{
//printf("cdmemsetn(pretregs = %s)\n", regm_str(pretregs));
elem* e2 = e.E2;
assert(e2.Eoper == OPparam);

Check warning on line 1351 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1350-L1351

Added lines #L1350 - L1351 were not covered by tests

elem* evalue = e2.E2;
elem* enelems = e2.E1;

Check warning on line 1354 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1353-L1354

Added lines #L1353 - L1354 were not covered by tests

tym_t tymv = tybasic(evalue.Ety);
const sz = tysize(evalue.Ety);
assert(cast(int)sz > 1);

Check warning on line 1358 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1356-L1358

Added lines #L1356 - L1358 were not covered by tests

if (tyxmmreg(tymv) && config.fpxmmregs)

Check warning on line 1360 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1360

Added line #L1360 was not covered by tests
assert(0); // fix later
if (tyfloating(tymv) && config.inline8087)

Check warning on line 1362 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1362

Added line #L1362 was not covered by tests
assert(0); // fix later

const grex = I64 ? (REX_W << 16) : 0;

Check warning on line 1365 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1365

Added line #L1365 was not covered by tests

// get the count of elems into CX
regm_t mregcx = mCX;
codelem(cgstate,cdb,enelems,mregcx,false);

Check warning on line 1369 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1368-L1369

Added lines #L1368 - L1369 were not covered by tests

// Get value into AX
regm_t retregs3 = cgstate.allregs & ~mregcx;
if (sz == 2 * REGSIZE)
retregs3 &= ~(mBP | IDXREGS); // BP cannot be used for register pair,

Check warning on line 1374 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1372-L1374

Added lines #L1372 - L1374 were not covered by tests
// IDXREGS could deplete index regs - see sdtor.d test14815()
scodelem(cgstate,cdb,evalue,retregs3,mregcx,false);

Check warning on line 1376 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1376

Added line #L1376 was not covered by tests

/* Necessary because if evalue calls a function, and that function never returns,
* it doesn't affect registers. Which means those registers can be used for enregistering
* variables, and next pass fails because it can't use those registers, and so cannot
* allocate registers for retregs3. See ice11596.d
*/
useregs(retregs3);

Check warning on line 1383 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1383

Added line #L1383 was not covered by tests

reg_t valreg = findreg(retregs3);
reg_t valreghi;
if (sz == 2 * REGSIZE)

Check warning on line 1387 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1385-L1387

Added lines #L1385 - L1387 were not covered by tests
{
valreg = findreglsw(retregs3);
valreghi = findregmsw(retregs3);

Check warning on line 1390 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1389-L1390

Added lines #L1389 - L1390 were not covered by tests
}

freenode(e2);

Check warning on line 1393 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1393

Added line #L1393 was not covered by tests

// Get s into ES:DI
regm_t mregidx = IDXREGS & ~(mregcx | retregs3);
assert(mregidx);
tym_t ty1 = tybasic(e.E1.Ety);
if (!tyreg(ty1))
mregidx |= mES;
scodelem(cgstate,cdb,e.E1,mregidx,mregcx | retregs3,false);
reg_t idxreg = findreg(mregidx);

Check warning on line 1402 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1396-L1402

Added lines #L1396 - L1402 were not covered by tests

regm_t mregbx = 0;
if (pretregs) // if need return value

Check warning on line 1405 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1404-L1405

Added lines #L1404 - L1405 were not covered by tests
{
mregbx = pretregs & ~(mregidx | mregcx | retregs3);
if (!mregbx)
mregbx = cgstate.allregs & ~(mregidx | mregcx | retregs3);
const regbx = allocreg(cdb, mregbx, TYnptr);
getregs(cdb, mregbx);
genmovreg(cdb,regbx,idxreg); // MOV BX,DI

Check warning on line 1412 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1407-L1412

Added lines #L1407 - L1412 were not covered by tests
}

getregs(cdb,mask(idxreg) | mCX); // modify DI and CX

Check warning on line 1415 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1415

Added line #L1415 was not covered by tests

/* Generate:
* JCXZ L1
* L2:
* MOV [idxreg],AX
* ADD idxreg,sz
* LOOP L2
* L1:
* NOP
*/
code* c1 = gennop(null);
genjmp(cdb, JCXZ, FL.code, cast(block*)c1);
code cs;
buildEA(&cs,idxreg,-1,1,0);
cs.Iop = 0x89;
if (!I16 && sz == 2)
cs.Iflags |= CFopsize;
if (I64 && sz == 8)
cs.Irex |= REX_W;
code_newreg(&cs, valreg);
cdb.gen(&cs); // MOV [idxreg],AX
code* c2 = cdb.last();
if (sz == REGSIZE * 2)

Check warning on line 1438 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1426-L1438

Added lines #L1426 - L1438 were not covered by tests
{
cs.IEV1.Vuns = REGSIZE;
code_newreg(&cs, valreghi);
cdb.gen(&cs); // MOV REGSIZE[idxreg],DX

Check warning on line 1442 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1440-L1442

Added lines #L1440 - L1442 were not covered by tests
}
cdb.genc2(0x81, grex | modregrmx(3,0,idxreg), sz); // ADD idxreg,sz
genjmp(cdb, LOOP, FL.code, cast(block*)c2); // LOOP L2
cdb.append(c1);

Check warning on line 1446 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1444-L1446

Added lines #L1444 - L1446 were not covered by tests

cgstate.regimmed_set(CX, 0); // CX is now 0

Check warning on line 1448 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1448

Added line #L1448 was not covered by tests

fixresult(cdb,e,mregbx,pretregs);

Check warning on line 1450 in compiler/src/dmd/backend/arm/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod2.d#L1450

Added line #L1450 was not covered by tests
}

/**********************
* Do structure assignments.
* This should be fixed so that (s1 = s2) is rewritten to (&s1 = &s2).
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dmd/backend/arm/cod3.d
Original file line number Diff line number Diff line change
Expand Up @@ -1763,6 +1763,7 @@
* Note: only works for forward referenced code.
* only direct jumps and branches are detected.
* LOOP instructions only work for backward refs.
* Reference: http://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#condbranch
*/
@trusted
void jmpaddr(code* c)
Expand Down Expand Up @@ -1805,7 +1806,7 @@
ad += calccodsize(ci);
ci = code_next(ci);
}
c.Iop = (-(ad >> 2)) << 5;
c.Iop |= (-(ad >> 2) & ((1 << 19) - 1)) << 5; // set the signed imm19 field

Check warning on line 1809 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L1809

Added line #L1809 was not covered by tests
c.IFL1 = FL.unde;
}
c = code_next(c);
Expand Down
40 changes: 34 additions & 6 deletions compiler/src/dmd/backend/arm/disasmarm.d
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,9 @@
const char* format = oO ? "bc.%s" : "b.%s";
const n = sprintf(buf.ptr, format, condstring[cond].ptr);
p1 = buf[0 .. n];
p2 = wordtostring(imm19);
if (imm19 & (1 << 18)) // if bit 19 is set
imm19 |= -1 << 18; // sign extend
p2 = signedWordtostring(imm19);

Check warning on line 748 in compiler/src/dmd/backend/arm/disasmarm.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/disasmarm.d#L746-L748

Added lines #L746 - L748 were not covered by tests
}
else if (field(ins, 31, 24) == 0x55) // http://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#miscbranch
{
Expand Down Expand Up @@ -2368,10 +2370,35 @@
p4 = eaString(op24, cast(ubyte)Rn, offset);
}

// Load/store register pair (unscaled immediate) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_unscaled
// Load/store register pair (immediate post-indexed) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_immpost
// Load/store register pair (unprivileged) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_unpriv
// Load/store register pair (immediate pre-indexed) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_immpre
// Load/store register (unscaled immediate) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_unscaled

// Load/store register (immediate post-indexed) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_immpost
if (field(ins, 29, 27) == 7 && field(ins, 25, 24) == 0 && field(ins, 21, 21) == 0 && field(ins, 11,10) == 1)
{
url = "ldst_immpost";

uint size = field(ins, 31, 30);
uint VR = field(ins, 26, 26);
uint opc = field(ins, 23, 22);
uint imm9 = field(ins, 20, 12);
uint Rn = field(ins, 9, 5);
uint Rt = field(ins, 4, 0);

if ((size & 2) && VR == 0 && opc == 0)
{
url2 = "str_imm_gen";

p1 = "str";
p2 = regString(size & 1, Rt);
if (size & 1 && Rt == 0x1F)
p2 = "xzr";
p3 = eaString(1, cast(ubyte)Rn, imm9);
}
}
else

// Load/store register (unprivileged) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_unpriv
// Load/store register (immediate pre-indexed) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_immpre
// Atomic memory operations https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#memop
// Load/store register (register offset) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_regoff
// Load/store register (pac) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_pac
Expand Down Expand Up @@ -3032,8 +3059,9 @@
unittest
{
int line64 = __LINE__;
string[84] cases64 = // 64 bit code gen
string[85] cases64 = // 64 bit code gen
[
"F8 00 84 5F str xzr,[x2],#8",
"6F 00 E4 01 movi v1.2d,#0x0",
"9E AF 00 3E fmov v30.d[1],x1",
"4E BE 1F C0 mov v0.16b,v30.16b",
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/backend/arm/instr.d
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,7 @@ struct INSTR
(VR << 26) |
(opc << 22) |
(imm9 << 12) |
(1 << 10) |
(Rn << 5) |
Rt;
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dmd/backend/x86/cod2.d
Original file line number Diff line number Diff line change
Expand Up @@ -4114,6 +4114,9 @@
@trusted
void cdmemset(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
{
if (cg.AArch64)
return dmd.backend.arm.cod2.cdmemset(cg, cdb, e, pretregs);

Check warning on line 4118 in compiler/src/dmd/backend/x86/cod2.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/x86/cod2.d#L4118

Added line #L4118 was not covered by tests

regm_t retregs1;
regm_t retregs3;
reg_t reg;
Expand Down
Loading