1// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#include "go_asm.h"
6#include "textflag.h"
7
8TEXT ·Compare(SB),NOSPLIT,$0-28
9	MOVL	a_base+0(FP), SI
10	MOVL	a_len+4(FP), BX
11	MOVL	b_base+12(FP), DI
12	MOVL	b_len+16(FP), DX
13	LEAL	ret+24(FP), AX
14	JMP	cmpbody<>(SB)
15
16TEXT runtime·cmpstring(SB),NOSPLIT,$0-20
17	MOVL	a_base+0(FP), SI
18	MOVL	a_len+4(FP), BX
19	MOVL	b_base+8(FP), DI
20	MOVL	b_len+12(FP), DX
21	LEAL	ret+16(FP), AX
22	JMP	cmpbody<>(SB)
23
24// input:
25//   SI = a
26//   DI = b
27//   BX = alen
28//   DX = blen
29//   AX = address of return word (set to 1/0/-1)
30TEXT cmpbody<>(SB),NOSPLIT,$0-0
31	MOVL	DX, BP
32	SUBL	BX, DX // DX = blen-alen
33	JLE	2(PC)
34	MOVL	BX, BP // BP = min(alen, blen)
35	CMPL	SI, DI
36	JEQ	allsame
37	CMPL	BP, $4
38	JB	small
39#ifdef GO386_softfloat
40	JMP	mediumloop
41#endif
42largeloop:
43	CMPL	BP, $16
44	JB	mediumloop
45	MOVOU	(SI), X0
46	MOVOU	(DI), X1
47	PCMPEQB X0, X1
48	PMOVMSKB X1, BX
49	XORL	$0xffff, BX	// convert EQ to NE
50	JNE	diff16	// branch if at least one byte is not equal
51	ADDL	$16, SI
52	ADDL	$16, DI
53	SUBL	$16, BP
54	JMP	largeloop
55
56diff16:
57	BSFL	BX, BX	// index of first byte that differs
58	XORL	DX, DX
59	MOVB	(SI)(BX*1), CX
60	CMPB	CX, (DI)(BX*1)
61	SETHI	DX
62	LEAL	-1(DX*2), DX	// convert 1/0 to +1/-1
63	MOVL	DX, (AX)
64	RET
65
66mediumloop:
67	CMPL	BP, $4
68	JBE	_0through4
69	MOVL	(SI), BX
70	MOVL	(DI), CX
71	CMPL	BX, CX
72	JNE	diff4
73	ADDL	$4, SI
74	ADDL	$4, DI
75	SUBL	$4, BP
76	JMP	mediumloop
77
78_0through4:
79	MOVL	-4(SI)(BP*1), BX
80	MOVL	-4(DI)(BP*1), CX
81	CMPL	BX, CX
82	JEQ	allsame
83
84diff4:
85	BSWAPL	BX	// reverse order of bytes
86	BSWAPL	CX
87	XORL	BX, CX	// find bit differences
88	BSRL	CX, CX	// index of highest bit difference
89	SHRL	CX, BX	// move a's bit to bottom
90	ANDL	$1, BX	// mask bit
91	LEAL	-1(BX*2), BX // 1/0 => +1/-1
92	MOVL	BX, (AX)
93	RET
94
95	// 0-3 bytes in common
96small:
97	LEAL	(BP*8), CX
98	NEGL	CX
99	JEQ	allsame
100
101	// load si
102	CMPB	SI, $0xfc
103	JA	si_high
104	MOVL	(SI), SI
105	JMP	si_finish
106si_high:
107	MOVL	-4(SI)(BP*1), SI
108	SHRL	CX, SI
109si_finish:
110	SHLL	CX, SI
111
112	// same for di
113	CMPB	DI, $0xfc
114	JA	di_high
115	MOVL	(DI), DI
116	JMP	di_finish
117di_high:
118	MOVL	-4(DI)(BP*1), DI
119	SHRL	CX, DI
120di_finish:
121	SHLL	CX, DI
122
123	BSWAPL	SI	// reverse order of bytes
124	BSWAPL	DI
125	XORL	SI, DI	// find bit differences
126	JEQ	allsame
127	BSRL	DI, CX	// index of highest bit difference
128	SHRL	CX, SI	// move a's bit to bottom
129	ANDL	$1, SI	// mask bit
130	LEAL	-1(SI*2), BX // 1/0 => +1/-1
131	MOVL	BX, (AX)
132	RET
133
134	// all the bytes in common are the same, so we just need
135	// to compare the lengths.
136allsame:
137	XORL	BX, BX
138	XORL	CX, CX
139	TESTL	DX, DX
140	SETLT	BX	// 1 if alen > blen
141	SETEQ	CX	// 1 if alen == blen
142	LEAL	-1(CX)(BX*2), BX	// 1,0,-1 result
143	MOVL	BX, (AX)
144	RET
145