@@ -108,6 +108,20 @@ pub const closure_thunk = $if ppc64le {
108108 0x81 , 0xc0 , 0x40 , 0x00 , // jmp %g1
109109 0x01 , 0x00 , 0x00 , 0x00 // nop
110110 ]!
111+ } $else $if ppc64 {
112+ [
113+ u8 (0x7C ), 0x08 , 0x02 , 0xA6 , // mflr %r0
114+ 0x48 , 0x00 , 0x00 , 0x05 , // bl here
115+ 0x7D , 0xC8 , 0x02 , 0xA6 , // here: mflr %r14
116+ 0x39 , 0xCE , 0xC0 , 0x08 , // addi %r14, %r14, -16376
117+ 0xC9 , 0xCE , 0x00 , 0x00 , // lfd %f14, 0(%r14) // userdata
118+ 0xE9 , 0xCE , 0x00 , 0x08 , // ld %r14, 8(%r14) // func descriptor ptr
119+ 0xE9 , 0x8E , 0x00 , 0x00 , // ld %r12, 0(%r14) // code addr from descriptor
120+ 0xE8 , 0x4E , 0x00 , 0x08 , // ld %r2, 8(%r14) // TOC from descriptor
121+ 0x7C , 0x08 , 0x03 , 0xA6 , // mtlr %r0
122+ 0x7D , 0x89 , 0x03 , 0xA6 , // mtctr %r12
123+ 0x4E , 0x80 , 0x04 , 0x20 , // bctr
124+ ]!
111125} $else {
112126 [u8 (0 )]!
113127}
@@ -167,6 +181,11 @@ const closure_get_data_bytes = $if arm32 {
167181 0x81 , 0xc3 , 0xe0 , 0x08 , // retl
168182 0x01 , 0x00 , 0x00 , 0x00 // nop
169183 ]!
184+ } $else $if ppc64 {
185+ [
186+ u8 (0x7d ), 0xc3 , 0x00 , 0x66 , // mfvsrd %r3, %f14
187+ 0x4e , 0x80 , 0x00 , 0x20 // blr
188+ ]!
170189} $else {
171190 [u8 (0 )]!
172191}
@@ -223,11 +242,20 @@ fn closure_init() {
223242 closure_memory_protect_platform (g_closure.closure_ptr, page_size, .read_write)
224243 // Copy closure entry stub code
225244 vmemcpy (g_closure.closure_ptr, & closure_get_data_bytes[0 ], closure_get_data_bytes.len)
226- // Re-enormalize execution protection
245+ // Re-normalize execution protection
227246 closure_memory_protect_platform (g_closure.closure_ptr, page_size, .read_exec)
228247 }
229248 // Setup global closure handler pointer
230- g_closure.closure_get_data = g_closure.closure_ptr
249+ $if ppc64 {
250+ mut desc := unsafe { & voidptr (& u8 (g_closure.closure_ptr) - assumed_page_size) }
251+ unsafe {
252+ desc[0 ] = g_closure.closure_ptr
253+ desc[1 ] = nil
254+ }
255+ g_closure.closure_get_data = desc
256+ } $else {
257+ g_closure.closure_get_data = g_closure.closure_ptr
258+ }
231259
232260 // Advance allocation pointer past header
233261 unsafe {
@@ -248,18 +276,35 @@ fn closure_create(func voidptr, data voidptr) voidptr {
248276 g_closure.closure_cap-- // Decrement slot counter
249277
250278 // Claim current closure slot
251- mut curr_closure := g_closure.closure_ptr
279+ curr_closure := g_closure.closure_ptr
252280 unsafe {
253281 // Move to next available slot
254282 g_closure.closure_ptr = & u8 (g_closure.closure_ptr) + closure_size
255283
256284 // Write closure metadata (data + function pointer)
257285 mut p := & voidptr (& u8 (curr_closure) - assumed_page_size)
258- p[0 ] = data // Stored closure context
259- p[1 ] = func // Target function to execute
286+ $if ppc64 {
287+ // ELFv1: guard page layout per slot:
288+ // [0] desc[0] = thunk code address <- returned as ELFv1 function pointer
289+ // [1] desc[1] = nil (TOC unused; thunk loads real TOC from func descriptor)
290+ // [2] userdata
291+ // [3] func (V function descriptor pointer into .opd)
292+ p[0 ] = curr_closure
293+ p[1 ] = nil
294+ p[2 ] = data
295+ p[3 ] = func
296+ } $else {
297+ p[0 ] = data // Stored closure context
298+ p[1 ] = func // Target function to execute
299+ }
260300 }
261301 closure_mtx_unlock_platform ()
262302
263303 // Return executable closure object
264- return curr_closure
304+ $if ppc64 {
305+ // ELFv1: return descriptor address (guard page), not raw code address
306+ return unsafe { & u8 (curr_closure) - assumed_page_size }
307+ } $else {
308+ return curr_closure
309+ }
265310}
0 commit comments