| // Copyright 2025 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| #include "go_asm.h" | |
| #include "textflag.h" | |
| // Offsets into Thread Environment Block (pointer in R18) | |
| #define TEB_error 0x68 | |
| TEXT ·StdCall<ABIInternal>(SB),NOSPLIT,$0 | |
| B ·asmstdcall(SB) | |
| TEXT ·asmstdcall(SB),NOSPLIT,$16 | |
| STP (R19, R20), 16(RSP) // save old R19, R20 | |
| MOVD R0, R19 // save fn pointer | |
| MOVD RSP, R20 // save stack pointer | |
| // SetLastError(0) | |
| MOVD $0, TEB_error(R18_PLATFORM) | |
| MOVD StdCallInfo_Args(R19), R12 | |
| // Do we have more than 8 arguments? | |
| MOVD StdCallInfo_N(R19), R0 | |
| CMP $0, R0; BEQ _0args | |
| CMP $1, R0; BEQ _1args | |
| CMP $2, R0; BEQ _2args | |
| CMP $3, R0; BEQ _3args | |
| CMP $4, R0; BEQ _4args | |
| CMP $5, R0; BEQ _5args | |
| CMP $6, R0; BEQ _6args | |
| CMP $7, R0; BEQ _7args | |
| CMP $8, R0; BEQ _8args | |
| // Reserve stack space for remaining args | |
| SUB $8, R0, R2 | |
| ADD $1, R2, R3 // make even number of words for stack alignment | |
| AND $~1, R3 | |
| LSL $3, R3 | |
| SUB R3, RSP | |
| // R4: size of stack arguments (n-8)*8 | |
| // R5: &args[8] | |
| // R6: loop counter, from 0 to (n-8)*8 | |
| // R7: scratch | |
| // R8: copy of RSP - (R2)(RSP) assembles as (R2)(ZR) | |
| SUB $8, R0, R4 | |
| LSL $3, R4 | |
| ADD $(8*8), R12, R5 | |
| MOVD $0, R6 | |
| MOVD RSP, R8 | |
| stackargs: | |
| MOVD (R6)(R5), R7 | |
| MOVD R7, (R6)(R8) | |
| ADD $8, R6 | |
| CMP R6, R4 | |
| BNE stackargs | |
| _8args: | |
| MOVD (7*8)(R12), R7 | |
| _7args: | |
| MOVD (6*8)(R12), R6 | |
| _6args: | |
| MOVD (5*8)(R12), R5 | |
| _5args: | |
| MOVD (4*8)(R12), R4 | |
| _4args: | |
| MOVD (3*8)(R12), R3 | |
| _3args: | |
| MOVD (2*8)(R12), R2 | |
| _2args: | |
| MOVD (1*8)(R12), R1 | |
| _1args: | |
| MOVD (0*8)(R12), R0 | |
| _0args: | |
| MOVD StdCallInfo_Fn(R19), R12 | |
| BL (R12) | |
| MOVD R20, RSP // free stack space | |
| MOVD R0, StdCallInfo_R1(R19) // save return value | |
| // TODO(rsc) floating point like amd64 in StdCallInfo_R2? | |
| // GetLastError | |
| MOVD TEB_error(R18_PLATFORM), R0 | |
| // Restore callee-saved registers. | |
| LDP 16(RSP), (R19, R20) | |
| RET |