|
239 | 239 | CACHEFLUSH((char *)fn, CODESIZE); |
240 | 240 | #define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub) |
241 | 241 | #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 |
244 | 244 | #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 | + */ |
248 | 259 | #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) |
253 | 278 | #define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub) |
254 | 279 | #elif defined(__sw_64__) |
255 | 280 | #define CODESIZE 12U |
|
271 | 296 | // lgrl %r1, fn_stub |
272 | 297 | // br %r1 |
273 | 298 | #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);\ |
275 | 300 | ((uint32_t*)fn)[1] = 0x07f10000;\ |
276 | 301 | *(uint64_t *)(fn + 8) = (uint64_t)fn_stub;\ |
277 | 302 | CACHEFLUSH((char *)fn, CODESIZE); |
|
0 commit comments