| 1 |
116 |
Agner |
/********************************* strlen.as ********************************
|
| 2 |
|
|
* Author: Agner Fog
|
| 3 |
|
|
* date created: 2018-03-25
|
| 4 |
|
|
* last modified: 2021-04-25
|
| 5 |
|
|
* Version: 1.09
|
| 6 |
|
|
* Project: ForwardCom library libc.li
|
| 7 |
|
|
* Description: strlen function. Find length of zero-terminated string
|
| 8 |
|
|
* C declaration: int64_t strlen(const char * str)
|
| 9 |
|
|
*
|
| 10 |
|
|
* Copyright 2018-2021 GNU General Public License http://www.gnu.org/licenses
|
| 11 |
|
|
|
| 12 |
|
|
// NOTE: Not up to date !!
|
| 13 |
|
|
*****************************************************************************/
|
| 14 |
|
|
|
| 15 |
|
|
%data_extra_space = 0x100 // maximum length we are allowed to read beyond a string
|
| 16 |
|
|
|
| 17 |
|
|
code section execute align = 4
|
| 18 |
|
|
|
| 19 |
|
|
_strlen function public reguse = 0xF, 0x7
|
| 20 |
|
|
// r0 = str
|
| 21 |
|
|
// start at nearest preceding 8 bytes boundary for efficiency
|
| 22 |
|
|
int64 r1 = r0 & -8 // 8-bytes boundary
|
| 23 |
|
|
int64 r2 = r0 - r1 // length of unused part
|
| 24 |
|
|
int64 r3 = data_extra_space // maximum allowed length
|
| 25 |
|
|
int64 v0 = 0 // zero
|
| 26 |
|
|
int8 v0 = set_len(v0, r3) // make a zero vector with length = min(data_extra_space, max_vector_length)
|
| 27 |
|
|
int64 r3 = get_len(v0) // this vector length will be used
|
| 28 |
|
|
int8 v1 = mask_length(v0, r2, 0), options=1 // mask off unused part
|
| 29 |
|
|
int8 v2 = [r1, length = r3] // read vector
|
| 30 |
|
|
int8 v2 = v1 ? (v0 == v2) : v0 // compare with 0, masked
|
| 31 |
|
|
int8 v1 = bool_reduce(v2) // horizontal OR is in bit 1
|
| 32 |
|
|
// loop as long as no zero is found
|
| 33 |
|
|
while (float !(v1 & 2)) { // (specify float to get vector register)
|
| 34 |
|
|
int64 r1 += r3 // next block of maximum length
|
| 35 |
|
|
int8 v2 = [r1, length = r3] // read vector
|
| 36 |
|
|
int8 v2 = (v0 == v2) // compare with 0, no mask now
|
| 37 |
|
|
int8 v1 = bool_reduce(v2)
|
| 38 |
|
|
}
|
| 39 |
|
|
int8 v2 = bool2bits(v2) // bit index to the end of the string
|
| 40 |
|
|
int64 r3 = -1 // will be zero in first iteration of loop below
|
| 41 |
|
|
BIT64_LOOP: // do while (v1 == 0):
|
| 42 |
|
|
int64 r3++ // point to 64-bit block of v2
|
| 43 |
|
|
int64 v1 = extract(v2, r3) // extract 64 bits from vector v2
|
| 44 |
|
|
double v1 = and(v1, v1), jump_zero BIT64_LOOP // loop while v1 is zero
|
| 45 |
|
|
int64 r2 = vec2gp(v1) // transfer to general purpose register
|
| 46 |
|
|
int64 r2 = bitscan(r2, 0) // get index to first byte
|
| 47 |
|
|
int64 r3 <<= 6 // r3 << 6
|
| 48 |
|
|
int64 r2 += r3 //
|
| 49 |
|
|
// add difference between current block start and string start
|
| 50 |
|
|
int64 r0 = r2 + r1 - r0 // the string length is returned in r0
|
| 51 |
|
|
return
|
| 52 |
|
|
_strlen end
|
| 53 |
|
|
|
| 54 |
|
|
code end
|