Regarding strncmp fix

venki kaps venkiece2005 at gmail.com
Mon May 4 07:27:05 UTC 2009


Hi,
 This is my idea only.

strncmp problem report:
========================
In the following below website:
*http://archive.netbsd.se/?ml=freebsd-arm&a=2009-04&m=10547557*

Hi,

 I am using the freebsd implementation of strncmp for ARM which is an

 assembly implementation.



 I have a small doubt, when i tested the strncmp by passing the third
argument:

 'n' as -1 the return values is '0' instead it should '-1'.



 When the third argument to strncmp is as below:

      ret = strncmp("a","b",-1)



I think the assembly implementation in > src/lib/libc/arm/string/strncmp.S
file needs

to be modified to take care of the above condition.

In the current implementation



 /* if ((len - 1)

subs r2, r2, #1

movmi r0, #0

RETc(mi)



This should be changed to check as below

 /* if ((len ) /* Assembly code here */



FreeBSD source:

===============



ENTRY(strncmp)

/* if ((len - 1) < 0) return 0 */

      subs  r2, r2, #1

      movmi r0, #0

      RETc(mi)



/* ip == last src address to compare */

      add   ip, r0, r2

1:

      ldrb  r2, [r0], #1

      ldrb  r3, [r1], #1

      cmp   ip, r0

      cmpcs r2, #1

      cmpcs r2, r3

      beq   1b

      sub   r0, r2, r3

      RET





Tinguely has given one solution for this:



ENTRY(strncmp)

      /* if (len == 0) return 0 */

      cmp r2, #0

      moveq r0, #0

      RETeq

      /* ip == last src address to compare */

      add ip, r0, r2

1:

      ldrb r2, [r0], #1

      ldrb r3, [r1], #1

      cmp ip, r0

-     cmpcs r2, #1

+     beq 2f

+     cmp r2, #1

      cmpcs r2, r3

      beq 1b

+2:

      sub r0, r2, r3

      RET



The above fix is nice.



But small change in the fix:



ENTRY(strncmp)

      /* if (len == 0) return 0 */

      cmp r2, #0

      moveq r0, #0

      RETeq

      /* ip == last src address to compare */

      add ip, r0, r2

1:

      ldrb r2, [r0], #1

      ldrb r3, [r1], #1

      cmp ip, r0

-     cmpcs r2, #1

+     cmp r2, #1 /* to igonre Carry falg set (unsigned higher or same) */

      cmpcs r2, r3

      beq 1b

      sub r0, r2, r3

      RET



Branch to 2f is not required since conditional

assemblers automatically calls subroutine when

compare fails.

And also we can reduce no. of cycles(3 cycles) since
3 cycles required to branch.





But I have one smaller query:

Will it support the above code in the ARM-thumb mode?



NOTE:

      Thumb mode and traditional mode instruction sets are different.



Thumb mode implementation:



/* if (len == 0) return 0 */

      cmp r2, #0

      bne 1f

      mov r0, #0

      RET

1:

      /* ip == last src address to compare */

      add ip, r0, r2

2:

      cmp ip, r0

      beq 3f

      ldrb r2, [r0]

      add r0, r0, #1

      ldrb r3, [r1]

      add r1, r1, #1

      cmp r2, #0

      beq 3f

      cmp r2, r3

      beq 2b

3:

      sub r0, r2, r3

      RET



Will need to support both thumb mode as well as traditional mode?



Example:

#ifdef __thumb__

      /* thumb code here */

#else

      /* traditional code here */

#endif





Thanks & Regards,

Venkappa


More information about the freebsd-arm mailing list