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