| // 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. |
| |
| #include "go_asm.h" |
| #include "textflag.h" |
| |
| |
| TEXT ·IndexByte<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-40 |
| #ifndef GOEXPERIMENT_regabiargs |
| MOVD b_base+0(FP), R2// b_base => R2 |
| MOVD b_len+8(FP), R3 // b_len => R3 |
| MOVBZ c+24(FP), R4 // c => R4 |
| MOVD $ret+32(FP), R5 // &ret => R5 |
| #else |
| MOVD R5, R4 |
| AND $0xff, R4 |
| #endif |
| BR indexbytebody<>(SB) |
| |
| TEXT ·IndexByteString<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32 |
| #ifndef GOEXPERIMENT_regabiargs |
| MOVD s_base+0(FP), R2 // s_base => R2 |
| MOVD s_len+8(FP), R3 // s_len => R3 |
| MOVBZ c+16(FP), R4 // c => R4 |
| MOVD $ret+24(FP), R5 // &ret => R5 |
| #else |
| AND $0xff, R4 |
| #endif |
| BR indexbytebody<>(SB) |
| |
| // input: |
| // R2: s |
| // R3: s_len |
| // R4: c -- byte sought |
| // For regabiargs output value(index) stored in R2 |
| // For !regabiargs address of output value(index) stored in R5 |
| TEXT indexbytebody<>(SB),NOSPLIT|NOFRAME,$0 |
| CMPBEQ R3, $0, notfound |
| MOVD R2, R6 // store base for later |
| ADD R2, R3, R8 // the address after the end of the string |
| //if the length is small, use loop; otherwise, use vector or srst search |
| CMPBGE R3, $16, large |
| |
| residual: |
| CMPBEQ R2, R8, notfound |
| MOVBZ 0(R2), R7 |
| LA 1(R2), R2 |
| CMPBNE R7, R4, residual |
| |
| found: |
| SUB R6, R2 |
| SUB $1, R2 |
| #ifndef GOEXPERIMENT_regabiargs |
| MOVD R2, 0(R5) |
| #endif |
| RET |
| |
| notfound: |
| #ifndef GOEXPERIMENT_regabiargs |
| MOVD $-1, 0(R5) |
| #else |
| MOVD $-1, R2 |
| #endif |
| RET |
| |
| large: |
| MOVBZ internal∕cpu·S390X+const_offsetS390xHasVX(SB), R1 |
| CMPBNE R1, $0, vectorimpl |
| |
| srstimpl: // no vector facility |
| MOVBZ R4, R0 // c needs to be in R0, leave until last minute as currently R0 is expected to be 0 |
| srstloop: |
| WORD $0xB25E0082 // srst %r8, %r2 (search the range [R2, R8)) |
| BVS srstloop // interrupted - continue |
| BGT notfoundr0 |
| foundr0: |
| XOR R0, R0 // reset R0 |
| SUB R6, R8 // remove base |
| #ifndef GOEXPERIMENT_regabiargs |
| MOVD R8, 0(R5) |
| #else |
| MOVD R8, R2 |
| #endif |
| RET |
| notfoundr0: |
| XOR R0, R0 // reset R0 |
| #ifndef GOEXPERIMENT_regabiargs |
| MOVD $-1, 0(R5) |
| #else |
| MOVD $-1, R2 |
| #endif |
| RET |
| |
| vectorimpl: |
| //if the address is not 16byte aligned, use loop for the header |
| MOVD R2, R8 |
| AND $15, R8 |
| CMPBGT R8, $0, notaligned |
| |
| aligned: |
| ADD R6, R3, R8 |
| MOVD R8, R7 |
| AND $-16, R7 |
| // replicate c across V17 |
| VLVGB $0, R4, V19 |
| VREPB $0, V19, V17 |
| |
| vectorloop: |
| CMPBGE R2, R7, residual |
| VL 0(R2), V16 // load string to be searched into V16 |
| ADD $16, R2 |
| VFEEBS V16, V17, V18 // search V17 in V16 and set conditional code accordingly |
| BVS vectorloop |
| |
| // when vector search found c in the string |
| VLGVB $7, V18, R7 // load 7th element of V18 containing index into R7 |
| SUB $16, R2 |
| SUB R6, R2 |
| ADD R2, R7 |
| #ifndef GOEXPERIMENT_regabiargs |
| MOVD R7, 0(R5) |
| #else |
| MOVD R7, R2 |
| #endif |
| RET |
| |
| notaligned: |
| MOVD R2, R8 |
| AND $-16, R8 |
| ADD $16, R8 |
| notalignedloop: |
| CMPBEQ R2, R8, aligned |
| MOVBZ 0(R2), R7 |
| LA 1(R2), R2 |
| CMPBNE R7, R4, notalignedloop |
| BR found |
| |