summaryrefslogtreecommitdiff
path: root/libc/string/metag/strcmp.S
blob: 3278ffaa5457a666bc82d763fa4a35f21bb2258e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
!    Copyright (C) 2013 Imagination Technologies Ltd.

!    Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.


#include <features.h>

	.text
	.global	_strcmp
	.type	_strcmp,function
!D1Ar1 s1
!D0Ar2 s2
_strcmp:
	TST	D1Ar1,#3
	TSTZ	D0Ar2,#3
	MOVT	D1Re0,#0x0101
	ADD	D1Re0,D1Re0,#0x0101
	BNZ	$Lstrcmp_slow
	GETD	D1Ar3,[D1Ar1+#4++]	! Load 32-bits from s1
	GETD	D1Ar5,[D0Ar2+#4++]      ! Load 32-bits from s2
	LSL	D0FrT,D1Re0,#7		! D0FrT = 0x80808080
$Lstrcmp4_loop:
	SUB	D0Re0,D1Ar3,D1Re0	! D1Re0 = 0x01010101
	MOV	D0Ar6,D1Ar3
	SUBS	D0Ar4,D1Ar3,D1Ar5	! Calculate difference
	XOR	D0Ar6,D0Ar6,#-1
	GETD	D1Ar3,[D1Ar1+#4++]	! Load 32-bits from s1
	AND	D0Re0,D0Re0,D0Ar6
	ANDSZ	D0Ar6,D0Re0,D0FrT	! D0FrT = 0x80808080
	GETD	D1Ar5,[D0Ar2+#4++]      ! Load 32-bits from s2
	BZ	$Lstrcmp4_loop
	AND	D0Ar6, D0Re0, D0FrT	! D0FrT = 0x80808080
!
! Either they are different or they both contain a NULL + junk
!
$Lstrcmp4_end:
	LSLS	D0Re0,D0Ar4,#24		! Was Byte[0] the same?
	LSLSZ	D0Ar2,D0Ar6,#24		! Yes: AND they where not zero?
	LSLSZ	D0Re0,D0Ar4,#16		! Yes: Was Byte[1] the same?
	LSLSZ	D0Ar2,D0Ar6,#16		! Yes: AND they where not zero?
	LSLSZ	D0Re0,D0Ar4,#8		! Tes: Was Byte[2] the same?
	LSLSZ	D0Ar2,D0Ar6,#8		! Yes: AND they where not zero?
	MOVZ	D0Re0,D0Ar4		! Yes: Must by Byte[3] thats the result
	ASR	D0Re0,D0Re0,#24		! Sign extend result to integer
	MOV	PC,D1RtP
!
! Misaligned case, byte at a time
!
$Lstrcmp_slow:
	GETB	D1Ar3,[D1Ar1++]		! Load char from s1
	GETB	D1Ar5,[D0Ar2++]         ! Load char from s2
	CMP	D1Ar3,#1		! Null -> C and NZ, rest -> NC (\1->Z)
	CMPNC	D1Ar3,D1Ar5		! NOT Null: Same -> Z, else -> NZ
	BZ	$Lstrcmp_slow		! NOT Null and Same: Loop
	SUB	D0Re0,D1Ar3,D1Ar5	! Generate result
	MOV	PC,D1RtP

        .size _strcmp,.-_strcmp


libc_hidden_def(strcmp)
#ifndef __UCLIBC_HAS_LOCALE__
strong_alias(strcmp,strcoll)
libc_hidden_def(strcoll)
#endif