github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/safecopy/memcpy_arm64.s (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include "textflag.h"
     6  
     7  // handleMemcpyFault returns (the value stored in R0, the value stored in R1).
     8  // Control is transferred to it when memcpy below receives SIGSEGV or SIGBUS,
     9  // with the faulting address stored in R0 and the signal number stored in R1.
    10  //
    11  // It must have the same frame configuration as memcpy so that it can undo any
    12  // potential call frame set up by the assembler.
    13  TEXT handleMemcpyFault(SB), NOSPLIT, $0-36
    14  	MOVD R0, addr+24(FP)
    15  	MOVW R1, sig+32(FP)
    16  	RET
    17  
    18  // memcpy copies data from src to dst. If a SIGSEGV or SIGBUS signal is received
    19  // during the copy, it returns the address that caused the fault and the number
    20  // of the signal that was received. Otherwise, it returns an unspecified address
    21  // and a signal number of 0.
    22  //
    23  // Data is copied in order, such that if a fault happens at address p, it is
    24  // safe to assume that all data before p-maxRegisterSize has already been
    25  // successfully copied.
    26  //
    27  // The code is derived from the Go source runtime.memmove.
    28  //
    29  // func memcpy(dst, src unsafe.Pointer, n uintptr) (fault unsafe.Pointer, sig int32)
    30  TEXT ·memcpy(SB), NOSPLIT, $-8-36
    31  	// Store 0 as the returned signal number. If we run to completion,
    32  	// this is the value the caller will see; if a signal is received,
    33  	// handleMemcpyFault will store a different value in this address.
    34  	MOVW $0, sig+32(FP)
    35  
    36  	MOVD dst+0(FP), R3
    37  	MOVD src+8(FP), R4
    38  	MOVD n+16(FP), R5
    39  	CMP $0, R5
    40  	BNE check
    41  	RET
    42  
    43  check:
    44  	AND $~7, R5, R7     // R7 is N&~7.
    45  	SUB R7, R5, R6      // R6 is N&7.
    46  
    47  	// Copying forward proceeds by copying R7/8 words then copying R6 bytes.
    48  	// R3 and R4 are advanced as we copy.
    49  
    50  	// (There may be implementations of armv8 where copying by bytes until
    51  	// at least one of source or dest is word aligned is a worthwhile
    52  	// optimization, but the on the one tested so far (xgene) it did not
    53  	// make a significance difference.)
    54  
    55  	CMP $0, R7          // Do we need to do any word-by-word copying?
    56  	BEQ noforwardlarge
    57  	ADD R3, R7, R9      // R9 points just past where we copy by word.
    58  
    59  forwardlargeloop:
    60  	MOVD.P 8(R4), R8       // R8 is just a scratch register.
    61  	MOVD.P R8, 8(R3)
    62  	CMP R3, R9
    63  	BNE forwardlargeloop
    64  
    65  noforwardlarge:
    66  	CMP $0, R6          // Do we need to do any byte-by-byte copying?
    67  	BNE forwardtail
    68  	RET
    69  
    70  forwardtail:
    71  	ADD R3, R6, R9      // R9 points just past the destination memory.
    72  
    73  forwardtailloop:
    74  	MOVBU.P 1(R4), R8
    75  	MOVBU.P R8, 1(R3)
    76  	CMP R3, R9
    77  	BNE forwardtailloop
    78  	RET
    79  
    80  // func addrOfMemcpy() uintptr
    81  TEXT ·addrOfMemcpy(SB), $0-8
    82  	MOVD	$·memcpy(SB), R0
    83  	MOVD	R0, ret+0(FP)
    84  	RET