Skip to content

Commit 02276d6

Browse files
authored
Update stub.h
1 parent 74c61d7 commit 02276d6

File tree

1 file changed

+35
-10
lines changed

1 file changed

+35
-10
lines changed

src/stub.h

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -239,17 +239,42 @@
239239
CACHEFLUSH((char *)fn, CODESIZE);
240240
#define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub)
241241
#elif defined(__sparc__) && defined(__arch64__)
242-
#define CODESIZE 24U
243-
#define CODESIZE_MIN 24U
242+
#define CODESIZE 28U // 7 instructions * 4 bytes
243+
#define CODESIZE_MIN 28U
244244
#define CODESIZE_MAX CODESIZE
245-
// sethi %hi(fn_stub), %g1
246-
// jmp %g1 + %lo(fn_stub)
247-
// nop
245+
/*
246+
* Correct 64-bit absolute jump for SPARCv9.
247+
* This sequence loads the full 64-bit address of fn_stub into register %g1
248+
* and then jumps to it.
249+
*
250+
* Assembly:
251+
* 1. sethi %hix(fn_stub), %g1 // bits 63-42
252+
* 2. or %g1, %lox(fn_stub), %g1 // bits 41-32
253+
* 3. sllx %g1, 32, %g1 // shift left by 32
254+
* 4. sethi %hi(fn_stub), %g1 // bits 31-10 (of the lower 32 bits)
255+
* 5. or %g1, %lo(fn_stub), %g1 // bits 9-0
256+
* 6. jmpl %g1, %g0 // jump to address in %g1
257+
* 7. nop // delay slot filler
258+
*/
248259
#define REPLACE_FAR(t, fn, fn_stub)\
249-
((uint32_t*)fn)[0] = 0x03000000 | (((uintptr_t)fn_stub >> 42) & 0x3fffff);\
250-
((uint32_t*)fn)[1] = 0x81c06000 | (((uintptr_t)fn_stub >> 32) & 0x3ff);\
251-
((uint32_t*)fn)[2] = 0x01000000;\
252-
CACHEFLUSH((char *)fn, CODESIZE);
260+
do {\
261+
uint64_t addr = (uint64_t)fn_stub;\
262+
/* 1. sethi %hix(addr), %g1 */\
263+
((uint32_t*)fn)[0] = 0x03000000 | ((addr >> 42) & 0x3fffff);\
264+
/* 2. or %g1, %lox(addr), %g1 */\
265+
((uint32_t*)fn)[1] = 0x82104000 | ((addr >> 32) & 0x3ff);\
266+
/* 3. sllx %g1, 32, %g1 */\
267+
((uint32_t*)fn)[2] = 0x83285020;\
268+
/* 4. sethi %hi(addr), %g1 */\
269+
((uint32_t*)fn)[3] = 0x03000000 | ((addr >> 10) & 0x3fffff);\
270+
/* 5. or %g1, %lo(addr), %g1 */\
271+
((uint32_t*)fn)[4] = 0x82104000 | (addr & 0x3ff);\
272+
/* 6. jmpl %g1, %g0 */\
273+
((uint32_t*)fn)[5] = 0x81c04000;\
274+
/* 7. nop */\
275+
((uint32_t*)fn)[6] = 0x01000000;\
276+
CACHEFLUSH((char *)fn, CODESIZE);\
277+
} while(0)
253278
#define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub)
254279
#elif defined(__sw_64__)
255280
#define CODESIZE 12U
@@ -271,7 +296,7 @@
271296
// lgrl %r1, fn_stub
272297
// br %r1
273298
#define REPLACE_FAR(t, fn, fn_stub)\
274-
((uint32_t*)fn)[0] = 0xc0200000 | (1 << 20) | (0x0);\
299+
((uint32_t*)fn)[0] = 0xc0100000 | (1 << 20) | (0x0);\
275300
((uint32_t*)fn)[1] = 0x07f10000;\
276301
*(uint64_t *)(fn + 8) = (uint64_t)fn_stub;\
277302
CACHEFLUSH((char *)fn, CODESIZE);

0 commit comments

Comments
 (0)