| // Copyright 2018 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 "go_asm.h" | |
| #include "textflag.h" | |
| TEXT ·Compare(SB),NOSPLIT|NOFRAME,$0-56 | |
| MOVD a_base+0(FP), R5 | |
| MOVD b_base+24(FP), R6 | |
| MOVD a_len+8(FP), R3 | |
| CMP R5,R6,CR7 | |
| MOVD b_len+32(FP), R4 | |
| MOVD $ret+48(FP), R7 | |
| CMP R3,R4,CR6 | |
| BEQ CR7,equal | |
| #ifdef GOARCH_ppc64le | |
| BR cmpbodyLE<>(SB) | |
| #else | |
| BR cmpbodyBE<>(SB) | |
| #endif | |
| equal: | |
| BEQ CR6,done | |
| MOVD $1, R8 | |
| BGT CR6,greater | |
| NEG R8 | |
| greater: | |
| MOVD R8, (R7) | |
| RET | |
| done: | |
| MOVD $0, (R7) | |
| RET | |
| TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40 | |
| MOVD a_base+0(FP), R5 | |
| MOVD b_base+16(FP), R6 | |
| MOVD a_len+8(FP), R3 | |
| CMP R5,R6,CR7 | |
| MOVD b_len+24(FP), R4 | |
| MOVD $ret+32(FP), R7 | |
| CMP R3,R4,CR6 | |
| BEQ CR7,equal | |
| #ifdef GOARCH_ppc64le | |
| BR cmpbodyLE<>(SB) | |
| #else | |
| BR cmpbodyBE<>(SB) | |
| #endif | |
| equal: | |
| BEQ CR6,done | |
| MOVD $1, R8 | |
| BGT CR6,greater | |
| NEG R8 | |
| greater: | |
| MOVD R8, (R7) | |
| RET | |
| done: | |
| MOVD $0, (R7) | |
| RET | |
| // Do an efficient memcmp for ppc64le | |
| // R3 = a len | |
| // R4 = b len | |
| // R5 = a addr | |
| // R6 = b addr | |
| // R7 = addr of return value | |
| TEXT cmpbodyLE<>(SB),NOSPLIT|NOFRAME,$0-0 | |
| MOVD R3,R8 // set up length | |
| CMP R3,R4,CR2 // unequal? | |
| BC 12,8,setuplen // BLT CR2 | |
| MOVD R4,R8 // use R4 for comparison len | |
| setuplen: | |
| MOVD R8,CTR // set up loop counter | |
| CMP R8,$8 // only optimize >=8 | |
| BLT simplecheck | |
| DCBT (R5) // cache hint | |
| DCBT (R6) | |
| CMP R8,$32 // optimize >= 32 | |
| MOVD R8,R9 | |
| BLT setup8a // 8 byte moves only | |
| setup32a: | |
| SRADCC $5,R8,R9 // number of 32 byte chunks | |
| MOVD R9,CTR | |
| // Special processing for 32 bytes or longer. | |
| // Loading this way is faster and correct as long as the | |
| // doublewords being compared are equal. Once they | |
| // are found unequal, reload them in proper byte order | |
| // to determine greater or less than. | |
| loop32a: | |
| MOVD 0(R5),R9 // doublewords to compare | |
| MOVD 0(R6),R10 // get 4 doublewords | |
| MOVD 8(R5),R14 | |
| MOVD 8(R6),R15 | |
| CMPU R9,R10 // bytes equal? | |
| MOVD $0,R16 // set up for cmpne | |
| BNE cmpne // further compare for LT or GT | |
| MOVD 16(R5),R9 // get next pair of doublewords | |
| MOVD 16(R6),R10 | |
| CMPU R14,R15 // bytes match? | |
| MOVD $8,R16 // set up for cmpne | |
| BNE cmpne // further compare for LT or GT | |
| MOVD 24(R5),R14 // get next pair of doublewords | |
| MOVD 24(R6),R15 | |
| CMPU R9,R10 // bytes match? | |
| MOVD $16,R16 // set up for cmpne | |
| BNE cmpne // further compare for LT or GT | |
| MOVD $-8,R16 // for cmpne, R5,R6 already inc by 32 | |
| ADD $32,R5 // bump up to next 32 | |
| ADD $32,R6 | |
| CMPU R14,R15 // bytes match? | |
| BC 8,2,loop32a // br ctr and cr | |
| BNE cmpne | |
| ANDCC $24,R8,R9 // Any 8 byte chunks? | |
| BEQ leftover // and result is 0 | |
| setup8a: | |
| SRADCC $3,R9,R9 // get the 8 byte count | |
| BEQ leftover // shifted value is 0 | |
| MOVD R9,CTR // loop count for doublewords | |
| loop8: | |
| MOVDBR (R5+R0),R9 // doublewords to compare | |
| MOVDBR (R6+R0),R10 // LE compare order | |
| ADD $8,R5 | |
| ADD $8,R6 | |
| CMPU R9,R10 // match? | |
| BC 8,2,loop8 // bt ctr <> 0 && cr | |
| BGT greater | |
| BLT less | |
| leftover: | |
| ANDCC $7,R8,R9 // check for leftover bytes | |
| MOVD R9,CTR // save the ctr | |
| BNE simple // leftover bytes | |
| BC 12,10,equal // test CR2 for length comparison | |
| BC 12,8,less | |
| BR greater | |
| simplecheck: | |
| CMP R8,$0 // remaining compare length 0 | |
| BNE simple // do simple compare | |
| BC 12,10,equal // test CR2 for length comparison | |
| BC 12,8,less // 1st len < 2nd len, result less | |
| BR greater // 1st len > 2nd len must be greater | |
| simple: | |
| MOVBZ 0(R5), R9 // get byte from 1st operand | |
| ADD $1,R5 | |
| MOVBZ 0(R6), R10 // get byte from 2nd operand | |
| ADD $1,R6 | |
| CMPU R9, R10 | |
| BC 8,2,simple // bc ctr <> 0 && cr | |
| BGT greater // 1st > 2nd | |
| BLT less // 1st < 2nd | |
| BC 12,10,equal // test CR2 for length comparison | |
| BC 12,9,greater // 2nd len > 1st len | |
| BR less // must be less | |
| cmpne: // only here is not equal | |
| MOVDBR (R5+R16),R8 // reload in reverse order | |
| MOVDBR (R6+R16),R9 | |
| CMPU R8,R9 // compare correct endianness | |
| BGT greater // here only if NE | |
| less: | |
| MOVD $-1,R3 | |
| MOVD R3,(R7) // return value if A < B | |
| RET | |
| equal: | |
| MOVD $0,(R7) // return value if A == B | |
| RET | |
| greater: | |
| MOVD $1,R3 | |
| MOVD R3,(R7) // return value if A > B | |
| RET | |
| // Do an efficient memcmp for ppc64 (BE) | |
| // R3 = a len | |
| // R4 = b len | |
| // R5 = a addr | |
| // R6 = b addr | |
| // R7 = addr of return value | |
| TEXT cmpbodyBE<>(SB),NOSPLIT|NOFRAME,$0-0 | |
| MOVD R3,R8 // set up length | |
| CMP R3,R4,CR2 // unequal? | |
| BC 12,8,setuplen // BLT CR2 | |
| MOVD R4,R8 // use R4 for comparison len | |
| setuplen: | |
| MOVD R8,CTR // set up loop counter | |
| CMP R8,$8 // only optimize >=8 | |
| BLT simplecheck | |
| DCBT (R5) // cache hint | |
| DCBT (R6) | |
| CMP R8,$32 // optimize >= 32 | |
| MOVD R8,R9 | |
| BLT setup8a // 8 byte moves only | |
| setup32a: | |
| SRADCC $5,R8,R9 // number of 32 byte chunks | |
| MOVD R9,CTR | |
| loop32a: | |
| MOVD 0(R5),R9 // doublewords to compare | |
| MOVD 0(R6),R10 // get 4 doublewords | |
| MOVD 8(R5),R14 | |
| MOVD 8(R6),R15 | |
| CMPU R9,R10 // bytes equal? | |
| BLT less // found to be less | |
| BGT greater // found to be greater | |
| MOVD 16(R5),R9 // get next pair of doublewords | |
| MOVD 16(R6),R10 | |
| CMPU R14,R15 // bytes match? | |
| BLT less // found less | |
| BGT greater // found greater | |
| MOVD 24(R5),R14 // get next pair of doublewords | |
| MOVD 24(R6),R15 | |
| CMPU R9,R10 // bytes match? | |
| BLT less // found to be less | |
| BGT greater // found to be greater | |
| ADD $32,R5 // bump up to next 32 | |
| ADD $32,R6 | |
| CMPU R14,R15 // bytes match? | |
| BC 8,2,loop32a // br ctr and cr | |
| BLT less // with BE, byte ordering is | |
| BGT greater // good for compare | |
| ANDCC $24,R8,R9 // Any 8 byte chunks? | |
| BEQ leftover // and result is 0 | |
| setup8a: | |
| SRADCC $3,R9,R9 // get the 8 byte count | |
| BEQ leftover // shifted value is 0 | |
| MOVD R9,CTR // loop count for doublewords | |
| loop8: | |
| MOVD (R5),R9 | |
| MOVD (R6),R10 | |
| ADD $8,R5 | |
| ADD $8,R6 | |
| CMPU R9,R10 // match? | |
| BC 8,2,loop8 // bt ctr <> 0 && cr | |
| BGT greater | |
| BLT less | |
| leftover: | |
| ANDCC $7,R8,R9 // check for leftover bytes | |
| MOVD R9,CTR // save the ctr | |
| BNE simple // leftover bytes | |
| BC 12,10,equal // test CR2 for length comparison | |
| BC 12,8,less | |
| BR greater | |
| simplecheck: | |
| CMP R8,$0 // remaining compare length 0 | |
| BNE simple // do simple compare | |
| BC 12,10,equal // test CR2 for length comparison | |
| BC 12,8,less // 1st len < 2nd len, result less | |
| BR greater // same len, must be equal | |
| simple: | |
| MOVBZ 0(R5),R9 // get byte from 1st operand | |
| ADD $1,R5 | |
| MOVBZ 0(R6),R10 // get byte from 2nd operand | |
| ADD $1,R6 | |
| CMPU R9,R10 | |
| BC 8,2,simple // bc ctr <> 0 && cr | |
| BGT greater // 1st > 2nd | |
| BLT less // 1st < 2nd | |
| BC 12,10,equal // test CR2 for length comparison | |
| BC 12,9,greater // 2nd len > 1st len | |
| less: | |
| MOVD $-1,R3 | |
| MOVD R3,(R7) // return value if A < B | |
| RET | |
| equal: | |
| MOVD $0,(R7) // return value if A == B | |
| RET | |
| greater: | |
| MOVD $1,R3 | |
| MOVD R3,(R7) // return value if A > B | |
| RET |