sys_s390x.s raw

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