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#include <picolibc.h> 32 33 .file "sncmp_ca.s" 34#ifdef __PIC 35 .pic 36#endif 37#ifdef __PID 38 .pid 39#endif 40/* 41 * (c) copyright 1988,1993 Intel Corp., all rights reserved 42 */ 43 44/* 45 procedure strncmp (optimized assembler version for the CA) 46 47 result = strncmp (src1_addr, src2_addr, max_bytes) 48 49 compare the null terminated string pointed to by src1_addr to 50 the string space pointed to by src2_addr. Return 0 iff the strings 51 are equal, -1 if src1_addr is lexicly less than src2_addr, and 1 52 if it is lexicly greater. Do not compare more than max_bytes bytes. 53 54 Undefined behavior will occur if the end of either source string 55 (i.e. the terminating null byte) is in the last word of the program's 56 allocated memory space. This is so because, in several cases, strncmp 57 will fetch ahead one word. Disallowing the fetch ahead would impose 58 a severe performance penalty. 59 60 This program handles five cases: 61 62 1) both arguments start on a word boundary 63 2) neither are word aligned, but they are offset by the same amount 64 3) source1 is word aligned, source2 is not 65 4) source2 is word aligned, source1 is not 66 5) neither is word aligned, and they are offset by differing amounts 67 68 At the time of this writing, only g0 thru g7 and g14 are available 69 for use in this leafproc; other registers would have to be saved and 70 restored. These nine registers are sufficient to implement the routine. 71 The registers are used as follows: 72 73 g0 original src1 ptr; extracted word; return result 74 g1 src2 ptr; 0xff -- byte extraction mask 75 g2 maximum number of bytes to compare 76 g3 src2 word ptr 77 Little endian: 78 g4 lsw of src1 79 g5 msw of src1 80 g6 src2 word 81 g7 src1 word ptr 82 Big endian: 83 g4 msw of src1 84 g5 lsw of src1 85 g6 src1 word ptr 86 g7 src2 word 87 g13 return address 88 g14 shift count 89*/ 90 91#if __i960_BIG_ENDIAN__ 92#define MSW g4 93#define LSW g5 94#define SRC1 g6 95#define SRC2 g7 96#else 97#define LSW g4 98#define MSW g5 99#define SRC2 g6 100#define SRC1 g7 101#endif 102 103 .globl _strncmp 104 .globl __strncmp 105 .leafproc _strncmp, __strncmp 106 .align 2 107_strncmp: 108#ifndef __PIC 109 lda Lrett,g14 110#else 111 lda Lrett-(.+8)(ip),g14 112#endif 113__strncmp: 114Lrestart: 115 notand g0,3,SRC1 # extract word addr of start of src1 116 lda (g14),g13 # preserve return address 117 cmpibge.f 0,g2,Lequal_exit # return equality if number of bytes to 118 /* compare is none. */ 119#if __i960_BIG_ENDIAN__ 120 cmpo g0,SRC1 # check alignment of src1 121#endif 122 ld (SRC1),LSW # fetch word with at least first byte of src1 123 notand g1,3,g3 # extract word addr of start of src2 124 ld 4(SRC1),MSW # fetch second word of src1 125#if __i960_BIG_ENDIAN__ 126 bne Lsrc1_unaligned # branch if src1 is unaligned 127 cmpo g3,g1 # check alignment of src2 128 ld (g3),SRC2 # fetch word with at least first byte of src2 129 shlo 3,g0,g14 # compute shift count for src1 130 subo g14,0,g14 # adjust shift count for big endian 131 lda 8(SRC1),SRC1 # advance src1 word addr 132 bne.f Lsrc2_unaligned # branch if src2 is NOT word aligned 133 134 /* src2 is word aligned */ 135 136 mov LSW,g0 137 138Lwloop2: # word comparing loop 139 cmpo SRC2,g0 # compare src1 and src2 words 140 lda 0xff000000,g1 # byte extraction mask 141 mov MSW,LSW # move msw of src1 to lsw 142 ld (SRC1),MSW # pre-fetch next msw of src1 143 addo 4,SRC1,SRC1 # post-increment src1 addr 144 lda 4(g3),g3 # pre-increment src2 addr 145 bne.f Lcloop # branch if src1 and src2 unequal 146 scanbyte 0,g0 # check for null byte in src1 word 147 ld (g3),SRC2 # pre-fetch next word of src2 148 mov LSW,g0 # extract word of src1 149 subi 4,g2,g2 # decrement maximum byte count 150 bo.f Lequal_exit # branch if null byte encountered 151 cmpibl.t 0,g2,Lwloop2 # branch if max_bytes not reached yet 152 153 b Lequal_exit # strings were equal up through max_bytes 154 155Lsrc1_unaligned: 156#endif 157 cmpo g3,g1 # check alignment of src2 158 ld (g3),SRC2 # fetch word with at least first byte of src2 159 shlo 3,g0,g14 # compute shift count for src1 160#if __i960_BIG_ENDIAN__ 161 subo g14,0,g14 # adjust shift count for big endian 162#endif 163 eshro g14,g4,LSW # extract word of src1 164 lda 8(SRC1),SRC1 # advance src1 word addr 165 bne.f Lsrc2_unaligned # branch if src2 is NOT word aligned 166 167 /* at least src2 is word aligned */ 168 169 mov LSW,g0 170 171Lwloop: # word comparing loop 172 cmpo SRC2,g0 # compare src1 and src2 words 173#if __i960_BIG_ENDIAN__ 174 lda 0xff000000,g1 # byte extraction mask 175#else 176 lda 0xff,g1 # byte extraction mask 177#endif 178 mov MSW,LSW # move msw of src1 to lsw 179 ld (SRC1),MSW # pre-fetch next msw of src1 180 addo 4,SRC1,SRC1 # post-increment src1 addr 181 lda 4(g3),g3 # pre-increment src2 addr 182 bne.f Lcloop # branch if src1 and src2 unequal 183 scanbyte 0,g0 # check for null byte in src1 word 184 ld (g3),SRC2 # pre-fetch next word of src2 185 eshro g14,g4,g0 # extract word of src1 186 subi 4,g2,g2 # decrement maximum byte count 187 bo.f Lequal_exit # branch if null byte encountered 188 cmpibl.t 0,g2,Lwloop # branch if max_bytes not reached yet 189 190 b Lequal_exit # strings were equal up through max_bytes 191 192Lcloop_setup: # setup for coming from Lsrc2_unaligned 193 mov LSW,g0 # restore extracted src1 word 194#if __i960_BIG_ENDIAN__ 195 lda 0xff000000,g1 # byte extraction mask 196#else 197 lda 0xff,g1 # byte extraction mask 198#endif 199 200Lcloop: # character comparing loop 201 and SRC2,g1,g3 # extract next char of src2 202 and g0,g1,LSW # extract next char of src1 203 cmpobne.f LSW,g3,.diff # check for equality 204 cmpo 0,LSW # check for null byte 205#if __i960_BIG_ENDIAN__ 206 shro 8,g1,g1 # shift mask for next byte 207#else 208 shlo 8,g1,g1 # shift mask for next byte 209#endif 210 subi 1,g2,g2 # decrement character counter 211 bne.t Lcloop # branch if null not reached 212 213 /* words are equal up thru null byte */ 214 215Lequal_exit: 216 mov 0,g14 # conform to register conventions 217 lda 0,g0 # return zero, indicating equality 218 bx (g13) # return 219 220Lrett: 221 ret 222 223.diff: 224 mov 0,g14 225 bl Lless_than_exit 226Lgreater_than_exit: 227 cmpibge.f 0,g2,Lequal_exit # branch if difference is beyond max_bytes 228 mov 1,g0 229 bx (g13) # g0 = 1 (src1 > src2) 230Lless_than_exit: 231 cmpibge.f 0,g2,Lequal_exit # branch if difference is beyond max_bytes 232 subi 1,0,g0 233 bx (g13) # g0 = -1 (src1 < src2) 234 235Lsrc2_unaligned: 236 notor g1,3,g14 # first step in computing new src1 ptr 237 ld 4(g3),SRC1 # fetch second word of src2 238 shlo 3,g1,MSW # compute shift count for src2 239#if __i960_BIG_ENDIAN__ 240 subo MSW,0,MSW # adjust shift count for big endian 241#endif 242 eshro MSW,g6,SRC2 # extract word of src2 243 cmpo LSW,SRC2 # compare src1 and src2 words 244 lda 4(g3),g1 # set new src2 ptr 245 bne.f Lcloop_setup # first four bytes differ 246 scanbyte 0,LSW # check for null byte 247 subo g14,g0,g0 # second (final) step in computing new src1 ptr 248 addi g14,g2,g2 # compute new max_bytes too 249 lda (g13),g14 # prepare return pointer for Lrestart 250 bno.t Lrestart # if null byte not encountered, continue 251 /* with both string fetches shifted such that*/ 252 /* src2 is now word aligned.*/ 253 mov 0,g14 # conform to register conventions. 254 lda 0,g0 # return indicator of equality. 255 bx (g13) 256