sys_s390x.s 3.1 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. // S390X ELF ABI:
  8. // - Integer args: R2-R6 (5 registers)
  9. // - Float args: F0, F2, F4, F6 (4 registers, even-numbered)
  10. // - Return: R2 (integer), F0 (float)
  11. // - Stack pointer: R15
  12. // - Link register: R14
  13. // - Callee-saved: R6-R13, F8-F15 (but R6 is also used for 5th param)
  14. //
  15. // Stack frame layout (aligned to 8 bytes):
  16. // 0(R15) - back chain
  17. // 8(R15) - reserved
  18. // 16(R15) - reserved
  19. // ... - register save area (R6-R15 at 48(R15))
  20. // 160(R15) - parameter area start (args beyond registers)
  21. //
  22. // We need space for:
  23. // - 160 bytes standard frame (with register save area)
  24. // - Stack args a6-a15 (10 * 8 = 80 bytes)
  25. // - Saved args pointer (8 bytes)
  26. // - Padding for alignment
  27. // Total: 264 bytes (rounded to 8-byte alignment)
  28. #define STACK_SIZE 264
  29. #define STACK_ARGS 160
  30. #define ARGP_SAVE 248
  31. GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
  32. DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
  33. TEXT syscall15X(SB), NOSPLIT, $0
  34. // On entry, R2 contains the args pointer
  35. // Save callee-saved registers in caller's frame (per ABI)
  36. STMG R6, R15, 48(R15)
  37. // Allocate our stack frame
  38. MOVD R15, R1
  39. SUB $STACK_SIZE, R15
  40. MOVD R1, 0(R15) // back chain
  41. // Save args pointer
  42. MOVD R2, ARGP_SAVE(R15)
  43. // R9 := args pointer (syscall15Args*)
  44. MOVD R2, R9
  45. // Load float args into F0, F2, F4, F6 (s390x uses even-numbered FPRs)
  46. FMOVD syscall15Args_f1(R9), F0
  47. FMOVD syscall15Args_f2(R9), F2
  48. FMOVD syscall15Args_f3(R9), F4
  49. FMOVD syscall15Args_f4(R9), F6
  50. // Load integer args into R2-R6 (5 registers)
  51. MOVD syscall15Args_a1(R9), R2
  52. MOVD syscall15Args_a2(R9), R3
  53. MOVD syscall15Args_a3(R9), R4
  54. MOVD syscall15Args_a4(R9), R5
  55. MOVD syscall15Args_a5(R9), R6
  56. // Spill remaining args (a6-a15) onto the stack at 160(R15)
  57. MOVD ARGP_SAVE(R15), R9 // reload args pointer
  58. MOVD syscall15Args_a6(R9), R1
  59. MOVD R1, (STACK_ARGS+0*8)(R15)
  60. MOVD syscall15Args_a7(R9), R1
  61. MOVD R1, (STACK_ARGS+1*8)(R15)
  62. MOVD syscall15Args_a8(R9), R1
  63. MOVD R1, (STACK_ARGS+2*8)(R15)
  64. MOVD syscall15Args_a9(R9), R1
  65. MOVD R1, (STACK_ARGS+3*8)(R15)
  66. MOVD syscall15Args_a10(R9), R1
  67. MOVD R1, (STACK_ARGS+4*8)(R15)
  68. MOVD syscall15Args_a11(R9), R1
  69. MOVD R1, (STACK_ARGS+5*8)(R15)
  70. MOVD syscall15Args_a12(R9), R1
  71. MOVD R1, (STACK_ARGS+6*8)(R15)
  72. MOVD syscall15Args_a13(R9), R1
  73. MOVD R1, (STACK_ARGS+7*8)(R15)
  74. MOVD syscall15Args_a14(R9), R1
  75. MOVD R1, (STACK_ARGS+8*8)(R15)
  76. MOVD syscall15Args_a15(R9), R1
  77. MOVD R1, (STACK_ARGS+9*8)(R15)
  78. // Call function
  79. MOVD syscall15Args_fn(R9), R1
  80. BL (R1)
  81. // Restore args pointer for storing results
  82. MOVD ARGP_SAVE(R15), R9
  83. // Store integer results back (R2, R3)
  84. MOVD R2, syscall15Args_a1(R9)
  85. MOVD R3, syscall15Args_a2(R9)
  86. // Store float return values (F0, F2, F4, F6)
  87. FMOVD F0, syscall15Args_f1(R9)
  88. FMOVD F2, syscall15Args_f2(R9)
  89. FMOVD F4, syscall15Args_f3(R9)
  90. FMOVD F6, syscall15Args_f4(R9)
  91. // Deallocate stack frame
  92. ADD $STACK_SIZE, R15
  93. // Restore callee-saved registers from caller's save area
  94. LMG 48(R15), R6, R15
  95. RET