| /* |
| * strcmp for ARMv6-M (optimized for performance, not size) |
| * |
| * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| * See https://llvm.org/LICENSE.txt for license information. |
| * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| */ |
| |
| #if __ARM_ARCH == 6 && __ARM_ARCH_6M__ >= 1 |
| |
| .thumb_func |
| .syntax unified |
| .arch armv6-m |
| |
| .macro DoSub n, label |
| subs r0, r0, r1 |
| #ifdef __ARM_BIG_ENDIAN |
| lsrs r1, r4, \n |
| #else |
| lsls r1, r4, \n |
| #endif |
| orrs r1, r0 |
| bne \label |
| .endm |
| |
| .macro Byte_Test n, label |
| lsrs r0, r2, \n |
| lsrs r1, r3, \n |
| DoSub \n, \label |
| .endm |
| |
| ENTRY_ALIGN (__strcmp_armv6m, 4) |
| mov r2, r0 |
| push {r4, r5, r6, lr} |
| orrs r2, r1 |
| lsls r2, r2, #30 |
| bne 6f |
| ldr r5, =0x01010101 |
| lsls r6, r5, #7 |
| 1: |
| ldmia r0!, {r2} |
| ldmia r1!, {r3} |
| subs r4, r2, r5 |
| bics r4, r2 |
| ands r4, r6 |
| beq 3f |
| |
| #ifdef __ARM_BIG_ENDIAN |
| Byte_Test #24, 4f |
| Byte_Test #16, 4f |
| Byte_Test #8, 4f |
| |
| b 7f |
| 3: |
| cmp r2, r3 |
| beq 1b |
| cmp r2, r3 |
| #else |
| uxtb r0, r2 |
| uxtb r1, r3 |
| DoSub #24, 2f |
| |
| uxth r0, r2 |
| uxth r1, r3 |
| DoSub #16, 2f |
| |
| lsls r0, r2, #8 |
| lsls r1, r3, #8 |
| lsrs r0, r0, #8 |
| lsrs r1, r1, #8 |
| DoSub #8, 2f |
| |
| lsrs r0, r2, #24 |
| lsrs r1, r3, #24 |
| subs r0, r0, r1 |
| 2: |
| pop {r4, r5, r6, pc} |
| |
| 3: |
| cmp r2, r3 |
| beq 1b |
| rev r0, r2 |
| rev r1, r3 |
| cmp r0, r1 |
| #endif |
| |
| bls 5f |
| movs r0, #1 |
| 4: |
| pop {r4, r5, r6, pc} |
| 5: |
| movs r0, #0 |
| mvns r0, r0 |
| pop {r4, r5, r6, pc} |
| 6: |
| ldrb r2, [r0, #0] |
| ldrb r3, [r1, #0] |
| adds r0, #1 |
| adds r1, #1 |
| cmp r2, #0 |
| beq 7f |
| cmp r2, r3 |
| bne 7f |
| ldrb r2, [r0, #0] |
| ldrb r3, [r1, #0] |
| adds r0, #1 |
| adds r1, #1 |
| cmp r2, #0 |
| beq 7f |
| cmp r2, r3 |
| beq 6b |
| 7: |
| subs r0, r2, r3 |
| pop {r4, r5, r6, pc} |
| |
| END (__strcmp_armv6m) |
| |
| #endif /* __ARM_ARCH == 6 && __ARM_ARCH_6M__ >= 1 */ |