1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright (c) 1989-1995,1998 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27.ident "%Z%%M% %I% %E% SMI" /* SunOS 4.1 1.2 */ 28 29 .file "%M%" 30 31/* 32 * memcmp(s1, s2, len) 33 * 34 * Compare n bytes: s1>s2: >0 s1==s2: 0 s1<s2: <0 35 * 36 * Fast assembler language version of the following C-program for memcmp 37 * which represents the `standard' for the C-library. 38 * 39 * int 40 * memcmp(const void *s1, const void *s2, size_t n) 41 * { 42 * if (s1 != s2 && n != 0) { 43 * const char *ps1 = s1; 44 * const char *ps2 = s2; 45 * do { 46 * if (*ps1++ != *ps2++) 47 * return (ps1[-1] - ps2[-1]); 48 * } while (--n != 0); 49 * } 50 * return (NULL); 51 * } 52 */ 53 54#include <sys/asm_linkage.h> 55 56 ANSI_PRAGMA_WEAK(memcmp,function) 57 58#include "synonyms.h" 59 60 ENTRY(memcmp) 61 st %g2, [%sp + 68] ! g2 must be restored before retl 62 cmp %o0, %o1 ! s1 == s2? 63 be .cmpeq 64 cmp %o2, 17 65 bleu,a .cmpbyt ! for small counts go do bytes 66 sub %o1, %o0, %o1 67 68 andcc %o0, 3, %o3 ! is s1 aligned? 69 bz,a .iss2 ! if so go check s2 70 andcc %o1, 3, %o4 ! is s2 aligned? 71 cmp %o3, 2 72 be .algn2 73 cmp %o3, 3 74 75.algn1: ldub [%o0], %o4 ! cmp one byte 76 inc %o0 77 ldub [%o1], %o5 78 inc %o1 79 dec %o2 80 be .algn3 81 cmp %o4, %o5 82 be .algn2 83 nop 84 b,a .noteq 85 86.algn2: lduh [%o0], %o4 87 inc 2, %o0 88 ldub [%o1], %o5 89 inc 1, %o1 90 srl %o4, 8, %o3 91 cmp %o3, %o5 92 be,a 1f 93 ldub [%o1], %o5 ! delay slot, get next byte from s2 94 b .noteq 95 mov %o3, %o4 ! delay slot, move *s1 to %o4 961: inc %o1 97 dec 2, %o2 98 and %o4, 0xff, %o4 99 cmp %o4, %o5 100.algn3: be,a .iss2 101 andcc %o1, 3, %o4 ! delay slot, is s2 aligned? 102 b,a .noteq 103 104.cmpbyt:b .bytcmp 105 deccc %o2 1061: ldub [%o0 + %o1], %o5 ! byte compare loop 107 inc %o0 108 cmp %o4, %o5 109 be,a .bytcmp 110 deccc %o2 ! delay slot, compare count (len) 111 b,a .noteq 112.bytcmp:bgeu,a 1b 113 ldub [%o0], %o4 114.cmpeq: ld [%sp + 68], %g2 115 retl ! strings compare equal 116 clr %o0 117 118.noteq_word: ! words aren't equal. find unequal byte 119 srl %o4, 24, %o1 ! first byte 120 srl %o5, 24, %o2 121 cmp %o1, %o2 122 bne 1f 123 sll %o4, 8, %o4 124 sll %o5, 8, %o5 125 srl %o4, 24, %o1 126 srl %o5, 24, %o2 127 cmp %o1, %o2 128 bne 1f 129 sll %o4, 8, %o4 130 sll %o5, 8, %o5 131 srl %o4, 24, %o1 132 srl %o5, 24, %o2 133 cmp %o1, %o2 134 bne 1f 135 sll %o4, 8, %o4 136 sll %o5, 8, %o5 137 srl %o4, 24, %o1 138 srl %o5, 24, %o2 1391: 140 ld [%sp + 68], %g2 141 retl 142 sub %o1, %o2, %o0 ! delay slot 143 144.noteq: 145 ld [%sp + 68], %g2 146 retl ! strings aren't equal 147 sub %o4, %o5, %o0 ! delay slot, return(*s1 - *s2) 148 149.iss2: andn %o2, 3, %o3 ! count of aligned bytes 150 and %o2, 3, %o2 ! remaining bytes 151 bz .w4cmp ! if s2 word aligned, compare words 152 cmp %o4, 2 153 be .w2cmp ! s2 half aligned 154 cmp %o4, 1 155 156.w3cmp: 157 dec 4, %o3 ! avoid reading beyond the last byte 158 inc 4, %o2 159 ldub [%o1], %g1 ! read a byte to align for word reads 160 inc 1, %o1 161 be .w1cmp ! aligned to 1 or 3 bytes 162 sll %g1, 24, %o5 163 164 sub %o1, %o0, %o1 1652: ld [%o0 + %o1], %g1 166 ld [%o0], %o4 167 inc 4, %o0 168 srl %g1, 8, %g2 ! merge with the other half 169 or %g2, %o5, %o5 170 cmp %o4, %o5 171 bne .noteq_word 172 deccc 4, %o3 173 bnz 2b 174 sll %g1, 24, %o5 175 sub %o1, 1, %o1 ! used 3 bytes of the last word read 176 b .bytcmp 177 deccc %o2 178 179.w1cmp: 180 dec 4, %o3 ! avoid reading beyond the last byte 181 inc 4, %o2 182 lduh [%o1], %g1 ! read 3 bytes to word align 183 inc 2, %o1 184 sll %g1, 8, %g2 185 or %o5, %g2, %o5 186 187 sub %o1, %o0, %o1 1883: ld [%o0 + %o1], %g1 189 ld [%o0], %o4 190 inc 4, %o0 191 srl %g1, 24, %g2 ! merge with the other half 192 or %g2, %o5, %o5 193 cmp %o4, %o5 194 bne .noteq_word 195 deccc 4, %o3 196 bnz 3b 197 sll %g1, 8, %o5 198 sub %o1, 3, %o1 ! used 1 byte of the last word read 199 b .bytcmp 200 deccc %o2 201 202.w2cmp: 203 dec 4, %o3 ! avoid reading beyond the last byte 204 inc 4, %o2 205 lduh [%o1], %g1 ! read a halfword to align s2 206 inc 2, %o1 207 sll %g1, 16, %o5 208 209 sub %o1, %o0, %o1 2104: ld [%o0 + %o1], %g1 ! read a word from s2 211 ld [%o0], %o4 ! read a word from s1 212 inc 4, %o0 213 srl %g1, 16, %g2 ! merge with the other half 214 or %g2, %o5, %o5 215 cmp %o4, %o5 216 bne .noteq_word 217 deccc 4, %o3 218 bnz 4b 219 sll %g1, 16, %o5 220 sub %o1, 2, %o1 ! only used half of the last read word 221 b .bytcmp 222 deccc %o2 223 224.w4cmp: 225 sub %o1, %o0, %o1 226 ld [%o0 + %o1], %o5 2275: ld [%o0], %o4 228 inc 4, %o0 229 cmp %o4, %o5 230 bne .noteq_word 231 deccc 4, %o3 232 bnz,a 5b 233 ld [%o0 + %o1], %o5 234 b .bytcmp ! compare remaining bytes, if any 235 deccc %o2 236 237 SET_SIZE(memcmp) 238