AArch64 does not have LEA, fake it (#21064)

This commit is contained in:
Walter Bright 2025-03-22 21:25:05 -07:00 committed by GitHub
parent 0ae065db22
commit c4d45a1a49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 24 additions and 6 deletions

View file

@ -58,6 +58,7 @@ nothrow:
void loadFromEA(ref code cs, reg_t reg, uint szw, uint szr)
{
//debug printf("loadFromEA() reg: %d, szw: %d, szr: %d\n", reg, szw, szr);
//debug printf("EV1.Voffset: %d\n", cast(int)cs.IEV1.Voffset);
assert(szr <= szw);
cs.Iop = INSTR.nop;
assert(reg != NOREG);
@ -496,6 +497,7 @@ void loadea(ref CodeBuilder cdb,elem* e,ref code cs,uint op,reg_t reg,targ_size_
getlvalue(cdb, cs, e, keepmsk, rmx);
cs.IEV1.Voffset += offset;
assert(op != LEA); // AArch64 does not have LEA
loadFromEA(cs,reg,sz == 8 ? 8 : 4,sz);
getregs(cdb, desmsk); // save any regs we destroy

View file

@ -1371,9 +1371,16 @@ static if (0)
}
else
{
loadea(cdb,e,cs,LEA,reg,0,0,0); // LEA reg,EA
if (I64)
code_orrex(cdb.last(), REX_W);
uint sh = 0;
uint base = 0;
cs.Iop = INSTR.addsub_imm(1,0,0,sh,base,cgstate.BP,reg); // ADD reg,BP,base
cs.IFL1 = fl;
cs.IEV1.Vsym = e.Vsym;
cs.IEV1.Voffset = 0;
cdb.gen(&cs);
cdb.gen1(INSTR.addsub_imm(1,0,0,sh,cast(uint)e.Voffset,reg,reg)); // ADD reg,reg,Voffset
// TODO AArch64 common subexpressions?
//loadea(cdb,e,cs,LEA,reg,0,0,0); // LEA reg,EA
}
break;

View file

@ -1295,7 +1295,7 @@ void assignaddrc(code* c)
s = c.IEV1.Vsym;
uint sz = 8;
uint ins = c.Iop;
if (0 && c.IFL1 != FL.unde)
if (c.IFL1 != FL.unde)
{
printf("FL: %-8s ", fl_str(c.IFL1));
disassemble(ins);
@ -1428,7 +1428,6 @@ void assignaddrc(code* c)
L2:
offset = cast(int)offset; // sign extend
// Load/store register (unsigned immediate) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#ldst_pos
assert(field(ins,29,27) == 7);
uint opc = field(ins,23,22);
uint shift = field(ins,31,30); // 0:1 1:2 2:4 3:8 shift for imm12
uint op24 = field(ins,25,24);
@ -1436,9 +1435,18 @@ void assignaddrc(code* c)
if (cgstate.hasframe)
offset += REGSIZE * 2;
offset += localsize;
if (op24 == 1)
if (field(ins,28,23) == 0x22) // Add/subtract (immediate)
{
uint imm12 = field(ins,21,10); // unsigned 12 bits
//printf("imm12: %d offset: %llx\n", imm12, offset);
imm12 += offset;
assert(imm12 < 0x1000);
ins = setField(ins,21,10,imm12);
}
else if (op24 == 1)
{
assert(field(ins,29,27) == 7);
uint imm12 = field(ins,21,10); // unsigned 12 bits
offset += imm12 << shift; // add in imm
//printf("shift: %d offset: %llx imm12: %x\n", shift, offset, imm12);
assert((offset & ((1 << shift) - 1)) == 0); // no misaligned access
@ -1448,6 +1456,7 @@ void assignaddrc(code* c)
}
else if (op24 == 0)
{
assert(field(ins,29,27) == 7);
if (opc == 2 && shift == 0)
shift = 4;
uint imm9 = field(ins,20,12); // signed 9 bits