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 "strcp_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 strcpy (optimized assembler version for the CA) 44 45 dest_addr = strcpy (dest_addr, src_addr) 46 47 copy the null terminated string pointed to by src_addr to 48 the string space pointed to by dest_addr. Return the original 49 dest_addr. 50 51 This routine will fail if the source and destination string 52 overlap (in particular, if the end of the source is overlapped 53 by the beginning of the destination). The behavior is undefined. 54 This is acceptable according to the draft C standard. 55 56 Undefined behavior will also occur if the end of the source string 57 (i.e. the terminating null byte) is in the last word of the program's 58 allocated memory space. This is so because, in several cases, strcpy 59 will fetch ahead one word. Disallowing the fetch ahead would impose 60 a severe performance penalty. 61 62 This program handles five cases: 63 64 1) both arguments start on a word boundary 65 2) neither are word aligned, but they are offset by the same amount 66 3) source is word aligned, destination is not 67 4) destination is word aligned, source is not 68 5) neither is word aligned, and they are offset by differing amounts 69 70 At the time of this writing, only g0 thru g7 and g13 are available 71 for use in this leafproc; other registers would have to be saved and 72 restored. These nine registers, plus tricky use of g14 are sufficient 73 to implement the routine. The registers are used as follows: 74 75 g0 original dest ptr; not modified, so that it may be returned. 76 g1 src ptr; shift count 77 g2 dest ptr; 4 bytes of src 78 g3 src ptr (word aligned) 79 g4 dest ptr (word aligned) 80 g5 0xff -- byte extraction mask 81 g6 lsw of double word for extraction of 4 bytes (little endian) 82 msw of double word for extraction of 4 bytes (big endian) 83 g7 msw of double word for extraction of 4 bytes (little endian) 84 lsw of double word for extraction of 4 bytes (big endian) 85 g13 return address 86 g14 byte extracted. When reaches null byte, which is zero, we will 87 be in conformance with register conventions, and can return to 88 the caller with a clear conscience. 89 90 procedure strcat 91 92 dest_addr = strcat (dest_addr, src_addr) 93 94 Appends the string pointed to by src_addr to the string pointed 95 to by dest_addr. The first character of the source string is 96 copied to the location initially occupied by the trailing null 97 byte of the destination string. Thereafter, characters are copied 98 from the source to the destination up thru the null byte that 99 trails the source string. 100*/ 101 102#if __i960_BIG_ENDIAN__ 103#define MSW g6 104#define LSW g7 105#else 106#define LSW g6 107#define MSW g7 108#endif 109 110 .globl _strcpy, _strcat 111 .globl __strcpy, __strcat 112 .leafproc _strcpy, __strcpy 113 .leafproc _strcat, __strcat 114 .align 2 115_strcat: 116#ifndef __PIC 117 lda Lrett,g14 118#else 119 lda Lrett-(.+8)(ip),g14 120#endif 121__strcat: 122 notand g0,3,g4 # extract word addr of start of dest 123 lda (g14),g13 # preserve return address 124 and g0,3,LSW # extract byte offset of dest 125 ld (g4),MSW # fetch word containing at least first byte 126 shlo 3,LSW,g14 # get shift count for making mask for first word 127 subi 1,0,LSW # mask initially all ones 128#if __i960_BIG_ENDIAN__ 129 shro g14,LSW,LSW # get mask for bytes needed from first word 130 lda 0xff000000,g5 # byte extraction mask 131#else 132 shlo g14,LSW,LSW # get mask for bytes needed from first word 133 lda 0xff,g5 # byte extraction mask 134#endif 135 notor MSW,LSW,MSW # set unneeded bytes to all ones 136Lsearch_for_word_with_null: 137 scanbyte 0,MSW # check for null byte 138 lda 4(g4),g4 # post-increment dest word pointer 139 mov MSW,LSW # keep a copy of current word 140 ld (g4),MSW # fetch next word of dest 141 bno.t Lsearch_for_word_with_null # branch if null not found yet 142 and g5,LSW,g14 # extract byte 143 cmpo 0,g14 # branch if null is first byte of word 144 subo 4,g4,g4 # move dest word ptr back to word with null 145 notand g1,3,g3 # extract word addr of start of src 146 lda (g4),g2 # set dest byte ptr to 1st byte of word w/ null 147 be.f Lcase_14 148Lsearch_for_null: 149#if __i960_BIG_ENDIAN__ 150 shro 8,g5,g5 # move mask down to next byte 151#else 152 shlo 8,g5,g5 # move mask up to next byte 153#endif 154 lda 1(g2),g2 # move dest byte ptr to next byte 155 and g5,LSW,g14 # extract byte 156 cmpobne.t 0,g14,Lsearch_for_null # branch if null is not yet found 157 lda 0xff,g5 # byte extraction mask 158 b Lcase_235.a 159 160 161_strcpy: 162#ifndef __PIC 163 lda Lrett,g14 164#else 165 lda Lrett-(.+8)(ip),g14 166#endif 167__strcpy: 168 notand g0,3,g4 # extract word addr of start of dest 169 lda (g14),g13 # preserve return address 170 cmpo g0,g4 # check alignment of dest 171 lda 0xff,g5 # load mask for byte extraction 172 notand g1,3,g3 # extract word addr of start of src 173 bne.f Lcase_235 # branch if dest is NOT word aligned 174 175Lcase_14: 176 cmpo g3,g1 # check alignment of src 177 ld (g3),LSW # fetch word containing at least first byte 178 shlo 3,g1,g1 # compute shift count 179 lda 4(g3),g3 # advance src word addr 180#if __i960_BIG_ENDIAN__ 181 lda 0xff,g5 # byte extraction mask 182#endif 183 bne.f Lcase_4 # branch if src is NOT word aligned 184 185Lcase_1: # src and dest are word aligned 186 subo 4,g4,g4 # store is pre-incrementing; back up dest addr 187Lcase_1_wloop: # word copying loop 188 scanbyte 0,LSW # check for null byte in src word 189 lda (LSW),g2 # keep a copy of the src word 190 addo 4,g4,g4 # pre-increment dest addr 191 ld (g3),LSW # pre-fetch next word of src 192 addo 4,g3,g3 # post-increment src addr 193 bo.f Lcase_1_cloop # branch if word contains null byte 194 st g2,(g4) # store word in dest string 195 b Lcase_1_wloop 196 197Lcase_3_cloop: 198Lcase_1_cloop: # character copying loop 199#if __i960_BIG_ENDIAN__ 200 rotate 8,g2,g2 # move next byte into position for extraction 201 and g5,g2,g14 # extract next char 202#else 203 and g5,g2,g14 # extract next char 204 shro 8,g2,g2 # move next byte into position for extraction 205#endif 206 cmpo 0,g14 # check for null byte 207 stob g14,(g4) # store the byte in dest 208 lda 1(g4),g4 # post-increment dest byte addr 209 bne.t Lcase_1_cloop # branch if null not reached 210 211Lexit_code: 212 bx (g13) # g0 = addr of dest; g14 = 0 213Lrett: 214 ret 215 216Lcase_3: # src is word aligned; dest is not 217 addo 4,g4,g4 # move dest word ptr to first word boundary 218 mov LSW,MSW # make copy of first word of src 219 lda 0,g1 # initialize shift count to zero 220 221Lcase_25: 222Lcase_3_cloop_at_start: # character copying loop for start of dest str 223#if __i960_BIG_ENDIAN__ 224 rotate 8,MSW,MSW # move next byte into position for extraction 225 and g5,MSW,g14 # extract next char 226#else 227 and g5,MSW,g14 # extract next char 228 shro 8,MSW,MSW # move next byte into position for extraction 229#endif 230 cmpo 0,g14 # check for null byte 231 stob g14,(g2) # store the byte in dest 232 lda 1(g2),g2 # post-increment dest ptr 233 be.f Lexit_code # branch if null byte reached 234 cmpo g2,g4 # have we reached word boundary in dest? 235 lda 8(g1),g1 # augment the shift counter 236 bne.t Lcase_3_cloop_at_start 237 238Lcase_4: 239 ld (g3),MSW # fetch msw of operand for double shift 240#if __i960_BIG_ENDIAN__ 241 subo g1,0,g1 # Adjust shift count for big endian. 242#endif 243 244Lcase_3_wloop: 245 eshro g1,g6,g2 # extract 4 bytes of src 246 lda 4(g3),g3 # post-increment src word addr 247 scanbyte 0,g2 # check for null byte 248 lda (MSW),LSW # move msw to lsw 249 ld (g3),MSW # pre-fetch msw of operand for double shift 250 bo.f Lcase_3_cloop # branch if word contains null byte 251 st g2,(g4) # store 4 bytes to dest 252 addo 4,g4,g4 # post-increment dest ptr 253 b Lcase_3_wloop 254 255Lcase_235: 256 lda (g0),g2 # copy dest ptr 257Lcase_235.a: 258 cmpo g3,g1 # check alignment of src 259 ld (g3),LSW # fetch word containing at least first byte 260 and 3,g1,g14 # compute shift count 261 lda 4(g3),g3 # advance src word addr 262 shlo 3,g14,g1 263 be.t Lcase_3 # branch if dest is word aligned 264 or g4,g14,g14 # is src earlier in word, later, or sync w/ dst 265 ld (g3),MSW # pre-fetch second half 266 cmpo g2,g14 # < indicates first word of dest has more bytes 267 lda 4(g4),g4 # move dest word addr to first word boundary 268 /* than first word of source. */ 269#if __i960_BIG_ENDIAN__ 270 subo g1,0,g14 # Adjust shift count for big endian. 271 eshro g14,g6,g14 # extract four bytes 272 bge.f 1f 273#else 274 eshro g1,g6,g14 # extract four bytes 275 bg.f 1f 276#endif 277 mov MSW,LSW 278 lda 4(g3),g3 # move src word addr to second word boundary 2791: 280 mov g14,MSW 281 b Lcase_25 282 283/* end of strcpy */ 284 285