@@ -1460,6 +1460,7 @@ bool orr_solution(ulong value, out uint N, out uint immr, out uint imms)
14601460@trusted
14611461void 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
18331869void jmpaddr (code* c)
18341870{
1835- // printf("jmpaddr()\n");
1871+ printf(" jmpaddr()\n " );
18361872
18371873 code* ci,cn,ctarg,cstart;
18381874 uint ad;
0 commit comments