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 "strncpy.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 procedure strncpy (optimized assembler version for the 80960K Series) 43 44 dest_addr = strncpy (dest_addr, src_addr, max_bytes) 45 46 copy the null terminated string pointed to by src_addr to the 47 string pointed to by dest_addr. Return the original dest_addr. 48 If the source string is shorter than max_bytes, then null-pad 49 the destination string. If it is longer than max_bytes, the 50 copy stops at max_bytes bytes (and no terminating null appears 51 in the destination string). 52 53 This routine will fail if the source and destination string 54 overlap (in particular, if the end of the source is overlapped 55 by the beginning of the destination). The behavior is undefined. 56 This is acceptable according to the draft C standard. 57 58 Undefined behavior will also occur if the end of the source string 59 (i.e. the terminating null byte) is in the last two words of the 60 program's allocated memory space. This is so because strncpy fetches 61 ahead. Disallowing the fetch ahead would impose a severe performance 62 penalty. 63 64 Strategy: 65 66 Fetch and store the strings by words and go to a character move loop 67 as soon as a null byte is encountered. If max_bytes is exhausted 68 first, then terminate after moving only max_bytes (with the last 69 0, 1, 2, or 3 bytes moved as single bytes, not as a word). 70 Otherwise, the character move loop moves the last bytes or the 71 source string, and then null-pads the destination string until 72 max_bytes is exhausted. 73 74 Tactics: 75 76 1) Do NOT try to fetch the words in a word aligned manner because, 77 in my judgement, the performance degradation experienced due to 78 non-aligned accesses does NOT outweigh the time and complexity added 79 by the preamble and convoluted body that would be necessary to assure 80 alignment. 81 82 2) When the null byte is encountered in a source word, null out the 83 higher-numbered bytes in that word, store the word in the destination, 84 and go to the word null-padder, which may eventually go to the byte 85 null-padder. 86*/ 87 88 .globl _strncpy 89 .globl __strncpy 90 .leafproc _strncpy,__strncpy 91 .align 2 92_strncpy: 93#ifndef __PIC 94 lda Lrett,g14 95#else 96 lda Lrett-(.+8)(ip),g14 97#endif 98__strncpy: 99 mov g14, g13 100 cmpibge 0,g2,Lexit # quit early if max_bytes <= 0 101 ld (g1), g7 # fetch the first word of the source 102 mov g0, g5 103 lda 0xff, g3 # byte extraction mask 104 addo g1, g2, g6 105 addo g2, g5, g2 106Lwloop: # word copying loop 107 addo 4, g1, g1 # post-increment source ptr 108 cmpo g6, g1 # max_bytes < 4 ? 109 mov g7, g4 # keep a copy of source word 110 bl Lcloop.a # if less than four bytes to go, go to char loop 111 scanbyte 0, g4 # null byte found? 112 ld (g1), g7 # pre-fetch next word of the source 113 be Lcloop.c # go to char loop if null encountered 114 st g4, (g5) # store current word 115 addo 4, g5, g5 # post-increment destination ptr 116 b Lwloop 117 118Lcloop.a: # character copying loop (max_bytes < 3) 119 and g3, g4, g14 # extract byte 120Lcloop.b: 121 cmpo g2, g5 # max_bytes <= 0 ? 122 shro 8, g4, g4 # position word to extract next byte 123 be Lexit # exit if max_bytes exhausted 124 cmpo 0, g14 # is it null? 125 stob g14, (g5) # store it 126 addo 1, g5, g5 # post-increment dest ptr 127 bne Lcloop.a # branch if we are NOT null padding 128 b Lcloop.b # branch if we are null padding 129 130Lexit: 131 mov 0, g14 132 bx (g13) # g0 = dest string address; g14 = 0 133Lrett: 134 ret 135 136Lcloop.c: # character copying loop 137 and g3, g4, g14 # extract byte 138 cmpo 0, g14 # is it null? 139 mov g3, g7 # save mask 140 shlo 8, g3, g3 # shift mask to next byte position 141 bne Lcloop.c # loop until null found 142 subo 1, g7, g3 # mask to null pad after null byte 143 and g3, g4, g4 # null-out stuff after null byte 144 st g4, (g5) # store last part of src and first of null-pad 145 subo 8,g2,g6 # adjust max_byte counter 146 147Lzwloop: 148 cmpo g5, g6 # max_bytes < 4 ? 149 addo 4, g5, g5 150 bg Lcloop.b # if so, goto character loop 151 st g14, (g5) # store four null bytes 152 b Lzwloop 153 154/* end of strncpy */ 155