1/******************************************************************************* 2 * 3 * Copyright (c) 1993 Intel Corporation 4 * 5 * Intel hereby grants you permission to copy, modify, and distribute this 6 * software and its documentation. Intel grants this permission provided 7 * that the above copyright notice appears in all copies and that both the 8 * copyright notice and this permission notice appear in supporting 9 * documentation. In addition, Intel grants this permission provided that 10 * you prominently mark as "not part of the original" any modifications 11 * made to this software or documentation, and that the name of Intel 12 * Corporation not be used in advertising or publicity pertaining to 13 * distribution of the software or the documentation without specific, 14 * written prior permission. 15 * 16 * Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR 17 * IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY 18 * OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or 19 * representations regarding the use of, or the results of the use of, 20 * the software and documentation in terms of correctness, accuracy, 21 * reliability, currentness, or otherwise; and you rely on the software, 22 * documentation and results solely at your own risk. 23 * 24 * IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, 25 * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES 26 * OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM 27 * PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER. 28 * 29 ******************************************************************************/ 30 31 .file "sncmp_ca.s" 32#ifdef __PIC 33 .pic 34#endif 35#ifdef __PID 36 .pid 37#endif 38/* 39 * (c) copyright 1988,1993 Intel Corp., all rights reserved 40 */ 41 42/* 43 procedure strncmp (optimized assembler version for the CA) 44 45 result = strncmp (src1_addr, src2_addr, max_bytes) 46 47 compare the null terminated string pointed to by src1_addr to 48 the string space pointed to by src2_addr. Return 0 iff the strings 49 are equal, -1 if src1_addr is lexicly less than src2_addr, and 1 50 if it is lexicly greater. Do not compare more than max_bytes bytes. 51 52 Undefined behavior will occur if the end of either source string 53 (i.e. the terminating null byte) is in the last word of the program's 54 allocated memory space. This is so because, in several cases, strncmp 55 will fetch ahead one word. Disallowing the fetch ahead would impose 56 a severe performance penalty. 57 58 This program handles five cases: 59 60 1) both arguments start on a word boundary 61 2) neither are word aligned, but they are offset by the same amount 62 3) source1 is word aligned, source2 is not 63 4) source2 is word aligned, source1 is not 64 5) neither is word aligned, and they are offset by differing amounts 65 66 At the time of this writing, only g0 thru g7 and g14 are available 67 for use in this leafproc; other registers would have to be saved and 68 restored. These nine registers are sufficient to implement the routine. 69 The registers are used as follows: 70 71 g0 original src1 ptr; extracted word; return result 72 g1 src2 ptr; 0xff -- byte extraction mask 73 g2 maximum number of bytes to compare 74 g3 src2 word ptr 75 Little endian: 76 g4 lsw of src1 77 g5 msw of src1 78 g6 src2 word 79 g7 src1 word ptr 80 Big endian: 81 g4 msw of src1 82 g5 lsw of src1 83 g6 src1 word ptr 84 g7 src2 word 85 g13 return address 86 g14 shift count 87*/ 88 89#if __i960_BIG_ENDIAN__ 90#define MSW g4 91#define LSW g5 92#define SRC1 g6 93#define SRC2 g7 94#else 95#define LSW g4 96#define MSW g5 97#define SRC2 g6 98#define SRC1 g7 99#endif 100 101 .globl _strncmp 102 .globl __strncmp 103 .leafproc _strncmp, __strncmp 104 .align 2 105_strncmp: 106#ifndef __PIC 107 lda Lrett,g14 108#else 109 lda Lrett-(.+8)(ip),g14 110#endif 111__strncmp: 112Lrestart: 113 notand g0,3,SRC1 # extract word addr of start of src1 114 lda (g14),g13 # preserve return address 115 cmpibge.f 0,g2,Lequal_exit # return equality if number of bytes to 116 /* compare is none. */ 117#if __i960_BIG_ENDIAN__ 118 cmpo g0,SRC1 # check alignment of src1 119#endif 120 ld (SRC1),LSW # fetch word with at least first byte of src1 121 notand g1,3,g3 # extract word addr of start of src2 122 ld 4(SRC1),MSW # fetch second word of src1 123#if __i960_BIG_ENDIAN__ 124 bne Lsrc1_unaligned # branch if src1 is unaligned 125 cmpo g3,g1 # check alignment of src2 126 ld (g3),SRC2 # fetch word with at least first byte of src2 127 shlo 3,g0,g14 # compute shift count for src1 128 subo g14,0,g14 # adjust shift count for big endian 129 lda 8(SRC1),SRC1 # advance src1 word addr 130 bne.f Lsrc2_unaligned # branch if src2 is NOT word aligned 131 132 /* src2 is word aligned */ 133 134 mov LSW,g0 135 136Lwloop2: # word comparing loop 137 cmpo SRC2,g0 # compare src1 and src2 words 138 lda 0xff000000,g1 # byte extraction mask 139 mov MSW,LSW # move msw of src1 to lsw 140 ld (SRC1),MSW # pre-fetch next msw of src1 141 addo 4,SRC1,SRC1 # post-increment src1 addr 142 lda 4(g3),g3 # pre-increment src2 addr 143 bne.f Lcloop # branch if src1 and src2 unequal 144 scanbyte 0,g0 # check for null byte in src1 word 145 ld (g3),SRC2 # pre-fetch next word of src2 146 mov LSW,g0 # extract word of src1 147 subi 4,g2,g2 # decrement maximum byte count 148 bo.f Lequal_exit # branch if null byte encountered 149 cmpibl.t 0,g2,Lwloop2 # branch if max_bytes not reached yet 150 151 b Lequal_exit # strings were equal up through max_bytes 152 153Lsrc1_unaligned: 154#endif 155 cmpo g3,g1 # check alignment of src2 156 ld (g3),SRC2 # fetch word with at least first byte of src2 157 shlo 3,g0,g14 # compute shift count for src1 158#if __i960_BIG_ENDIAN__ 159 subo g14,0,g14 # adjust shift count for big endian 160#endif 161 eshro g14,g4,LSW # extract word of src1 162 lda 8(SRC1),SRC1 # advance src1 word addr 163 bne.f Lsrc2_unaligned # branch if src2 is NOT word aligned 164 165 /* at least src2 is word aligned */ 166 167 mov LSW,g0 168 169Lwloop: # word comparing loop 170 cmpo SRC2,g0 # compare src1 and src2 words 171#if __i960_BIG_ENDIAN__ 172 lda 0xff000000,g1 # byte extraction mask 173#else 174 lda 0xff,g1 # byte extraction mask 175#endif 176 mov MSW,LSW # move msw of src1 to lsw 177 ld (SRC1),MSW # pre-fetch next msw of src1 178 addo 4,SRC1,SRC1 # post-increment src1 addr 179 lda 4(g3),g3 # pre-increment src2 addr 180 bne.f Lcloop # branch if src1 and src2 unequal 181 scanbyte 0,g0 # check for null byte in src1 word 182 ld (g3),SRC2 # pre-fetch next word of src2 183 eshro g14,g4,g0 # extract word of src1 184 subi 4,g2,g2 # decrement maximum byte count 185 bo.f Lequal_exit # branch if null byte encountered 186 cmpibl.t 0,g2,Lwloop # branch if max_bytes not reached yet 187 188 b Lequal_exit # strings were equal up through max_bytes 189 190Lcloop_setup: # setup for coming from Lsrc2_unaligned 191 mov LSW,g0 # restore extracted src1 word 192#if __i960_BIG_ENDIAN__ 193 lda 0xff000000,g1 # byte extraction mask 194#else 195 lda 0xff,g1 # byte extraction mask 196#endif 197 198Lcloop: # character comparing loop 199 and SRC2,g1,g3 # extract next char of src2 200 and g0,g1,LSW # extract next char of src1 201 cmpobne.f LSW,g3,.diff # check for equality 202 cmpo 0,LSW # check for null byte 203#if __i960_BIG_ENDIAN__ 204 shro 8,g1,g1 # shift mask for next byte 205#else 206 shlo 8,g1,g1 # shift mask for next byte 207#endif 208 subi 1,g2,g2 # decrement character counter 209 bne.t Lcloop # branch if null not reached 210 211 /* words are equal up thru null byte */ 212 213Lequal_exit: 214 mov 0,g14 # conform to register conventions 215 lda 0,g0 # return zero, indicating equality 216 bx (g13) # return 217 218Lrett: 219 ret 220 221.diff: 222 mov 0,g14 223 bl Lless_than_exit 224Lgreater_than_exit: 225 cmpibge.f 0,g2,Lequal_exit # branch if difference is beyond max_bytes 226 mov 1,g0 227 bx (g13) # g0 = 1 (src1 > src2) 228Lless_than_exit: 229 cmpibge.f 0,g2,Lequal_exit # branch if difference is beyond max_bytes 230 subi 1,0,g0 231 bx (g13) # g0 = -1 (src1 < src2) 232 233Lsrc2_unaligned: 234 notor g1,3,g14 # first step in computing new src1 ptr 235 ld 4(g3),SRC1 # fetch second word of src2 236 shlo 3,g1,MSW # compute shift count for src2 237#if __i960_BIG_ENDIAN__ 238 subo MSW,0,MSW # adjust shift count for big endian 239#endif 240 eshro MSW,g6,SRC2 # extract word of src2 241 cmpo LSW,SRC2 # compare src1 and src2 words 242 lda 4(g3),g1 # set new src2 ptr 243 bne.f Lcloop_setup # first four bytes differ 244 scanbyte 0,LSW # check for null byte 245 subo g14,g0,g0 # second (final) step in computing new src1 ptr 246 addi g14,g2,g2 # compute new max_bytes too 247 lda (g13),g14 # prepare return pointer for Lrestart 248 bno.t Lrestart # if null byte not encountered, continue 249 /* with both string fetches shifted such that*/ 250 /* src2 is now word aligned.*/ 251 mov 0,g14 # conform to register conventions. 252 lda 0,g0 # return indicator of equality. 253 bx (g13) 254