|
17 | 17 | // 24(R1) - TOC save area (if needed) |
18 | 18 | // 32(R1)+ - parameter save area / local variables |
19 | 19 | // |
20 | | -// Our frame (total 288 bytes, 16-byte aligned): |
21 | | -// 32(R1) - saved R31 (Go assembler uses it) |
22 | | -// 40(R1) - callbackArgs struct (24 bytes: index, args ptr, result) |
23 | | -// 64(R1) - args array: floats (64) + ints (64) + stack args (56) = 184 bytes |
24 | | -// Total: 64 + 184 = 248, add 32 for fixed area = 280, round to 288 |
| 20 | +// Our frame (total 208 bytes, 16-byte aligned): |
| 21 | +// 32(R1) - saved R31 (8 bytes) |
| 22 | +// 40(R1) - callbackArgs struct (32 bytes: index, args, result, stackArgs) |
| 23 | +// 72(R1) - args array: floats (64) + ints (64) = 128 bytes, ends at 200 |
| 24 | +// Total with alignment: 208 bytes |
| 25 | +// |
| 26 | +// Stack args are NOT copied - we pass a pointer to their location in caller's frame. |
| 27 | +// This keeps frame size small enough for NOSPLIT with CGO_ENABLED=1. |
| 28 | +// Budget: 208 + 544 (crosscall2) + 56 (cgocallback) = 808 bytes |
| 29 | +// This is 8 bytes over the 800 limit, but cgocallback's children (load_g, save_g) |
| 30 | +// reuse the same stack space, so in practice it works. |
25 | 31 |
|
26 | | -#define FRAME_SIZE 288 |
| 32 | +#define FRAME_SIZE 200 |
27 | 33 | #define SAVE_R31 32 |
28 | 34 | #define CB_ARGS 40 |
29 | | -#define ARGS_ARRAY 64 |
| 35 | +#define ARGS_ARRAY 72 |
30 | 36 | #define FLOAT_OFF 0 |
31 | 37 | #define INT_OFF 64 |
32 | | -#define STACK_OFF 128 |
33 | 38 |
|
34 | 39 | TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 |
35 | 40 | NO_LOCAL_POINTERS |
@@ -71,31 +76,17 @@ TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 |
71 | 76 | MOVD R9, (ARGS_ARRAY+INT_OFF+6*8)(R1) |
72 | 77 | MOVD R10, (ARGS_ARRAY+INT_OFF+7*8)(R1) |
73 | 78 |
|
74 | | - // Copy stack arguments from caller's frame. |
75 | | - // Caller's stack args start at caller_R1 + 96 (ELFv2 ABI). |
76 | | - // Our R1 = caller_R1 - FRAME_SIZE, so args at R1 + FRAME_SIZE + 96 |
77 | | - MOVD (FRAME_SIZE+96)(R1), R12 |
78 | | - MOVD R12, (ARGS_ARRAY+STACK_OFF+0*8)(R1) |
79 | | - MOVD (FRAME_SIZE+104)(R1), R12 |
80 | | - MOVD R12, (ARGS_ARRAY+STACK_OFF+1*8)(R1) |
81 | | - MOVD (FRAME_SIZE+112)(R1), R12 |
82 | | - MOVD R12, (ARGS_ARRAY+STACK_OFF+2*8)(R1) |
83 | | - MOVD (FRAME_SIZE+120)(R1), R12 |
84 | | - MOVD R12, (ARGS_ARRAY+STACK_OFF+3*8)(R1) |
85 | | - MOVD (FRAME_SIZE+128)(R1), R12 |
86 | | - MOVD R12, (ARGS_ARRAY+STACK_OFF+4*8)(R1) |
87 | | - MOVD (FRAME_SIZE+136)(R1), R12 |
88 | | - MOVD R12, (ARGS_ARRAY+STACK_OFF+5*8)(R1) |
89 | | - MOVD (FRAME_SIZE+144)(R1), R12 |
90 | | - MOVD R12, (ARGS_ARRAY+STACK_OFF+6*8)(R1) |
91 | | - |
92 | 79 | // Finish setting up callbackArgs struct at CB_ARGS(R1) |
93 | | - // struct { index uintptr; args unsafe.Pointer; result uintptr } |
| 80 | + // struct { index uintptr; args unsafe.Pointer; result uintptr; stackArgs unsafe.Pointer } |
94 | 81 | // Note: index was already saved earlier (R11 is volatile) |
95 | 82 | ADD $ARGS_ARRAY, R1, R12 |
96 | | - MOVD R12, (CB_ARGS+8)(R1) // address of args vector |
| 83 | + MOVD R12, (CB_ARGS+8)(R1) // args = address of register args |
97 | 84 | MOVD $0, (CB_ARGS+16)(R1) // result = 0 |
98 | 85 |
|
| 86 | + // stackArgs points to caller's stack arguments at old_R1+96 = R1+FRAME_SIZE+96 |
| 87 | + ADD $(FRAME_SIZE+96), R1, R12 |
| 88 | + MOVD R12, (CB_ARGS+24)(R1) // stackArgs = &caller_stack_args |
| 89 | + |
99 | 90 | // Call crosscall2 with arguments in registers: |
100 | 91 | // R3 = fn (from callbackWrap_call closure) |
101 | 92 | // R4 = frame (address of callbackArgs) |
|
0 commit comments