diff options
Diffstat (limited to 'private/crt32/misc/alpha/scmpeql.s')
-rw-r--r-- | private/crt32/misc/alpha/scmpeql.s | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/private/crt32/misc/alpha/scmpeql.s b/private/crt32/misc/alpha/scmpeql.s new file mode 100644 index 000000000..2d9f82fcc --- /dev/null +++ b/private/crt32/misc/alpha/scmpeql.s @@ -0,0 +1,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 |