Skip to content

Commit c4d45a1

Browse files
authored
AArch64 does not have LEA, fake it (dlang#21064)
1 parent 0ae065d commit c4d45a1

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

compiler/src/dmd/backend/arm/cod1.d

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ nothrow:
5858
void loadFromEA(ref code cs, reg_t reg, uint szw, uint szr)
5959
{
6060
//debug printf("loadFromEA() reg: %d, szw: %d, szr: %d\n", reg, szw, szr);
61+
//debug printf("EV1.Voffset: %d\n", cast(int)cs.IEV1.Voffset);
6162
assert(szr <= szw);
6263
cs.Iop = INSTR.nop;
6364
assert(reg != NOREG);
@@ -496,6 +497,7 @@ void loadea(ref CodeBuilder cdb,elem* e,ref code cs,uint op,reg_t reg,targ_size_
496497
getlvalue(cdb, cs, e, keepmsk, rmx);
497498
cs.IEV1.Voffset += offset;
498499

500+
assert(op != LEA); // AArch64 does not have LEA
499501
loadFromEA(cs,reg,sz == 8 ? 8 : 4,sz);
500502

501503
getregs(cdb, desmsk); // save any regs we destroy

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,9 +1371,16 @@ static if (0)
13711371
}
13721372
else
13731373
{
1374-
loadea(cdb,e,cs,LEA,reg,0,0,0); // LEA reg,EA
1375-
if (I64)
1376-
code_orrex(cdb.last(), REX_W);
1374+
uint sh = 0;
1375+
uint base = 0;
1376+
cs.Iop = INSTR.addsub_imm(1,0,0,sh,base,cgstate.BP,reg); // ADD reg,BP,base
1377+
cs.IFL1 = fl;
1378+
cs.IEV1.Vsym = e.Vsym;
1379+
cs.IEV1.Voffset = 0;
1380+
cdb.gen(&cs);
1381+
cdb.gen1(INSTR.addsub_imm(1,0,0,sh,cast(uint)e.Voffset,reg,reg)); // ADD reg,reg,Voffset
1382+
// TODO AArch64 common subexpressions?
1383+
//loadea(cdb,e,cs,LEA,reg,0,0,0); // LEA reg,EA
13771384
}
13781385
break;
13791386

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,7 +1295,7 @@ void assignaddrc(code* c)
12951295
s = c.IEV1.Vsym;
12961296
uint sz = 8;
12971297
uint ins = c.Iop;
1298-
if (0 && c.IFL1 != FL.unde)
1298+
if (c.IFL1 != FL.unde)
12991299
{
13001300
printf("FL: %-8s ", fl_str(c.IFL1));
13011301
disassemble(ins);
@@ -1428,17 +1428,25 @@ void assignaddrc(code* c)
14281428
L2:
14291429
offset = cast(int)offset; // sign extend
14301430
// Load/store register (unsigned immediate) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_pos
1431-
assert(field(ins,29,27) == 7);
14321431
uint opc = field(ins,23,22);
14331432
uint shift = field(ins,31,30); // 0:1 1:2 2:4 3:8 shift for imm12
14341433
uint op24 = field(ins,25,24);
14351434
//printf("offset: %lld localsize: %lld REGSIZE*2: %d\n", offset, localsize, REGSIZE*2);
14361435
if (cgstate.hasframe)
14371436
offset += REGSIZE * 2;
14381437
offset += localsize;
1439-
if (op24 == 1)
1438+
if (field(ins,28,23) == 0x22) // Add/subtract (immediate)
14401439
{
14411440
uint imm12 = field(ins,21,10); // unsigned 12 bits
1441+
//printf("imm12: %d offset: %llx\n", imm12, offset);
1442+
imm12 += offset;
1443+
assert(imm12 < 0x1000);
1444+
ins = setField(ins,21,10,imm12);
1445+
}
1446+
else if (op24 == 1)
1447+
{
1448+
assert(field(ins,29,27) == 7);
1449+
uint imm12 = field(ins,21,10); // unsigned 12 bits
14421450
offset += imm12 << shift; // add in imm
14431451
//printf("shift: %d offset: %llx imm12: %x\n", shift, offset, imm12);
14441452
assert((offset & ((1 << shift) - 1)) == 0); // no misaligned access
@@ -1448,6 +1456,7 @@ void assignaddrc(code* c)
14481456
}
14491457
else if (op24 == 0)
14501458
{
1459+
assert(field(ins,29,27) == 7);
14511460
if (opc == 2 && shift == 0)
14521461
shift = 4;
14531462
uint imm9 = field(ins,20,12); // signed 9 bits

0 commit comments

Comments
 (0)