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 "strle_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 strlen (optimized assembler version for the CA) 46 47 src_addr = strlen (src_addr) 48 49 return the number of bytes that precede the null byte in the 50 string pointed to by src_addr. 51 52 Undefined behavior will occur if the end of the source string (i.e. 53 the terminating null byte) is in the last four words of the program's 54 allocated memory space. This is so because, in several cases, strlen 55 will fetch ahead several words. Disallowing the fetch ahead would 56 impose a severe performance penalty. 57 58 This program handles two cases: 59 60 1) the argument starts on a word boundary 61 2) the argument doesn't start on a word boundary 62 63 At the time of this writing, only g0 thru g7 and g13 are available 64 for use in this leafproc; other registers would have to be saved and 65 restored. These nine registers, plus tricky use of g14 are sufficient 66 to implement the routine. The registers are used as follows: 67 68 g0 original src ptr; upon return it is the byte count. 69 g1 70 g2 src ptr 71 g3 mask 72 g4 even word of the source string 73 g5 odd word of the source string 74 g6 copy of even word, shift count 75 g7 copy of odd word 76 g13 return address 77 g14 byte extracted. 78*/ 79 80 .globl _strlen 81 .globl __strlen 82 .leafproc _strlen, __strlen 83 .align 2 84_strlen: 85#ifndef __PIC 86 lda Lrett,g14 87#else 88 lda Lrett-(.+8)(ip),g14 89#endif 90__strlen: 91 92 notand g0,3,g2 # extract word addr of start of src 93 lda (g14),g13 # preserve return address 94 and g0,3,g7 # extract byte offset of src 95 ld (g2),g5 # fetch word containing at least first byte 96 shlo 3,g7,g7 # get shift count for making mask for first word 97 lda 4(g2),g2 # post-increment src word pointer 98 subi 1,0,g3 # mask initially all ones 99 chkbit 2,g2 # are we on an even word boundary or an odd one? 100#if __i960_BIG_ENDIAN__ 101 shro g7,g3,g3 # get mask for bytes needed from first word 102 notor g5,g3,g7 # set unneeded bytes to all ones 103 lda 0xff000000,g3 # byte extraction mask 104#else 105 shlo g7,g3,g3 # get mask for bytes needed from first word 106 notor g5,g3,g7 # set unneeded bytes to all ones 107 lda 0xff,g3 # byte extraction mask 108#endif 109 bno.f Lodd_word # branch if first word is odd 110 mov g7,g4 # move first word to copy thereof 111 ld (g2),g5 # load odd word 112 lda 4(g2),g2 # post-increment src word pointer 113 114 115Leven_word: 116 scanbyte 0,g4 # check for null byte 117 movl g4,g6 # copy both words 118Lodd_word: # trickery! if we branch here, following branch 119 /* instruction will fall thru, as we want, */ 120 /* effecting the load of g4 and g5 only. */ 121 ldl (g2),g4 # fetch next pair of word of src 122 bo.f Lsearch_for_null # branch if null found 123 scanbyte 0,g7 # check for null byte 124 lda 8(g2),g2 # post-increment src word pointer 125 bno.t Leven_word # branch if null not found yet 126 127 subo 4,g2,g2 # back up the byte pointer 128 lda (g7),g6 # move odd word to search word 129Lsearch_for_null: 130 subo 9,g2,g2 # back up the byte pointer 131Lsearch_for_null.a: 132 and g6,g3,g14 # extract byte 133 cmpo 0,g14 # is it null? 134 lda 1(g2),g2 # bump src byte ptr 135#if __i960_BIG_ENDIAN__ 136 shlo 8,g6,g6 # shift word to position next byte 137#else 138 shro 8,g6,g6 # shift word to position next byte 139#endif 140 bne.t Lsearch_for_null.a 141 142Lexit_code: 143 subo g0,g2,g0 # calculate string length 144 bx (g13) # g0 = addr of src; g14 = 0 145Lrett: 146 ret 147 148/* end of strlen */ 149