| // Copyright 2016 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 "textflag.h" | 
 |  | 
 | // See memmove Go doc for important implementation constraints. | 
 |  | 
 | // void runtime·memmove(void*, void*, uintptr) | 
 | TEXT runtime·memmove<ABIInternal>(SB),NOSPLIT,$-0-24 | 
 | 	// X10 = to | 
 | 	// X11 = from | 
 | 	// X12 = n | 
 | 	BEQ	X10, X11, done | 
 | 	BEQZ	X12, done | 
 |  | 
 | 	// If the destination is ahead of the source, start at the end of the | 
 | 	// buffer and go backward. | 
 | 	BGTU	X10, X11, backward | 
 |  | 
 | 	// If less than 8 bytes, do single byte copies. | 
 | 	MOV	$8, X9 | 
 | 	BLT	X12, X9, f_loop4_check | 
 |  | 
 | 	// Check alignment - if alignment differs we have to do one byte at a time. | 
 | 	AND	$7, X10, X5 | 
 | 	AND	$7, X11, X6 | 
 | 	BNE	X5, X6, f_loop8_unaligned_check | 
 | 	BEQZ	X5, f_loop_check | 
 |  | 
 | 	// Move one byte at a time until we reach 8 byte alignment. | 
 | 	SUB	X5, X9, X5 | 
 | 	SUB	X5, X12, X12 | 
 | f_align: | 
 | 	SUB	$1, X5 | 
 | 	MOVB	0(X11), X14 | 
 | 	MOVB	X14, 0(X10) | 
 | 	ADD	$1, X10 | 
 | 	ADD	$1, X11 | 
 | 	BNEZ	X5, f_align | 
 |  | 
 | f_loop_check: | 
 | 	MOV	$16, X9 | 
 | 	BLT	X12, X9, f_loop8_check | 
 | 	MOV	$32, X9 | 
 | 	BLT	X12, X9, f_loop16_check | 
 | 	MOV	$64, X9 | 
 | 	BLT	X12, X9, f_loop32_check | 
 | f_loop64: | 
 | 	MOV	0(X11), X14 | 
 | 	MOV	8(X11), X15 | 
 | 	MOV	16(X11), X16 | 
 | 	MOV	24(X11), X17 | 
 | 	MOV	32(X11), X18 | 
 | 	MOV	40(X11), X19 | 
 | 	MOV	48(X11), X20 | 
 | 	MOV	56(X11), X21 | 
 | 	MOV	X14, 0(X10) | 
 | 	MOV	X15, 8(X10) | 
 | 	MOV	X16, 16(X10) | 
 | 	MOV	X17, 24(X10) | 
 | 	MOV	X18, 32(X10) | 
 | 	MOV	X19, 40(X10) | 
 | 	MOV	X20, 48(X10) | 
 | 	MOV	X21, 56(X10) | 
 | 	ADD	$64, X10 | 
 | 	ADD	$64, X11 | 
 | 	SUB	$64, X12 | 
 | 	BGE	X12, X9, f_loop64 | 
 | 	BEQZ	X12, done | 
 |  | 
 | f_loop32_check: | 
 | 	MOV	$32, X9 | 
 | 	BLT	X12, X9, f_loop16_check | 
 | f_loop32: | 
 | 	MOV	0(X11), X14 | 
 | 	MOV	8(X11), X15 | 
 | 	MOV	16(X11), X16 | 
 | 	MOV	24(X11), X17 | 
 | 	MOV	X14, 0(X10) | 
 | 	MOV	X15, 8(X10) | 
 | 	MOV	X16, 16(X10) | 
 | 	MOV	X17, 24(X10) | 
 | 	ADD	$32, X10 | 
 | 	ADD	$32, X11 | 
 | 	SUB	$32, X12 | 
 | 	BGE	X12, X9, f_loop32 | 
 | 	BEQZ	X12, done | 
 |  | 
 | f_loop16_check: | 
 | 	MOV	$16, X9 | 
 | 	BLT	X12, X9, f_loop8_check | 
 | f_loop16: | 
 | 	MOV	0(X11), X14 | 
 | 	MOV	8(X11), X15 | 
 | 	MOV	X14, 0(X10) | 
 | 	MOV	X15, 8(X10) | 
 | 	ADD	$16, X10 | 
 | 	ADD	$16, X11 | 
 | 	SUB	$16, X12 | 
 | 	BGE	X12, X9, f_loop16 | 
 | 	BEQZ	X12, done | 
 |  | 
 | f_loop8_check: | 
 | 	MOV	$8, X9 | 
 | 	BLT	X12, X9, f_loop4_check | 
 | f_loop8: | 
 | 	MOV	0(X11), X14 | 
 | 	MOV	X14, 0(X10) | 
 | 	ADD	$8, X10 | 
 | 	ADD	$8, X11 | 
 | 	SUB	$8, X12 | 
 | 	BGE	X12, X9, f_loop8 | 
 | 	BEQZ	X12, done | 
 | 	JMP	f_loop4_check | 
 |  | 
 | f_loop8_unaligned_check: | 
 | 	MOV	$8, X9 | 
 | 	BLT	X12, X9, f_loop4_check | 
 | f_loop8_unaligned: | 
 | 	MOVB	0(X11), X14 | 
 | 	MOVB	1(X11), X15 | 
 | 	MOVB	2(X11), X16 | 
 | 	MOVB	3(X11), X17 | 
 | 	MOVB	4(X11), X18 | 
 | 	MOVB	5(X11), X19 | 
 | 	MOVB	6(X11), X20 | 
 | 	MOVB	7(X11), X21 | 
 | 	MOVB	X14, 0(X10) | 
 | 	MOVB	X15, 1(X10) | 
 | 	MOVB	X16, 2(X10) | 
 | 	MOVB	X17, 3(X10) | 
 | 	MOVB	X18, 4(X10) | 
 | 	MOVB	X19, 5(X10) | 
 | 	MOVB	X20, 6(X10) | 
 | 	MOVB	X21, 7(X10) | 
 | 	ADD	$8, X10 | 
 | 	ADD	$8, X11 | 
 | 	SUB	$8, X12 | 
 | 	BGE	X12, X9, f_loop8_unaligned | 
 |  | 
 | f_loop4_check: | 
 | 	MOV	$4, X9 | 
 | 	BLT	X12, X9, f_loop1 | 
 | f_loop4: | 
 | 	MOVB	0(X11), X14 | 
 | 	MOVB	1(X11), X15 | 
 | 	MOVB	2(X11), X16 | 
 | 	MOVB	3(X11), X17 | 
 | 	MOVB	X14, 0(X10) | 
 | 	MOVB	X15, 1(X10) | 
 | 	MOVB	X16, 2(X10) | 
 | 	MOVB	X17, 3(X10) | 
 | 	ADD	$4, X10 | 
 | 	ADD	$4, X11 | 
 | 	SUB	$4, X12 | 
 | 	BGE	X12, X9, f_loop4 | 
 |  | 
 | f_loop1: | 
 | 	BEQZ	X12, done | 
 | 	MOVB	0(X11), X14 | 
 | 	MOVB	X14, 0(X10) | 
 | 	ADD	$1, X10 | 
 | 	ADD	$1, X11 | 
 | 	SUB	$1, X12 | 
 | 	JMP	f_loop1 | 
 |  | 
 | backward: | 
 | 	ADD	X10, X12, X10 | 
 | 	ADD	X11, X12, X11 | 
 |  | 
 | 	// If less than 8 bytes, do single byte copies. | 
 | 	MOV	$8, X9 | 
 | 	BLT	X12, X9, b_loop4_check | 
 |  | 
 | 	// Check alignment - if alignment differs we have to do one byte at a time. | 
 | 	AND	$7, X10, X5 | 
 | 	AND	$7, X11, X6 | 
 | 	BNE	X5, X6, b_loop8_unaligned_check | 
 | 	BEQZ	X5, b_loop_check | 
 |  | 
 | 	// Move one byte at a time until we reach 8 byte alignment. | 
 | 	SUB	X5, X12, X12 | 
 | b_align: | 
 | 	SUB	$1, X5 | 
 | 	SUB	$1, X10 | 
 | 	SUB	$1, X11 | 
 | 	MOVB	0(X11), X14 | 
 | 	MOVB	X14, 0(X10) | 
 | 	BNEZ	X5, b_align | 
 |  | 
 | b_loop_check: | 
 | 	MOV	$16, X9 | 
 | 	BLT	X12, X9, b_loop8_check | 
 | 	MOV	$32, X9 | 
 | 	BLT	X12, X9, b_loop16_check | 
 | 	MOV	$64, X9 | 
 | 	BLT	X12, X9, b_loop32_check | 
 | b_loop64: | 
 | 	SUB	$64, X10 | 
 | 	SUB	$64, X11 | 
 | 	MOV	0(X11), X14 | 
 | 	MOV	8(X11), X15 | 
 | 	MOV	16(X11), X16 | 
 | 	MOV	24(X11), X17 | 
 | 	MOV	32(X11), X18 | 
 | 	MOV	40(X11), X19 | 
 | 	MOV	48(X11), X20 | 
 | 	MOV	56(X11), X21 | 
 | 	MOV	X14, 0(X10) | 
 | 	MOV	X15, 8(X10) | 
 | 	MOV	X16, 16(X10) | 
 | 	MOV	X17, 24(X10) | 
 | 	MOV	X18, 32(X10) | 
 | 	MOV	X19, 40(X10) | 
 | 	MOV	X20, 48(X10) | 
 | 	MOV	X21, 56(X10) | 
 | 	SUB	$64, X12 | 
 | 	BGE	X12, X9, b_loop64 | 
 | 	BEQZ	X12, done | 
 |  | 
 | b_loop32_check: | 
 | 	MOV	$32, X9 | 
 | 	BLT	X12, X9, b_loop16_check | 
 | b_loop32: | 
 | 	SUB	$32, X10 | 
 | 	SUB	$32, X11 | 
 | 	MOV	0(X11), X14 | 
 | 	MOV	8(X11), X15 | 
 | 	MOV	16(X11), X16 | 
 | 	MOV	24(X11), X17 | 
 | 	MOV	X14, 0(X10) | 
 | 	MOV	X15, 8(X10) | 
 | 	MOV	X16, 16(X10) | 
 | 	MOV	X17, 24(X10) | 
 | 	SUB	$32, X12 | 
 | 	BGE	X12, X9, b_loop32 | 
 | 	BEQZ	X12, done | 
 |  | 
 | b_loop16_check: | 
 | 	MOV	$16, X9 | 
 | 	BLT	X12, X9, b_loop8_check | 
 | b_loop16: | 
 | 	SUB	$16, X10 | 
 | 	SUB	$16, X11 | 
 | 	MOV	0(X11), X14 | 
 | 	MOV	8(X11), X15 | 
 | 	MOV	X14, 0(X10) | 
 | 	MOV	X15, 8(X10) | 
 | 	SUB	$16, X12 | 
 | 	BGE	X12, X9, b_loop16 | 
 | 	BEQZ	X12, done | 
 |  | 
 | b_loop8_check: | 
 | 	MOV	$8, X9 | 
 | 	BLT	X12, X9, b_loop4_check | 
 | b_loop8: | 
 | 	SUB	$8, X10 | 
 | 	SUB	$8, X11 | 
 | 	MOV	0(X11), X14 | 
 | 	MOV	X14, 0(X10) | 
 | 	SUB	$8, X12 | 
 | 	BGE	X12, X9, b_loop8 | 
 | 	BEQZ	X12, done | 
 | 	JMP	b_loop4_check | 
 |  | 
 | b_loop8_unaligned_check: | 
 | 	MOV	$8, X9 | 
 | 	BLT	X12, X9, b_loop4_check | 
 | b_loop8_unaligned: | 
 | 	SUB	$8, X10 | 
 | 	SUB	$8, X11 | 
 | 	MOVB	0(X11), X14 | 
 | 	MOVB	1(X11), X15 | 
 | 	MOVB	2(X11), X16 | 
 | 	MOVB	3(X11), X17 | 
 | 	MOVB	4(X11), X18 | 
 | 	MOVB	5(X11), X19 | 
 | 	MOVB	6(X11), X20 | 
 | 	MOVB	7(X11), X21 | 
 | 	MOVB	X14, 0(X10) | 
 | 	MOVB	X15, 1(X10) | 
 | 	MOVB	X16, 2(X10) | 
 | 	MOVB	X17, 3(X10) | 
 | 	MOVB	X18, 4(X10) | 
 | 	MOVB	X19, 5(X10) | 
 | 	MOVB	X20, 6(X10) | 
 | 	MOVB	X21, 7(X10) | 
 | 	SUB	$8, X12 | 
 | 	BGE	X12, X9, b_loop8_unaligned | 
 |  | 
 | b_loop4_check: | 
 | 	MOV	$4, X9 | 
 | 	BLT	X12, X9, b_loop1 | 
 | b_loop4: | 
 | 	SUB	$4, X10 | 
 | 	SUB	$4, X11 | 
 | 	MOVB	0(X11), X14 | 
 | 	MOVB	1(X11), X15 | 
 | 	MOVB	2(X11), X16 | 
 | 	MOVB	3(X11), X17 | 
 | 	MOVB	X14, 0(X10) | 
 | 	MOVB	X15, 1(X10) | 
 | 	MOVB	X16, 2(X10) | 
 | 	MOVB	X17, 3(X10) | 
 | 	SUB	$4, X12 | 
 | 	BGE	X12, X9, b_loop4 | 
 |  | 
 | b_loop1: | 
 | 	BEQZ	X12, done | 
 | 	SUB	$1, X10 | 
 | 	SUB	$1, X11 | 
 | 	MOVB	0(X11), X14 | 
 | 	MOVB	X14, 0(X10) | 
 | 	SUB	$1, X12 | 
 | 	JMP	b_loop1 | 
 |  | 
 | done: | 
 | 	RET |