summaryrefslogtreecommitdiffstats
path: root/private/crt32/misc/alpha/scmplss.s
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/misc/alpha/scmplss.s')
-rw-r--r--private/crt32/misc/alpha/scmplss.s339
1 files changed, 339 insertions, 0 deletions
diff --git a/private/crt32/misc/alpha/scmplss.s b/private/crt32/misc/alpha/scmplss.s
new file mode 100644
index 000000000..ab043fb8f
--- /dev/null
+++ b/private/crt32/misc/alpha/scmplss.s
@@ -0,0 +1,339 @@
+ #++
+ #
+ # 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_lsss(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_lss(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 29 Jan 1992 WBN Use .otsent macro
+ #
+ # 007 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 008 22 Sep 1992 KDG Add case-sensitive name
+ #
+ # 009 26 Jan 1993 KDG Add underscore
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 --> A
+ # r17 = A_len
+ # r18 --> B
+ # r19 = B_len
+ # returns r0=1 if A less, r0=0 if A greater/equal
+ # destroys r16-r21, r27-r28
+ #
+ .globl _OtsStringCompareLss
+ .ent _OtsStringCompareLss
+_OtsStringCompareLss:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+
+ subq r17, r19, r21 # A_len - B_len
+ cmovgt r21, r19, r17 # r17 = min length
+ br r31, join
+
+ # r16 --> A
+ # r17 = len
+ # r18 --> B
+ # returns r0=1 if A less, r0=0 if A greater/equal
+ # destroys r16-r21, r27-r28
+ #
+ .globl _OtsStringCompareLssSameLen
+ .aent _OtsStringCompareLssSameLen
+_OtsStringCompareLssSameLen:
+ .frame sp,0,r26
+
+ clr r21 # Lengths are equal
+
+join: subq r17, 8, r19 # More than 8 bytes to compare?
+ beq r17, equal # Done if empty strings
+
+ ldq_u r20, (r16) # Get first QW containing part of A
+ addq r18, r17, r27 # Point to end of B
+
+ ldq_u r17, (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, r19, r28 # Point to end of A
+
+ extql r20, r16, r20 # Get first part of A
+
+ ldq_u r28, 7(r28) # Get last QW containing part of A
+
+ extql r17, r18, r17 # Get first part of B
+
+ extqh r27, r18, r27 # Get last part of B
+
+ extqh r28, r16, r28 # Get last part of A
+
+ or r17, r27, r27 # Combine B
+
+ or r20, r28, r28 # Combine A
+
+ xor r28, r27, r0 # Are they different?
+
+ beq r19, ck_leq
+ mskql r0, r19, r0 # Discard differences after length
+
+ #stall
+
+ck_leq: cmpbge r31, r0, r17 # Where is B = A?
+ beq r0, equal # (Skip if they're equal?)
+
+ cmpbge r27, r28, r28 # Where is B >= A?
+
+ addq r17, 1, r0 # Flip first difference
+
+ andnot r28, r17, r28 # Where is B > A?
+
+ and r28, r0, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ #.odd
+big: and r16, 7, r28 # A alignment, or amount not compared
+
+ subq r18, r28, r18 # Back up B pointer that much
+
+ and r18, 7, r0 # Is B now aligned?
+
+ addq r19, r28, 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 r0, unalign # Skip if B alignment doesn't match
+
+ xor r20, r17, 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: bne r0, neq_2017 # Done if difference in prior compare
+ ldq_u r20, 16(r16) # Get yet another QW of A
+
+ xor r28, r27, r0 # Compare prior QW's
+ ldq r17, 16(r18) # Get yet another QW of B
+
+ subq r19, 16, r19 # Decrement length
+ bne r0, neq_2827 # 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, r17, 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, neq_2017 # Done if difference in prior compare
+
+ xor r28, r27, r0 # Compare QW's just loaded
+ ble r19, last # Skip if this is last compare
+
+ bne r0, neq_2827 # Done if difference in this compare
+ ldq_u r28, 16(r16) # Get last QW of A
+
+ ldq r27, 16(r18) # Get last QW of B
+ subq r19, 8, r19
+
+ #2 stalls
+
+ xor r28, r27, r0 # Compare last QW's
+last: beq r19, ck_last
+
+ mskql r0, r19, r0 # Discard diffs after length
+
+ck_last:
+ bne r0, neq_2827 # See which is greater
+
+equal: cmplt r21, r31, r0 # Equal: return A_len < B_len
+ ret r31, (r26)
+
+ #.align quad
+unalign:
+ extql r17, r18, r17 # Get first part of B
+
+ extqh r27, r18, r0 # Get second part of B
+
+ #stall
+
+ or r0, r17, r17 # Combine pieces of B
+
+ xor r20, r17, 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 r17, 16(r18) # Get more B
+ subq r19, 16, r19 # Decrement length
+
+ bne r0, neq_20xx # Done if r20.ne.r17
+ extql r27, r18, r20 # Get piece of B from prior QW
+
+ 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 r17, r18, r0 # Get piece of B from first QW in loop
+
+ extql r17, r18, r17 # Get second piece of B from there
+
+ or r20, r0, r0 # Combine pieces for first B
+
+ ldq_u r20, 16(r16) # Get still more A
+ xor r28, r0, r0 # Compare with first A
+
+ bne r0, neq_28xx # Done if r28.ne.r0
+ extqh r27, r18, r0 # Start building second B
+
+ addq r16, 16, r16 # Increment A pointer
+
+ or r0, r17, r17 # Combine pieces for second B
+
+ xor r20, r17, r0 # Compare with second A
+ bge r19, loop_u # Repeat if at least 16 more bytes
+
+bott_u: and r19, 8, r28 # At least 8 more bytes?
+ bne r0, neq_2017 # Done if r20.ne.r17
+
+ and r19, 7, r19 # How many odd bytes?
+ beq r28, last_u # Skip if not a whole QW
+
+ extql r27, r18, r20 # 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 r20, r0, r20 # Combine pieces
+
+ xor r28, r20, r0 # Compare with A
+
+ nop
+ bne r0, neq_28xx # Done if r28.ne.r20
+
+last_u: addq r18, r19, r17 # Point to end of B
+ beq r19, eql_u # Check length diff 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
+
+ #stall
+
+ beq r0, eql_u # Done if they're still equal
+
+ #.align quad
+neq_28xx:
+ xor r28, r0, r27 # Recover B from A and xor
+neq_2827:
+ cmpbge r31, r0, r17 # Where is B = A?
+
+ cmpbge r27, r28, r20 # Where is B >= A?
+
+ addq r17, 1, r0 # Flip first difference
+
+ andnot r20, r17, r20 # Where is B > A?
+
+ and r20, r0, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ #.align quad
+neq_20xx:
+ xor r20, r0, r17 # Recover B from A and xor
+neq_2017:
+ cmpbge r31, r0, r27 # Where is B = A?
+
+ cmpbge r17, r20, r20 # Where is B >= A?
+
+ addq r27, 1, r0 # Flip first difference
+
+ andnot r20, r27, r20 # Where is B > A?
+
+ and r20, r0, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+
+eql_u: cmplt r21, r31, r0 # Equal: return A_len < B_len
+ ret r31, (r26)
+
+
+ .set at
+ .set reorder
+ .end _OtsStringCompareLss