/* strlen(src) -- Return length of string SRC For Intel 80x86, x>=3. Used only if x>=5 actually. */ #include #include "asm-syntax.h" /* INPUT PARAMETERS: src (sp + 4) Inner loop: n cycles Startup: 2 if aligned, else 4+n cycles (max. 7 cycles) Final: 8 cycles */ .text ENTRY(strlen): movl 4(%esp),%eax /* Load the string's address */ testl $3,%eax /* Is it aligned? */ je L(6) addl $3, %eax /* Add 2^n-1 */ xorl %ecx, %ecx cmpb %cl, -3(%eax) /* Check if the length was 0 */ jz L(5) cmpb %cl, -2(%eax) /* or 1 */ jz L(4) cmpb %cl, -1(%eax) /* or 2 */ jz L(3) andl $~3, %eax /* Align EAX to a DWORD */ jmp L(6) L(3): mov $2, %eax /* Return 2 */ jmp L(9) L(4): mov $1, %eax /* Return 1 */ jmp L(9) L(5): mov %ecx, %eax /* Return 0 */ jmp L(9) ALIGN(4) L(6): /* Here we put -1 in ECX and XOR it with EDX to get the complement, instead of putting EDX and XORing with -1. We would need two instructions anyway, and this achieves better pairing. We might also use LEA to subtract, and simply XOR ECX with -1, but it is difficult to avoid the AGI stall. This sequence achieves perfect pairing. */ movl (%eax),%ecx /* Read 4 bytes */ movl $-1, %edx /* Prepare to complement */ xorl $ecx, %edx /* Get their complement in ECX */ subl $0x01010101,%ecx /* Decrement each byte in ECX */ addl $4,%eax xorl %edx, %ecx /* See which bits changed */ andl $0x80808080,%ecx /* Did the high bits change? */ je L(6) /* No, go on */ ALIGN(2) /* The last four bytes */ leal -4(%eax),%edx /* Get their address */ movl -4(%eax), %eax /* Load them in EAX, it has better pairing */ testl $0xFF, %eax /* Is the low byte zero? */ jz L(8) /* We're done */ incl %eax testl $0xFF00, %eax /* Is the second one zero? */ jz L(8) /* Increment by one */ incl %eax testl $0xFF0000, %eax /* Is the third one zero? */ jz L(8) /* Increment by two */ incl %eax /* Else by three */ ALIGN(2) L(8): subl 4(%esp),%edx /* Compute the length */ L(9): movl %edx, %eax ret END (strlen)