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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
#++
#
# Copyright (c) 1993 by
# Digital Equipment Corporation, Maynard, MA
#
# This software is furnished under a license and may be used and copied
# only in accordance with the terms of such license and with the
# inclusion of the above copyright notice. This software or any other
# copies thereof may not be provided or otherwise made available to any
# other person. No title to and ownership of the software is hereby
# transferred.
#
# The information in this software is subject to change without notice
# and should not be construed as a commitment by Digital Equipment
# Corporation.
#
# Digital assumes no responsibility for the use or reliability of its
# software on equipment which is not supplied by Digital.
#
# Facility:
#
# GEM/OTS - GEM compiler system support library
#
# Abstract:
#
# OTS character string support, Alpha version
#
# Authors:
#
# Bill Noyce
#
#
# long ots_strcmp_eqls(char *str1, long strlen, char *str2);
# compares two strings of the same length.
# returns r0=1 if str1=str2, r0=0 otherwise.
# long ots_strcmp_eql(char *str1, long str1len, char *str2, long str2len);
# compares two strings of different lengths, without padding.
# returns r0=1 if str1=str2, r0=0 otherwise.
#
# Special conventions: No stack space, r16-r21 and r27-r28 ONLY,
# no linkage pointer required.
# (Warning: The auto-loader potentially takes some regs across
# the call if this is being used in a shared lib. environment.)
#
# Modification history:
#
# 005 27 Aug 1991 WBN Initial version, replacing BLISS -004
#
# 006 19 May 1992 KDG Changes for common VMS/OSF sources
#
# 007 22 Sep 1992 KDG Add case-sensitive name
#
# 008 26 Jan 1993 KDG Add underscore
#--
#include "ots_defs.hs"
# r16 --> A
# r17 = len
# r18 --> B
# returns r0=1 if equal, r0=0 if not equal
# destroys r16-r21, r27-r28
#.align octa
.globl _OtsStringCompareEqlSameLen
.ent _OtsStringCompareEqlSameLen
_OtsStringCompareEqlSameLen:
.set noat
.set noreorder
.frame sp,0,r26
subq r17, 8, r19 # More than 8 bytes to compare?
beq r17, equal # Done if empty strings
join: ldq_u r20, (r16) # Get first QW containing part of A
addq r18, r17, r27 # Point to end of B
ldq_u r21, (r18) # Get first QW containing part of B
bgt r19, big # Skip if more than 8 bytes
ldq_u r27, -1(r27) # Get last QW containing part of B
addq r16, r17, r28 # Point to end of A
extql r20, r16, r20 # Get first part of A
ldq_u r28, -1(r28) # Get last QW containing part of A
extql r21, r18, r21 # Get first part of B
extqh r27, r18, r27 # Get last part of B
extqh r28, r16, r28 # Get last part of A
or r21, r27, r27 # Combine B
or r20, r28, r28 # Combine A
xor r28, r27, r0 # Are they different?
extqh r0, r19, r0 # Discard differences after length
nop
cmpeq r0, 0, r0 # Return 1 or 0 as xor=0 or not
ret r31, (r26)
equal: mov 1, r0 # Return true
ret r31, (r26)
# r16 --> A
# r17 = A_len
# r18 --> B
# r19 = B_len
# returns r0=1 if equal, r0=0 if not equal
# destroys r16-r21, r27-r28
#
nop #.align octa
nop
.globl _OtsStringCompareEql
.aent _OtsStringCompareEql
_OtsStringCompareEql:
.frame sp,0,r26
cmpeq r17, r19, r0 # Are lengths equal?
beq r17, done # If one is zero, no compares needed
subq r17, 8, r19 # More than 8 bytes to compare?
blbs r0, join # Only compare if lengths equal
done: ret r31, (r26) # Return result of length comparison
#.odd
big: and r16, 7, r0 # A alignment, or amount not compared
subq r18, r0, r18 # Back up B pointer that much
and r18, 7, r17 # Is B now aligned?
addq r19, r0, r19 # (Len-8+align) is amount left to do
ldq_u r27, 8(r18) # Get next QW of B
subq r19, 16, r19 # More than 2 QW's left?
bne r17, unalign # Skip if B alignment doesn't match
xor r20, r21, r0 # Compare first (partial) QW
ldq_u r28, 8(r16) # Get next QW of A
mskqh r0, r16, r0 # Discard junk preceding strings
ble r19, bottom # Skip if two quadwords or less to go
# stall
loop: ldq_u r20, 16(r16) # Get yet another QW of A
bne r0, not_eq # Done if difference in prior compare
xor r28, r27, r0 # Compare prior QW's
ldq r21, 16(r18) # Get yet another QW of B
subq r19, 16, r19 # Decrement length
bne r0, not_eq # Done if difference in this compare
ldq r27, 24(r18) # Get next QW of B
addq r18, 16, r18 # Increment pointer
ldq_u r28, 24(r16) # Get next QW of A
addq r16, 16, r16 # Increment pointer
xor r20, r21, r0 # Compare QW's loaded at top of loop
bgt r19, loop # Repeat until two or less QWs left
bottom: addq r19, 8, r19 # More than 1 QW left?
bne r0, not_eq # Done if difference in prior compare
xor r28, r27, r0 # Compare QW's just loaded
ble r19, last # Skip if this is last compare
ldq_u r28, 16(r16) # Get last QW of A
bne r0, not_eq # Done if difference in this compare
ldq r27, 16(r18) # Get last QW of B
#2 stalls
xor r28, r27, r0 # Compare last QW's
last: extqh r0, r19, r0 # Discard diffs after length
nop
cmpeq r0, 0, r0 # Return 1 or 0 as xor=0 or not
ret r31, (r26)
#.align quad
unalign:
extql r21, r18, r21 # Get first part of B
extqh r27, r18, r0 # Get second part of B
#stall
or r0, r21, r21 # Combine pieces of B
xor r20, r21, r0 # Compare with A
mskqh r0, r16, r0 # Trim junk preceding strings
blt r19, bott_u # Skip if fewer than 16 bytes left
loop_u: ldq_u r21, 16(r18) # Get more B
subq r19, 16, r19 # Decrement length
extql r27, r18, r17 # Get piece of B from prior QW
bne r0, not_eq # Done if r1.ne.r2
ldq_u r27, 24(r18) # Get still more B
addq r18, 16, r18 # Increment B pointer
ldq_u r28, 8(r16) # Get more A
extqh r21, r18, r0 # Get piece of B from first QW in loop
ldq_u r20, 16(r16) # Get still more A
extql r21, r18, r21 # Get second piece of B from there
or r17, r0, r17 # Combine pieces for first B
xor r28, r17, r0 # Compare with first A
extqh r27, r18, r17 # Start building second B
bne r0, not_eq # Done if r28.ne.r17
addq r16, 16, r16 # Increment A pointer
or r17, r21, r21 # Combine pieces for second B
xor r20, r21, r0 # Compare with second A
bge r19, loop_u # Repeat if at least 16 more bytes
bott_u: and r19, 8, r17 # At least 8 more bytes?
bne r0, not_eq # Done if r1.ne.r2
and r19, 7, r19 # How many odd bytes?
beq r17, last_u # Skip if not a whole QW
extql r27, r18, r17 # Get a piece of B
ldq_u r27, 16(r18) # Load another QW of B
addq r18, 8, r18 # Increment B pointer
ldq_u r28, 8(r16) # Load another QW of A
addq r16, 8, r16 # Increment A pointer
extqh r27, r18, r0 # Get a piece of new B QW
#stall
or r17, r0, r17 # Combine pieces
xor r28, r17, r0 # Compare with A
nop
bne r0, not_eq # Done if r28.ne.r17
last_u: addq r18, r19, r17 # Point to end of B
beq r19, eql_u # Return true if no more bytes
ldq_u r28, 8(r16) # Get last QW of A
ldq_u r20, 7(r17) # Get QW containing end of B
extql r27, r18, r27 # Get piece of prior B QW
#stall
extqh r20, r18, r0 # Get a piece of last B QW
#stall
or r27, r0, r27 # Combine
xor r28, r27, r0 # Compare with A
mskql r0, r19, r0 # Discard diffs after strings
nop
eql_u: cmpeq r0, 0, r0 # Return 1 or 0 as xor=0 or not
ret r31, (r26)
not_eq: clr r0 # Return false
ret r31, (r26)
.set at
.set reorder
.end _OtsStringCompareEqlSameLen
|