| // 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 |