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

     1  // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
     2  // Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
     3  // Portions Copyright 2009 The Go Authors. All rights reserved.
     4  //
     5  // Permission is hereby granted, free of charge, to any person obtaining a copy
     6  // of this software and associated documentation files (the "Software"), to deal
     7  // in the Software without restriction, including without limitation the rights
     8  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     9  // copies of the Software, and to permit persons to whom the Software is
    10  // furnished to do so, subject to the following conditions:
    11  //
    12  // The above copyright notice and this permission notice shall be included in
    13  // all copies or substantial portions of the Software.
    14  //
    15  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    17  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    18  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    19  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    20  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    21  // THE SOFTWARE.
    22  
    23  #include "textflag.h"
    24  
    25  // handleMemcpyFault returns (the value stored in AX, the value stored in DI).
    26  // Control is transferred to it when memcpy below receives SIGSEGV or SIGBUS,
    27  // with the faulting address stored in AX and the signal number stored in DI.
    28  //
    29  // It must have the same frame configuration as memcpy so that it can undo any
    30  // potential call frame set up by the assembler.
    31  TEXT handleMemcpyFault(SB), NOSPLIT|NOFRAME, $0-36
    32  	MOVQ	AX, addr+24(FP)
    33  	MOVL	DI, sig+32(FP)
    34  	RET
    35  
    36  // memcpy copies data from src to dst. If a SIGSEGV or SIGBUS signal is received
    37  // during the copy, it returns the address that caused the fault and the number
    38  // of the signal that was received. Otherwise, it returns an unspecified address
    39  // and a signal number of 0.
    40  //
    41  // Data is copied in order, such that if a fault happens at address p, it is
    42  // safe to assume that all data before p-maxRegisterSize has already been
    43  // successfully copied.
    44  //
    45  // The code is derived from the forward copying part of runtime.memmove.
    46  //
    47  // func memcpy(dst, src unsafe.Pointer, n uintptr) (fault unsafe.Pointer, sig int32)
    48  TEXT ·memcpy(SB), NOSPLIT|NOFRAME, $0-36
    49  	// Store 0 as the returned signal number. If we run to completion,
    50  	// this is the value the caller will see; if a signal is received,
    51  	// handleMemcpyFault will store a different value in this address.
    52  	MOVL	$0, sig+32(FP)
    53  
    54  	MOVQ	dst+0(FP), DI
    55  	MOVQ	src+8(FP), SI
    56  	MOVQ	n+16(FP), BX
    57  
    58  tail:
    59  	// BSR+branch table make almost all memmove/memclr benchmarks worse. Not
    60  	// worth doing.
    61  	TESTQ	BX, BX
    62  	JEQ	move_0
    63  	CMPQ	BX, $2
    64  	JBE	move_1or2
    65  	CMPQ	BX, $4
    66  	JBE	move_3or4
    67  	CMPQ	BX, $8
    68  	JB	move_5through7
    69  	JE	move_8
    70  	CMPQ	BX, $16
    71  	JBE	move_9through16
    72  	CMPQ	BX, $32
    73  	JBE	move_17through32
    74  	CMPQ	BX, $64
    75  	JBE	move_33through64
    76  	CMPQ	BX, $128
    77  	JBE	move_65through128
    78  	CMPQ	BX, $256
    79  	JBE	move_129through256
    80  
    81  move_257plus:
    82  	SUBQ	$256, BX
    83  	MOVOU	(SI), X0
    84  	MOVOU	X0, (DI)
    85  	MOVOU	16(SI), X1
    86  	MOVOU	X1, 16(DI)
    87  	MOVOU	32(SI), X2
    88  	MOVOU	X2, 32(DI)
    89  	MOVOU	48(SI), X3
    90  	MOVOU	X3, 48(DI)
    91  	MOVOU	64(SI), X4
    92  	MOVOU	X4, 64(DI)
    93  	MOVOU	80(SI), X5
    94  	MOVOU	X5, 80(DI)
    95  	MOVOU	96(SI), X6
    96  	MOVOU	X6, 96(DI)
    97  	MOVOU	112(SI), X7
    98  	MOVOU	X7, 112(DI)
    99  	MOVOU	128(SI), X8
   100  	MOVOU	X8, 128(DI)
   101  	MOVOU	144(SI), X9
   102  	MOVOU	X9, 144(DI)
   103  	MOVOU	160(SI), X10
   104  	MOVOU	X10, 160(DI)
   105  	MOVOU	176(SI), X11
   106  	MOVOU	X11, 176(DI)
   107  	MOVOU	192(SI), X12
   108  	MOVOU	X12, 192(DI)
   109  	MOVOU	208(SI), X13
   110  	MOVOU	X13, 208(DI)
   111  	MOVOU	224(SI), X14
   112  	MOVOU	X14, 224(DI)
   113  	MOVOU	240(SI), X15
   114  	MOVOU	X15, 240(DI)
   115  	CMPQ	BX, $256
   116  	LEAQ	256(SI), SI
   117  	LEAQ	256(DI), DI
   118  	JGE	move_257plus
   119  	JMP	tail
   120  
   121  move_1or2:
   122  	MOVB	(SI), AX
   123  	MOVB	AX, (DI)
   124  	MOVB	-1(SI)(BX*1), CX
   125  	MOVB	CX, -1(DI)(BX*1)
   126  	RET
   127  move_0:
   128  	RET
   129  move_3or4:
   130  	MOVW	(SI), AX
   131  	MOVW	AX, (DI)
   132  	MOVW	-2(SI)(BX*1), CX
   133  	MOVW	CX, -2(DI)(BX*1)
   134  	RET
   135  move_5through7:
   136  	MOVL	(SI), AX
   137  	MOVL	AX, (DI)
   138  	MOVL	-4(SI)(BX*1), CX
   139  	MOVL	CX, -4(DI)(BX*1)
   140  	RET
   141  move_8:
   142  	// We need a separate case for 8 to make sure we write pointers atomically.
   143  	MOVQ	(SI), AX
   144  	MOVQ	AX, (DI)
   145  	RET
   146  move_9through16:
   147  	MOVQ	(SI), AX
   148  	MOVQ	AX, (DI)
   149  	MOVQ	-8(SI)(BX*1), CX
   150  	MOVQ	CX, -8(DI)(BX*1)
   151  	RET
   152  move_17through32:
   153  	MOVOU	(SI), X0
   154  	MOVOU	X0, (DI)
   155  	MOVOU	-16(SI)(BX*1), X1
   156  	MOVOU	X1, -16(DI)(BX*1)
   157  	RET
   158  move_33through64:
   159  	MOVOU	(SI), X0
   160  	MOVOU	X0, (DI)
   161  	MOVOU	16(SI), X1
   162  	MOVOU	X1, 16(DI)
   163  	MOVOU	-32(SI)(BX*1), X2
   164  	MOVOU	X2, -32(DI)(BX*1)
   165  	MOVOU	-16(SI)(BX*1), X3
   166  	MOVOU	X3, -16(DI)(BX*1)
   167  	RET
   168  move_65through128:
   169  	MOVOU	(SI), X0
   170  	MOVOU	X0, (DI)
   171  	MOVOU	16(SI), X1
   172  	MOVOU	X1, 16(DI)
   173  	MOVOU	32(SI), X2
   174  	MOVOU	X2, 32(DI)
   175  	MOVOU	48(SI), X3
   176  	MOVOU	X3, 48(DI)
   177  	MOVOU	-64(SI)(BX*1), X4
   178  	MOVOU	X4, -64(DI)(BX*1)
   179  	MOVOU	-48(SI)(BX*1), X5
   180  	MOVOU	X5, -48(DI)(BX*1)
   181  	MOVOU	-32(SI)(BX*1), X6
   182  	MOVOU	X6, -32(DI)(BX*1)
   183  	MOVOU	-16(SI)(BX*1), X7
   184  	MOVOU	X7, -16(DI)(BX*1)
   185  	RET
   186  move_129through256:
   187  	MOVOU	(SI), X0
   188  	MOVOU	X0, (DI)
   189  	MOVOU	16(SI), X1
   190  	MOVOU	X1, 16(DI)
   191  	MOVOU	32(SI), X2
   192  	MOVOU	X2, 32(DI)
   193  	MOVOU	48(SI), X3
   194  	MOVOU	X3, 48(DI)
   195  	MOVOU	64(SI), X4
   196  	MOVOU	X4, 64(DI)
   197  	MOVOU	80(SI), X5
   198  	MOVOU	X5, 80(DI)
   199  	MOVOU	96(SI), X6
   200  	MOVOU	X6, 96(DI)
   201  	MOVOU	112(SI), X7
   202  	MOVOU	X7, 112(DI)
   203  	MOVOU	-128(SI)(BX*1), X8
   204  	MOVOU	X8, -128(DI)(BX*1)
   205  	MOVOU	-112(SI)(BX*1), X9
   206  	MOVOU	X9, -112(DI)(BX*1)
   207  	MOVOU	-96(SI)(BX*1), X10
   208  	MOVOU	X10, -96(DI)(BX*1)
   209  	MOVOU	-80(SI)(BX*1), X11
   210  	MOVOU	X11, -80(DI)(BX*1)
   211  	MOVOU	-64(SI)(BX*1), X12
   212  	MOVOU	X12, -64(DI)(BX*1)
   213  	MOVOU	-48(SI)(BX*1), X13
   214  	MOVOU	X13, -48(DI)(BX*1)
   215  	MOVOU	-32(SI)(BX*1), X14
   216  	MOVOU	X14, -32(DI)(BX*1)
   217  	MOVOU	-16(SI)(BX*1), X15
   218  	MOVOU	X15, -16(DI)(BX*1)
   219  	RET
   220  
   221  // func addrOfMemcpy() uintptr
   222  TEXT ·addrOfMemcpy(SB), $0-8
   223  	MOVQ	$·memcpy(SB), AX
   224  	MOVQ	AX, ret+0(FP)
   225  	RET