Skip to content

Commit 6b64cfb

Browse files
authored
need 2 instructions for offsets larger than 0xFFF (#21603)
* more bugs in cdstreq() (#21568) * need 2 instructions for offsets larger than 0xFFF
1 parent 4ce4bf8 commit 6b64cfb

3 files changed

Lines changed: 49 additions & 13 deletions

File tree

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

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,7 @@ bool orr_solution(ulong value, out uint N, out uint immr, out uint imms)
14601460
@trusted
14611461
void assignaddrc(code* c)
14621462
{
1463+
printf("assignaddrc()\n");
14631464
int sn;
14641465
Symbol* s;
14651466
ubyte rm;
@@ -1555,7 +1556,7 @@ void assignaddrc(code* c)
15551556
s = c.IEV1.Vsym;
15561557
uint sz = 8;
15571558
uint ins = c.Iop;
1558-
if (0 && c.IFL1 != FL.unde)
1559+
if (1 && c.IFL1 != FL.unde)
15591560
{
15601561
printf("FL: %-8s ", fl_str(c.IFL1));
15611562
disassemble(ins);
@@ -1638,13 +1639,13 @@ void assignaddrc(code* c)
16381639
c.Iop = INSTR.nop; // remove references to it
16391640
break;
16401641
}
1641-
static if (0)
1642+
static if (1)
16421643
{
1643-
//symbol_print(*s);
1644+
symbol_print(*s);
16441645
//printf("c: %p, x%08x\n", c, c.Iop);
1645-
printf("s = %s, Soffset = %d, Para.size = %d, BPoff = %d, EBPtoESP = %d, Voffset = %d\n",
1646+
printf("s = %s, Soffset = %d, Para.size = %d, BPoff = %d, EBPtoESP = %d, Voffset = %d, sectionOff = %d\n",
16461647
s.Sident.ptr, cast(int)s.Soffset, cast(int)cgstate.Para.size, cast(int)cgstate.BPoff,
1647-
cast(int)cgstate.EBPtoESP, cast(int)c.IEV1.Voffset);
1648+
cast(int)cgstate.EBPtoESP, cast(int)c.IEV1.Voffset, cast(int)sectionOff);
16481649
}
16491650
if (s.Sflags & SFLunambig)
16501651
c.Iflags |= CFunambig;
@@ -1711,13 +1712,26 @@ void assignaddrc(code* c)
17111712
uint shift = field(ins,31,30); // 0:1 1:2 2:4 3:8 shift for imm12
17121713
uint op24 = field(ins,25,24);
17131714
uint op11 = field(ins,11,10);
1714-
if (field(ins,28,23) == 0x22) // Add/subtract (immediate)
1715+
if (field(ins,28,23) == 0x22) // Add/subtract (immediate) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#addsub_imm
17151716
{
1717+
// add Rd,Rn,Voffset
17161718
uint imm12 = field(ins,21,10); // unsigned 12 bits
17171719
//printf("imm12: %x offset: %llx\n", imm12, offset);
17181720
imm12 += offset;
1719-
assert(imm12 < 0x1000);
1720-
ins = setField(ins,21,10,imm12);
1721+
ins = setField(ins,21,10,imm12 & 0xFFF);
1722+
if (imm12 >= 0x1000)
1723+
{
1724+
// Add in the shifted part of the offset
1725+
// add Rd,Rd,(imm12 >> 12) << 12 // https://www.scs.stanford.edu/~zyedidia/arm64/add_addsub_imm.html
1726+
c.Iop = ins;
1727+
code* c2 = code_calloc();
1728+
const reg_t Rd2 = cast(reg_t)field(ins,4,0);
1729+
c2.Iop = INSTR.add_addsub_imm(1,1,imm12>>12,Rd2,Rd2);
1730+
c2.Iop |= ins & (1 << 30); // SUB
1731+
c2.next = c.next;
1732+
c.next = c2;
1733+
continue;
1734+
}
17211735
}
17221736
else if (op24 == 1)
17231737
{
@@ -1739,8 +1753,29 @@ void assignaddrc(code* c)
17391753
{
17401754
imm12 = cast(uint)(offset >> shift);
17411755
//printf("offset: %llu x%llx shift: %d imm12: x%x\n", offset,offset,shift,imm12);
1742-
assert(imm12 < 0x1000);
1743-
ins = setField(ins,21,10,imm12);
1756+
if (imm12 < 0x1000)
1757+
ins = setField(ins,21,10,imm12);
1758+
else
1759+
{
1760+
// insert extra instruction to load the offset using scratch register R16
1761+
enum R16 = 16; // scratch register
1762+
// add R16,Rn,(imm12 >> 12) << 12 // https://www.scs.stanford.edu/~zyedidia/arm64/add_addsub_imm.html
1763+
const reg_t Rn2 = cast(reg_t)field(ins,9,5);
1764+
uint ins2 = INSTR.add_addsub_imm(1,1,imm12>>12,Rn2,R16);
1765+
c.Iop = ins2;
1766+
c.IFL1 = FL.unde;
1767+
c.IEV1.Vpointer = 0;
1768+
1769+
// ldr Rt,[R16,#imm12 & 0xFFF] // https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_gen.html
1770+
ins = setField(ins,9,5,R16);
1771+
ins = setField(ins,21,10,imm12 & 0xFFF);
1772+
1773+
code* c2 = code_calloc();
1774+
c2.Iop = ins;
1775+
c2.next = c.next;
1776+
c.next = c2;
1777+
continue;
1778+
}
17441779
}
17451780
}
17461781
else if (op24 == 0 && op11) // postinc or predec
@@ -1779,6 +1814,7 @@ void assignaddrc(code* c)
17791814
{ /* Convert to SP relative address instead of BP */
17801815
offset += cgstate.EBPtoESP; // add difference in offset
17811816
ins = setField(ins,9,5,31); // set Rn to SP
1817+
assert(0); // offset is ignored
17821818
}
17831819
c.Iop = ins;
17841820

@@ -1832,7 +1868,7 @@ void assignaddrc(code* c)
18321868
@trusted
18331869
void jmpaddr(code* c)
18341870
{
1835-
//printf("jmpaddr()\n");
1871+
printf("jmpaddr()\n");
18361872

18371873
code* ci,cn,ctarg,cstart;
18381874
uint ad;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2576,7 +2576,7 @@ void disassemble(uint c) @trusted
25762576
case ldr(0,0,0): p1 = "strb"; goto Lldr8; // https://www.scs.stanford.edu/~zyedidia/arm64/strb_imm.html
25772577
case ldr(0,0,1): p1 = "ldrb"; goto Lldr8;
25782578
Lldr8:
2579-
p2 = regString(factor == 84, Rt);
2579+
p2 = regString(factor == 8, Rt);
25802580
p3 = eaString(0, cast(ubyte)Rn, imm12);
25812581
break;
25822582

compiler/src/dmd/backend/codebuilder.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct CodeBuilder
3535
code** pTail;
3636

3737
enum BADINS = 0x1234_5678;
38-
//enum BADINS = 0x3C24_6843;
38+
//enum BADINS = 0x9100_03A2;
3939

4040
nothrow:
4141
public:

0 commit comments

Comments
 (0)