detached 3a10209

sys_unix_ppc64le.s RawHistoryFolder

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3
4//go:build linux
5
6#include "textflag.h"
7#include "go_asm.h"
8#include "funcdata.h"
9
10// PPC64LE ELFv2 ABI callbackasm1 implementation
11// On entry, R11 contains the callback index (set by callbackasm)
12//
13// ELFv2 stack frame layout requirements:
14//   0(R1)   - back chain (pointer to caller's frame)
15//   8(R1)   - CR save area (optional)
16//  16(R1)   - LR save area (for callee to save caller's LR)
17//  24(R1)   - TOC save area (if needed)
18//  32(R1)+  - parameter save area / local variables
19//
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.
31
32#define FRAME_SIZE     200
33#define SAVE_R31       32
34#define CB_ARGS        40
35#define ARGS_ARRAY     72
36#define FLOAT_OFF      0
37#define INT_OFF        64
38
39TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
40	NO_LOCAL_POINTERS
41
42	// On entry, the trampoline in zcallback_ppc64le.s left
43	// the callback index in R11.
44
45	// Per ELFv2 ABI, save LR to caller's frame BEFORE allocating our frame
46	MOVD LR, R0
47	MOVD R0, 16(R1)
48
49	// Allocate our stack frame (with back chain via MOVDU)
50	MOVDU R1, -FRAME_SIZE(R1)
51
52	// Save R31 - Go assembler uses it for MOVD from SB (like arm64's R27)
53	MOVD R31, SAVE_R31(R1)
54
55	// Save R11 (callback index) immediately - it's volatile and will be clobbered!
56	// Store it in the callbackArgs struct's index field now.
57	MOVD R11, (CB_ARGS+0)(R1)
58
59	// Save callback arguments to args array.
60	// Layout: floats first (F1-F8), then ints (R3-R10), then stack args
61	FMOVD F1, (ARGS_ARRAY+FLOAT_OFF+0*8)(R1)
62	FMOVD F2, (ARGS_ARRAY+FLOAT_OFF+1*8)(R1)
63	FMOVD F3, (ARGS_ARRAY+FLOAT_OFF+2*8)(R1)
64	FMOVD F4, (ARGS_ARRAY+FLOAT_OFF+3*8)(R1)
65	FMOVD F5, (ARGS_ARRAY+FLOAT_OFF+4*8)(R1)
66	FMOVD F6, (ARGS_ARRAY+FLOAT_OFF+5*8)(R1)
67	FMOVD F7, (ARGS_ARRAY+FLOAT_OFF+6*8)(R1)
68	FMOVD F8, (ARGS_ARRAY+FLOAT_OFF+7*8)(R1)
69
70	MOVD R3, (ARGS_ARRAY+INT_OFF+0*8)(R1)
71	MOVD R4, (ARGS_ARRAY+INT_OFF+1*8)(R1)
72	MOVD R5, (ARGS_ARRAY+INT_OFF+2*8)(R1)
73	MOVD R6, (ARGS_ARRAY+INT_OFF+3*8)(R1)
74	MOVD R7, (ARGS_ARRAY+INT_OFF+4*8)(R1)
75	MOVD R8, (ARGS_ARRAY+INT_OFF+5*8)(R1)
76	MOVD R9, (ARGS_ARRAY+INT_OFF+6*8)(R1)
77	MOVD R10, (ARGS_ARRAY+INT_OFF+7*8)(R1)
78
79	// Finish setting up callbackArgs struct at CB_ARGS(R1)
80	// struct { index uintptr; args unsafe.Pointer; result uintptr; stackArgs unsafe.Pointer }
81	// Note: index was already saved earlier (R11 is volatile)
82	ADD  $ARGS_ARRAY, R1, R12
83	MOVD R12, (CB_ARGS+8)(R1) // args = address of register args
84	MOVD $0, (CB_ARGS+16)(R1) // result = 0
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
90	// Call crosscall2 with arguments in registers:
91	// R3 = fn (from callbackWrap_call closure)
92	// R4 = frame (address of callbackArgs)
93	// R6 = ctxt (0)
94	MOVD ·callbackWrap_call(SB), R3
95	MOVD (R3), R3                   // dereference closure to get fn
96	ADD  $CB_ARGS, R1, R4           // frame = &callbackArgs
97	MOVD $0, R6                     // ctxt = 0
98
99	BL crosscall2(SB)
100
101	// Get callback result into R3
102	MOVD (CB_ARGS+16)(R1), R3
103
104	// Restore R31
105	MOVD SAVE_R31(R1), R31
106
107	// Deallocate frame
108	ADD $FRAME_SIZE, R1
109
110	// Restore LR from caller's frame (per ELFv2, it was saved at 16(old_R1))
111	MOVD 16(R1), R0
112	MOVD R0, LR
113
114	RET

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close