static void
write_uuo_insns (insn_t * target, insn_t * iaddr, int pcrel)
{
- /* ldr x0, pc-pcrel */
- (iaddr[0]) = (0x58000000UL | ((((unsigned) pcrel) & 0x7ffff) << 5));
+ /* ldr x1, pc-pcrel */
+ (iaddr[0]) = (0x58000001UL | ((((unsigned) pcrel) & 0x7ffff) << 5));
/* If the target PC is right after the target offset, then the PC
requires no further relocation and we can jump to a fixed address.
if ((((const int64_t *) (newspace_to_tospace (target)))[-1]) == 0)
{
ptrdiff_t offset = (((uintptr_t) target) - ((uintptr_t) (&iaddr[1])));
- if ((-0x40000 <= offset) && (offset <= 0x3ffff))
+ assert ((offset & 3) == 0);
+ if ((-0x10000000 <= offset) && (offset <= 0xfffffff))
{
- unsigned immlo2 = (offset & 3);
- unsigned immhi19 = ((((unsigned) offset) >> 2) & 0x1ffff);
- assert (offset == ((ptrdiff_t) ((immhi19 << 2) | immlo2)));
- /* adr x1, target */
- (iaddr[1]) = (0x10000001UL | (immlo2 << 29) | (immhi19 << 5));
- /* br x1 */
- (iaddr[2]) = 0xd61f0020UL;
+ unsigned imm26 = ((offset >> 2) & 0x03ffffff);
+ /* b target */
+ (iaddr[1]) = (0x14000000UL | imm26);
}
else if (((- (INT64_C (0x200000000))) <= offset) &&
(offset <= (INT64_C (0x1ffffffff))))
(offset == ((ptrdiff_t) ((pghi19 << 14) | (pglo2 << 12) | lo12)));
/* adrp x1, target */
(iaddr[1]) = (0x90000001UL | (pglo2 << 29) | (pghi19 << 5));
- /* add x1, x1, #off */
- (iaddr[2]) = (0x91000021UL | (lo12 << 10));
- /* br x1 */
- (iaddr[3]) = 0xd61f0020UL;
+ /* add x17, x17, #off */
+ (iaddr[2]) = (0x91000031UL | (lo12 << 10));
+ /* br x17 */
+ (iaddr[3]) = 0xd61f0022UL;
}
else
/* You have too much memory. */
}
else
{
- (iaddr[1]) = 0xd1002001UL; /* sub x1, x0, #8 */
- (iaddr[2]) = 0xf9400021UL; /* ldr x1, [x1] */
- (iaddr[3]) = 0x8b000021UL; /* add x1, x1, x0 */
- (iaddr[4]) = 0xd61f0020UL; /* br x1 */
+ (iaddr[1]) = 0xd1002031UL; /* sub x17, x1, #8 */
+ (iaddr[2]) = 0xf9400231UL; /* ldr x17, [x17] */
+ (iaddr[3]) = 0x8b010231UL; /* add x17, x17, x1 */
+ (iaddr[4]) = 0xd61f0022UL; /* br x17 */
}
}
return (trampoline_entry_addr (block, index));
}
-#define REGNUM_REGS_POINTER 19
-#define REGBLOCK_SCHEME_TO_INTERFACE 0
-
bool
store_trampoline_insns (insn_t * entry, uint8_t code)
{
(entry[-2]) = 0; /* PC offset, first half */
(entry[-1]) = 0; /* PC offset, other half */
- /* movz x16, #code */
- (entry[0]) = (0xd2800010UL | (((unsigned) code) << 5));
- /* adr x1, storage */
+ /* movz x17, #code */
+ (entry[0]) = (0xd2800011UL | (((unsigned) code) << 5));
+ /* adr x1, storage (pc + 12) */
(entry[1]) = 0x10000061UL;
- /* ldr x17, [x19, #<scheme_to_interface>] */
- {
- unsigned Rn = REGNUM_REGS_POINTER;
- unsigned imm12 = REGBLOCK_SCHEME_TO_INTERFACE;
- (entry[2]) = (0xf9400011UL | (imm12 << 10) | (Rn << 5));
- }
- /* br x17 */
- (entry[3]) = 0xd61f0220UL;
+ /* br x23 (scheme-to-interface) */
+ (entry[2]) = 0xd61f02e0UL;
return (false); /* no error */
}
\f
(after linking, pointing to near open procedure)
target 0x00 8 <entry address>
0x08 4 <frame size>
-uuo 0x0c 4 ldr x0, target ; Load entry address.
- 0x10 4 adr x1, target_pc ; Load PC-relative address.
- 0x14 4 br x1
- 0x18 8 (padding)
+uuo 0x0c 4 ldr x1, target ; Load entry address.
+ 0x10 4 b target_pc ; Branch to PC-relative.
+ 0x14 12 (padding)
0x20
(after linking, pointing to far open procedure)
target 0x00 8 <entry address>
0x08 4 <frame size>
-uuo 0x0c 4 ldr x0, target ; Load entry address.
- 0x10 4 adrp x1, target_pc ; Load PC-relative page addr.
- 0x14 4 add x1, x1, #page_offset : Add page offset.
- 0x18 4 br x1
+uuo 0x0c 4 ldr x1, target ; Load entry address.
+ 0x10 4 adrp x17, target_pc ; Load PC-relative page addr.
+ 0x14 4 add x17, x17, #page_offset : Add page offset.
+ 0x18 4 br x17
0x1c 4 (padding)
0x20
(after linking, pointing to closure)
target 0x00 8 <entry address>
0x08 4 <frame size>
-uuo 0x0c 4 ldr x0, target ; Load entry address.
- 0x10 4 sub x1, x0, #8 ; Get address of PC offset.
- 0x14 4 ldr x1, [x1] ; Load PC offset.
- 0x18 4 add x1, x1, x0 ; Compute PC = entry + offset.
- 0x1c 4 br x1
+uuo 0x0c 4 ldr x1, target ; Load entry address.
+ 0x10 4 sub x17, x1, #8 ; Get address of PC offset.
+ 0x14 4 ldr x17, [x17] ; Load PC offset.
+ 0x18 4 add x17, x17, x1 ; Compute PC = entry + offset.
+ 0x1c 4 br x17
0x20
- Execute cache, big-endian:
(after linking, pointing to near open procedure)
target 0x00 8 <entry address>
-uuo 0x08 4 ldr x0, target ; Load entry address.
- 0x0c 4 adr x1, target_pc ; Load PC-relative address.
- 0x10 4 br x1
- 0x14 8 (padding)
+uuo 0x08 4 ldr x1, target ; Load entry address.
+ 0x0c 4 b target_pc ; Branch PC-relative.
+ 0x10 12 (padding)
0x1c 4 <frame size>
0x20
(after linking, pointing to far open procedure)
target 0x00 8 <entry address>
-uuo 0x08 4 ldr x0, target ; Load entry address.
- 0x0c 4 adrp x1, target_pc ; Load PC-relative page addr.
- 0x10 4 add x1, x1, #page_offset ; Add page offset.
- 0x14 4 br x1
+uuo 0x08 4 ldr x1, target ; Load entry address.
+ 0x0c 4 adrp x17, target_pc ; Load PC-relative page addr.
+ 0x10 4 add x17, x17, #page_offset ; Add page offset.
+ 0x14 4 br x17
0x18 4 (padding)
0x1c 4 <frame size>
0x20
(after linking, pointing to closure)
target 0x00 8 <entry address>
-uuo 0x08 4 ldr x0, target ; Load entry address.
- 0x0c 4 sub x1, x0, #8 ; Get address of PC offset.
- 0x10 4 ldr x1, [x1] ; Load PC offset.
- 0x14 4 add x1, x1, x0 ; Compute PC = entry + offset.
- 0x18 4 br x1
+uuo 0x08 4 ldr x1, target ; Load entry address.
+ 0x0c 4 sub x17, x1, #8 ; Get address of PC offset.
+ 0x10 4 ldr x17, [x17] ; Load PC offset.
+ 0x14 4 add x17, x17, x1 ; Compute PC = entry + offset.
+ 0x18 4 br x17
0x1c 4 <frame size>
0x20
-0x0c 2 <type/arity info>
-0x0a 2 <block offset>
-0x08 8 <PC offset = 0> 00 00 00 00 00 00 00 00
-entry 0x00 4 movz x16, #<code> ; Set utility number.
+entry 0x00 4 movz x17, #<code> ; Set utility index.
0x04 4 adr x1, storage ; Set x1 to storage pointer.
- 0x08 4 ldr x17, [x19, #<scheme_to_interface>]
- 0x0c 4 br x17
+ 0x08 4 br x23 ; Jump to scheme-to-interface.
+ 0x0c 4 (padding)
storage 0x10 8 [tag: first trampoline datum]
0x18 8 [tag: second trampoline datum]
...