| // Copyright 2014 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. | |
| // +build ppc64 ppc64le | |
| #include "textflag.h" | |
| // void runtime·memmove(void*, void*, uintptr) | |
| TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24 | |
| MOVD to+0(FP), R3 | |
| MOVD from+8(FP), R4 | |
| MOVD n+16(FP), R5 | |
| // Determine if there are doublewords to | |
| // copy so a more efficient move can be done | |
| check: | |
| ANDCC $7, R5, R7 // R7: bytes to copy | |
| SRAD $3, R5, R6 // R6: double words to copy | |
| CMP R6, $0, CR1 // CR1[EQ] set if no double words to copy | |
| // Determine overlap by subtracting dest - src and comparing against the | |
| // length. The catches the cases where src and dest are in different types | |
| // of storage such as stack and static to avoid doing backward move when not | |
| // necessary. | |
| SUB R4, R3, R8 // dest - src | |
| CMPU R8, R5, CR2 // < len? | |
| BC 12, 8, backward // BLT CR2 backward | |
| // Copying forward if no overlap. | |
| BC 12, 6, noforwardlarge // "BEQ CR1, noforwardlarge" | |
| MOVD R6,CTR // R6 = number of double words | |
| SRADCC $2,R6,R8 // 32 byte chunks? | |
| BNE forward32setup // | |
| // Move double words | |
| forward8: | |
| MOVD 0(R4), R8 // double word | |
| ADD $8,R4 | |
| MOVD R8, 0(R3) // | |
| ADD $8,R3 | |
| BC 16, 0, forward8 | |
| BR noforwardlarge // handle remainder | |
| // Prepare for moves of 32 bytes at a time. | |
| forward32setup: | |
| DCBTST (R3) // prepare data cache | |
| DCBT (R4) | |
| MOVD R8, CTR // double work count | |
| forward32: | |
| MOVD 0(R4), R8 // load 4 double words | |
| MOVD 8(R4), R9 | |
| MOVD 16(R4), R14 | |
| MOVD 24(R4), R15 | |
| ADD $32,R4 | |
| MOVD R8, 0(R3) // store those 4 | |
| MOVD R9, 8(R3) | |
| MOVD R14,16(R3) | |
| MOVD R15,24(R3) | |
| ADD $32,R3 // bump up for next set | |
| BC 16, 0, forward32 // continue | |
| RLDCLCC $61,R5,$3,R6 // remaining doublewords | |
| BEQ noforwardlarge | |
| MOVD R6,CTR // set up the CTR | |
| BR forward8 | |
| noforwardlarge: | |
| CMP R7,$0 // any remaining bytes | |
| BC 4, 1, LR | |
| forwardtail: | |
| MOVD R7, CTR // move tail bytes | |
| forwardtailloop: | |
| MOVBZ 0(R4), R8 // move single bytes | |
| ADD $1,R4 | |
| MOVBZ R8, 0(R3) | |
| ADD $1,R3 | |
| BC 16, 0, forwardtailloop | |
| RET | |
| backward: | |
| // Copying backwards proceeds by copying R7 bytes then copying R6 double words. | |
| // R3 and R4 are advanced to the end of the destination/source buffers | |
| // respectively and moved back as we copy. | |
| ADD R5, R4, R4 // end of source | |
| ADD R3, R5, R3 // end of dest | |
| BEQ nobackwardtail // earlier condition | |
| MOVD R7, CTR // bytes to move | |
| backwardtailloop: | |
| MOVBZ -1(R4), R8 // point to last byte | |
| SUB $1,R4 | |
| MOVBZ R8, -1(R3) | |
| SUB $1,R3 | |
| BC 16, 0, backwardtailloop | |
| nobackwardtail: | |
| CMP R6,$0 | |
| BC 4, 5, LR | |
| backwardlarge: | |
| MOVD R6, CTR | |
| backwardlargeloop: | |
| MOVD -8(R4), R8 | |
| SUB $8,R4 | |
| MOVD R8, -8(R3) | |
| SUB $8,R3 | |
| BC 16, 0, backwardlargeloop // | |
| RET |