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 "memchr.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 memchr (optimized assembler version for the 80960K series) 46 47 src_addr = memchr (src_addr, char, max_bytes) 48 49 searching from src_addr for a span of max_bytes bytes, return a 50 pointer to the first byte in the source array that contains the 51 indicated char. Return null if the char is not found. 52 53 Undefined behavior will occur if the last byte of the source array 54 is in the last two words of the program's allocated memory space. 55 This is so because memchr fetches ahead. Disallowing the fetch 56 ahead would impose a severe performance penalty. 57 58 Strategy: 59 60 Fetch the source array by words and scanbyte the words for the 61 char until either a word with the byte is found or max_bytes is 62 exhausted. In the former case, move through the word to find the 63 matching byte and return its memory address. In the latter case, 64 return zero (null). 65 66 Tactics: 67 68 1) Do NOT try to fetch the words in a word aligned manner because, 69 in my judgement, the performance degradation experienced due to 70 non-aligned accesses does NOT outweigh the time and complexity added 71 by the preamble that would be necessary to assure alignment. This 72 is supported by the intuition that most source arrays (even more 73 true of most big source arrays) will be word aligned to begin with. 74 75 2) Rather than decrementing max_bytes to zero, I calculate the 76 address of the byte after the last byte of the source array, and 77 quit when the source byte pointer passes that. Refining, actually 78 I calculate the address of the fifth byte after the last byte of 79 the source array, because the source byte pointer is ahead of the 80 actual examination point due to fetch ahead. 81*/ 82 83 .globl _memchr 84 .globl __memchr 85 .leafproc _memchr, __memchr 86 .align 2 87_memchr: 88#ifndef __PIC 89 lda Lrett,g14 90#else 91 lda Lrett-(.+8)(ip),g14 92#endif 93__memchr: 94 95 mov g14,g13 # preserve return address 96 lda 0xff,g7 # byte extraction mask 97 and g1,g7,g1 # make char an 8-bit ordinal 98 mov 0,g14 # conform to register linkage standard 99 cmpibge 0,g2,Lnot_found # do nothing if max_bytes <= 0 100 addo 4,g0,g6 # post-increment src word pointer 101 addo g2,g6,g2 # compute ending address from start and len 102 ld (g0),g4 # fetch first word 103 shlo 8,g1,g3 # broadcast the char to four bytes 104 or g1,g3,g3 105 shlo 16,g3,g5 106 or g3,g5,g3 107 108Lsearch_for_word_with_char: 109 mov g4,g5 # keep a copy of word 110 scanbyte g3,g5 # check for byte with char 111 ld (g6),g4 # fetch next word of src 112 bo Lsearch_for_char # branch if null found 113 addo 4,g6,g6 # post-increment src word pointer 114 cmpobge g2,g6,Lsearch_for_word_with_char # branch if max_bytes > 3 115 116Lnot_found: 117 mov 0,g0 # char not found. Return null 118 bx (g13) # g0 = addr of char in src (or null); g14 = 0 119Lrett: 120 ret 121 122Lsearch_for_char: 123 cmpobe.f g6,g2,Lnot_found # quit if max_bytes exhausted 124 and g5,g7,g0 # extract byte 125 cmpo g1,g0 # is it char? 126 addo 1,g6,g6 # bump src byte ptr 127 shro 8,g5,g5 # shift word to position next byte 128 bne.t Lsearch_for_char 129 subo 5,g6,g0 # back up the byte pointer 130 bx (g13) 131 132/* end of memchr */ 133