sys_unix_ppc64le.s 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // SPDX-License-Identifier: Apache-2.0
  2. // SPDX-FileCopyrightText: 2026 The Ebitengine Authors
  3. //go:build linux
  4. #include "textflag.h"
  5. #include "go_asm.h"
  6. #include "funcdata.h"
  7. // PPC64LE ELFv2 ABI callbackasm1 implementation
  8. // On entry, R11 contains the callback index (set by callbackasm)
  9. //
  10. // ELFv2 stack frame layout requirements:
  11. // 0(R1) - back chain (pointer to caller's frame)
  12. // 8(R1) - CR save area (optional)
  13. // 16(R1) - LR save area (for callee to save caller's LR)
  14. // 24(R1) - TOC save area (if needed)
  15. // 32(R1)+ - parameter save area / local variables
  16. //
  17. // Our frame (total 208 bytes, 16-byte aligned):
  18. // 32(R1) - saved R31 (8 bytes)
  19. // 40(R1) - callbackArgs struct (32 bytes: index, args, result, stackArgs)
  20. // 72(R1) - args array: floats (64) + ints (64) = 128 bytes, ends at 200
  21. // Total with alignment: 208 bytes
  22. //
  23. // Stack args are NOT copied - we pass a pointer to their location in caller's frame.
  24. // This keeps frame size small enough for NOSPLIT with CGO_ENABLED=1.
  25. // Budget: 208 + 544 (crosscall2) + 56 (cgocallback) = 808 bytes
  26. // This is 8 bytes over the 800 limit, but cgocallback's children (load_g, save_g)
  27. // reuse the same stack space, so in practice it works.
  28. #define FRAME_SIZE 200
  29. #define SAVE_R31 32
  30. #define CB_ARGS 40
  31. #define ARGS_ARRAY 72
  32. #define FLOAT_OFF 0
  33. #define INT_OFF 64
  34. TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
  35. NO_LOCAL_POINTERS
  36. // On entry, the trampoline in zcallback_ppc64le.s left
  37. // the callback index in R11.
  38. // Per ELFv2 ABI, save LR to caller's frame BEFORE allocating our frame
  39. MOVD LR, R0
  40. MOVD R0, 16(R1)
  41. // Allocate our stack frame (with back chain via MOVDU)
  42. MOVDU R1, -FRAME_SIZE(R1)
  43. // Save R31 - Go assembler uses it for MOVD from SB (like arm64's R27)
  44. MOVD R31, SAVE_R31(R1)
  45. // Save R11 (callback index) immediately - it's volatile and will be clobbered!
  46. // Store it in the callbackArgs struct's index field now.
  47. MOVD R11, (CB_ARGS+0)(R1)
  48. // Save callback arguments to args array.
  49. // Layout: floats first (F1-F8), then ints (R3-R10), then stack args
  50. FMOVD F1, (ARGS_ARRAY+FLOAT_OFF+0*8)(R1)
  51. FMOVD F2, (ARGS_ARRAY+FLOAT_OFF+1*8)(R1)
  52. FMOVD F3, (ARGS_ARRAY+FLOAT_OFF+2*8)(R1)
  53. FMOVD F4, (ARGS_ARRAY+FLOAT_OFF+3*8)(R1)
  54. FMOVD F5, (ARGS_ARRAY+FLOAT_OFF+4*8)(R1)
  55. FMOVD F6, (ARGS_ARRAY+FLOAT_OFF+5*8)(R1)
  56. FMOVD F7, (ARGS_ARRAY+FLOAT_OFF+6*8)(R1)
  57. FMOVD F8, (ARGS_ARRAY+FLOAT_OFF+7*8)(R1)
  58. MOVD R3, (ARGS_ARRAY+INT_OFF+0*8)(R1)
  59. MOVD R4, (ARGS_ARRAY+INT_OFF+1*8)(R1)
  60. MOVD R5, (ARGS_ARRAY+INT_OFF+2*8)(R1)
  61. MOVD R6, (ARGS_ARRAY+INT_OFF+3*8)(R1)
  62. MOVD R7, (ARGS_ARRAY+INT_OFF+4*8)(R1)
  63. MOVD R8, (ARGS_ARRAY+INT_OFF+5*8)(R1)
  64. MOVD R9, (ARGS_ARRAY+INT_OFF+6*8)(R1)
  65. MOVD R10, (ARGS_ARRAY+INT_OFF+7*8)(R1)
  66. // Finish setting up callbackArgs struct at CB_ARGS(R1)
  67. // struct { index uintptr; args unsafe.Pointer; result uintptr; stackArgs unsafe.Pointer }
  68. // Note: index was already saved earlier (R11 is volatile)
  69. ADD $ARGS_ARRAY, R1, R12
  70. MOVD R12, (CB_ARGS+8)(R1) // args = address of register args
  71. MOVD $0, (CB_ARGS+16)(R1) // result = 0
  72. // stackArgs points to caller's stack arguments at old_R1+96 = R1+FRAME_SIZE+96
  73. ADD $(FRAME_SIZE+96), R1, R12
  74. MOVD R12, (CB_ARGS+24)(R1) // stackArgs = &caller_stack_args
  75. // Call crosscall2 with arguments in registers:
  76. // R3 = fn (from callbackWrap_call closure)
  77. // R4 = frame (address of callbackArgs)
  78. // R6 = ctxt (0)
  79. MOVD ·callbackWrap_call(SB), R3
  80. MOVD (R3), R3 // dereference closure to get fn
  81. ADD $CB_ARGS, R1, R4 // frame = &callbackArgs
  82. MOVD $0, R6 // ctxt = 0
  83. BL crosscall2(SB)
  84. // Get callback result into R3
  85. MOVD (CB_ARGS+16)(R1), R3
  86. // Restore R31
  87. MOVD SAVE_R31(R1), R31
  88. // Deallocate frame
  89. ADD $FRAME_SIZE, R1
  90. // Restore LR from caller's frame (per ELFv2, it was saved at 16(old_R1))
  91. MOVD 16(R1), R0
  92. MOVD R0, LR
  93. RET