10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 56812Sraf * Common Development and Distribution License (the "License"). 66812Sraf * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 216812Sraf 220Sstevel@tonic-gate/* 236812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 246812Sraf * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 27*7298SMark.J.Nelson@Sun.COM .file "strncmp.s" 280Sstevel@tonic-gate 290Sstevel@tonic-gate/* 300Sstevel@tonic-gate * strncmp(s1, s2, n) 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * Compare strings (at most n bytes): s1>s2: >0 s1==s2: 0 s1<s2: <0 330Sstevel@tonic-gate * 340Sstevel@tonic-gate * Fast assembler language version of the following C-program for strncmp 350Sstevel@tonic-gate * which represents the `standard' for the C-library. 360Sstevel@tonic-gate * 370Sstevel@tonic-gate * int 380Sstevel@tonic-gate * strncmp(const char *s1, const char *s2, size_t n) 390Sstevel@tonic-gate * { 400Sstevel@tonic-gate * n++; 410Sstevel@tonic-gate * if (s1 == s2) 420Sstevel@tonic-gate * return (0); 430Sstevel@tonic-gate * while (--n != 0 && *s1 == *s2++) 440Sstevel@tonic-gate * if (*s1++ == '\0') 450Sstevel@tonic-gate * return (0); 460Sstevel@tonic-gate * return ((n == 0) ? 0 : (*s1 - s2[-1])); 470Sstevel@tonic-gate * } 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate 500Sstevel@tonic-gate#include <sys/asm_linkage.h> 510Sstevel@tonic-gate 520Sstevel@tonic-gate ENTRY(strncmp) 530Sstevel@tonic-gate save %sp, -SA(WINDOWSIZE), %sp 540Sstevel@tonic-gate cmp %i2, 8 550Sstevel@tonic-gate blu,a .cmp_bytes ! for small counts go do bytes 560Sstevel@tonic-gate sub %i0, %i1, %i0 ! delay slot, get diff from s1 - s2 570Sstevel@tonic-gate andcc %i0, 3, %g0 ! is s1 aligned 580Sstevel@tonic-gate1: bz .iss2 ! if so go check s2 590Sstevel@tonic-gate andcc %i1, 3, %i3 ! is s2 aligned 600Sstevel@tonic-gate 610Sstevel@tonic-gate deccc %i2 ! --n >= 0 ? 620Sstevel@tonic-gate bcs .doneq 630Sstevel@tonic-gate nop ! delay slot 640Sstevel@tonic-gate 650Sstevel@tonic-gate ldub [%i0], %i4 ! else cmp one byte 660Sstevel@tonic-gate ldub [%i1], %i5 670Sstevel@tonic-gate inc %i0 680Sstevel@tonic-gate cmp %i4, %i5 690Sstevel@tonic-gate bne .noteqb 700Sstevel@tonic-gate inc %i1 710Sstevel@tonic-gate tst %i4 ! terminating zero 720Sstevel@tonic-gate bnz 1b 730Sstevel@tonic-gate andcc %i0, 3, %g0 740Sstevel@tonic-gate b,a .doneq 750Sstevel@tonic-gate 760Sstevel@tonic-gate.iss2: 770Sstevel@tonic-gate set 0x7efefeff, %l6 780Sstevel@tonic-gate set 0x81010100, %l7 790Sstevel@tonic-gate sethi %hi(0xff000000), %l0 ! masks to test for terminating null 800Sstevel@tonic-gate sethi %hi(0x00ff0000), %l1 810Sstevel@tonic-gate srl %l1, 8, %l2 ! generate 0x0000ff00 mask 820Sstevel@tonic-gate 830Sstevel@tonic-gate bz .w4cmp ! if s2 word aligned, compare words 840Sstevel@tonic-gate cmp %i3, 2 ! check if s2 half aligned 850Sstevel@tonic-gate be .w2cmp 860Sstevel@tonic-gate cmp %i3, 1 ! check if aligned to 1 or 3 bytes 870Sstevel@tonic-gate.w3cmp: ldub [%i1], %i5 880Sstevel@tonic-gate inc 1, %i1 890Sstevel@tonic-gate be .w1cmp 900Sstevel@tonic-gate sll %i5, 24, %i5 910Sstevel@tonic-gate sub %i0, %i1, %i0 920Sstevel@tonic-gate2: 930Sstevel@tonic-gate deccc 4, %i2 ! n >= 4 ? 940Sstevel@tonic-gate bgeu,a 3f 950Sstevel@tonic-gate ld [%i1], %i3 ! delay slot 960Sstevel@tonic-gate dec %i1 ! reset s2 970Sstevel@tonic-gate inc %i0 ! reset s1 diff 980Sstevel@tonic-gate b .cmp_bytes ! do a byte at a time if n < 4 990Sstevel@tonic-gate inc 4, %i2 1000Sstevel@tonic-gate3: 1010Sstevel@tonic-gate ld [%i0 + %i1], %i4 1020Sstevel@tonic-gate inc 4, %i1 1030Sstevel@tonic-gate srl %i3, 8, %l4 ! merge with the other half 1040Sstevel@tonic-gate or %l4, %i5, %i5 1050Sstevel@tonic-gate cmp %i4, %i5 1060Sstevel@tonic-gate be 1f 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate add %i4, %l6, %l3 1090Sstevel@tonic-gate b,a .noteq 1100Sstevel@tonic-gate1: xor %l3, %i4, %l3 1110Sstevel@tonic-gate and %l3, %l7, %l3 1120Sstevel@tonic-gate cmp %l3, %l7 1130Sstevel@tonic-gate be,a 2b 1140Sstevel@tonic-gate sll %i3, 24, %i5 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate ! 1170Sstevel@tonic-gate ! For 7-bit characters, we know one of the bytes is zero, but for 1180Sstevel@tonic-gate ! 8-bit characters, the zero detection algorithm gives some false 1190Sstevel@tonic-gate ! triggers ... check every byte individually. 1200Sstevel@tonic-gate ! 1210Sstevel@tonic-gate andcc %i4, %l0, %g0 ! check if first byte was zero 1220Sstevel@tonic-gate bnz 1f 1230Sstevel@tonic-gate andcc %i4, %l1, %g0 ! check if second byte was zero 1240Sstevel@tonic-gate b,a .doneq 1250Sstevel@tonic-gate1: bnz 1f 1260Sstevel@tonic-gate andcc %i4, %l2, %g0 ! check if third byte was zero 1270Sstevel@tonic-gate b,a .doneq 1280Sstevel@tonic-gate1: bnz 1f 1290Sstevel@tonic-gate andcc %i4, 0xff, %g0 ! check if last byte is zero 1300Sstevel@tonic-gate b,a .doneq 1310Sstevel@tonic-gate1: bnz 2b 1320Sstevel@tonic-gate sll %i3, 24, %i5 1330Sstevel@tonic-gate b,a .doneq 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate.w1cmp: clr %l4 1360Sstevel@tonic-gate lduh [%i1], %l4 1370Sstevel@tonic-gate inc 2, %i1 1380Sstevel@tonic-gate sll %l4, 8, %l4 1390Sstevel@tonic-gate or %i5, %l4, %i5 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate sub %i0, %i1, %i0 1420Sstevel@tonic-gate3: 1430Sstevel@tonic-gate deccc 4, %i2 ! n >= 4 ? 1440Sstevel@tonic-gate bgeu,a 4f 1450Sstevel@tonic-gate ld [%i1], %i3 ! delay slot 1460Sstevel@tonic-gate dec 3, %i1 ! reset s2 1470Sstevel@tonic-gate inc 3, %i0 ! reset s1 diff 1480Sstevel@tonic-gate b .cmp_bytes ! do a byte at a time if n < 4 1490Sstevel@tonic-gate inc 4, %i2 1500Sstevel@tonic-gate4: 1510Sstevel@tonic-gate ld [%i0 + %i1], %i4 1520Sstevel@tonic-gate inc 4, %i1 1530Sstevel@tonic-gate srl %i3, 24, %l4 ! merge with the other half 1540Sstevel@tonic-gate or %l4, %i5, %i5 1550Sstevel@tonic-gate cmp %i4, %i5 1560Sstevel@tonic-gate be 1f 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate add %i4, %l6, %l3 1590Sstevel@tonic-gate b,a .noteq 1600Sstevel@tonic-gate1: xor %l3, %i4, %l3 1610Sstevel@tonic-gate and %l3, %l7, %l3 1620Sstevel@tonic-gate cmp %l3, %l7 1630Sstevel@tonic-gate be,a 3b 1640Sstevel@tonic-gate sll %i3, 8, %i5 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate andcc %i4, %l0, %g0 ! check if first byte was zero 1670Sstevel@tonic-gate bnz 1f 1680Sstevel@tonic-gate andcc %i4, %l1, %g0 ! check if second byte was zero 1690Sstevel@tonic-gate b,a .doneq 1700Sstevel@tonic-gate1: bnz 1f 1710Sstevel@tonic-gate andcc %i4, %l2, %g0 ! check if third byte was zero 1720Sstevel@tonic-gate b,a .doneq 1730Sstevel@tonic-gate1: bnz 1f 1740Sstevel@tonic-gate andcc %i4, 0xff, %g0 ! check if last byte is zero 1750Sstevel@tonic-gate b,a .doneq 1760Sstevel@tonic-gate1: bnz 3b 1770Sstevel@tonic-gate sll %i3, 8, %i5 1780Sstevel@tonic-gate b,a .doneq 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate.w2cmp: 1810Sstevel@tonic-gate lduh [%i1], %i5 ! read a halfword to align s2 1820Sstevel@tonic-gate inc 2, %i1 1830Sstevel@tonic-gate sll %i5, 16, %i5 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate sub %i0, %i1, %i0 1860Sstevel@tonic-gate4: 1870Sstevel@tonic-gate deccc 4, %i2 ! n >= 4 ? 1880Sstevel@tonic-gate bgeu,a 5f 1890Sstevel@tonic-gate ld [%i1], %i3 ! delay slot 1900Sstevel@tonic-gate dec 2, %i1 ! reset s2 1910Sstevel@tonic-gate inc 2, %i0 ! reset s1 diff 1920Sstevel@tonic-gate b .cmp_bytes ! do a byte at a time if n < 4 1930Sstevel@tonic-gate inc 4, %i2 ! delay slot 1940Sstevel@tonic-gate5: 1950Sstevel@tonic-gate ld [%i1 + %i0], %i4 ! read a word from s2 1960Sstevel@tonic-gate inc 4, %i1 1970Sstevel@tonic-gate srl %i3, 16, %l4 ! merge with the other half 1980Sstevel@tonic-gate or %l4, %i5, %i5 1990Sstevel@tonic-gate cmp %i4, %i5 2000Sstevel@tonic-gate be 1f 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate add %i4, %l6, %l3 2030Sstevel@tonic-gate b,a .noteq 2040Sstevel@tonic-gate1: xor %l3, %i4, %l3 ! are any bytes 0? 2050Sstevel@tonic-gate and %l3, %l7, %l3 2060Sstevel@tonic-gate cmp %l3, %l7 2070Sstevel@tonic-gate be,a 4b 2080Sstevel@tonic-gate sll %i3, 16, %i5 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate andcc %i4, %l0, %g0 ! check if first byte was zero 2110Sstevel@tonic-gate bnz 1f 2120Sstevel@tonic-gate andcc %i4, %l1, %g0 ! check if second byte was zero 2130Sstevel@tonic-gate b,a .doneq 2140Sstevel@tonic-gate1: bnz 1f 2150Sstevel@tonic-gate andcc %i4, %l2, %g0 ! check if third byte was zero 2160Sstevel@tonic-gate b,a .doneq 2170Sstevel@tonic-gate1: bnz 1f 2180Sstevel@tonic-gate andcc %i4, 0xff, %g0 ! check if last byte is zero 2190Sstevel@tonic-gate b,a .doneq 2200Sstevel@tonic-gate1: bnz 4b 2210Sstevel@tonic-gate sll %i3, 16, %i5 2220Sstevel@tonic-gate b,a .doneq 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate.w4cmp: sub %i0, %i1, %i0 2250Sstevel@tonic-gate ld [%i1], %i5 ! read a word from s1 2260Sstevel@tonic-gate5: cmp %i2,0 2270Sstevel@tonic-gate be,a .doneq 2280Sstevel@tonic-gate nop 2290Sstevel@tonic-gate ld [%i1], %i5 ! read a word from s1 2300Sstevel@tonic-gate deccc 4, %i2 ! n >= 4 ? 2310Sstevel@tonic-gate bcs,a .cmp_bytes ! do a byte at a time if n < 4 2320Sstevel@tonic-gate inc 4, %i2 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate ld [%i1 + %i0], %i4 ! read a word from s2 2350Sstevel@tonic-gate cmp %i4, %i5 2360Sstevel@tonic-gate inc 4, %i1 2370Sstevel@tonic-gate be 1f 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate add %i4, %l6, %l3 2400Sstevel@tonic-gate b,a .noteq 2410Sstevel@tonic-gate1: xor %l3, %i4, %l3 2420Sstevel@tonic-gate and %l3, %l7, %l3 2430Sstevel@tonic-gate cmp %l3, %l7 2440Sstevel@tonic-gate be,a 5b 2450Sstevel@tonic-gate nop 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate andcc %i4, %l0, %g0 ! check if first byte was zero 2480Sstevel@tonic-gate bnz 1f 2490Sstevel@tonic-gate andcc %i4, %l1, %g0 ! check if second byte was zero 2500Sstevel@tonic-gate b,a .doneq 2510Sstevel@tonic-gate1: bnz 1f 2520Sstevel@tonic-gate andcc %i4, %l2, %g0 ! check if third byte was zero 2530Sstevel@tonic-gate b,a .doneq 2540Sstevel@tonic-gate1: bnz 1f 2550Sstevel@tonic-gate andcc %i4, 0xff, %g0 ! check if last byte is zero 2560Sstevel@tonic-gate b,a .doneq 2570Sstevel@tonic-gate1: bnz,a 5b 2580Sstevel@tonic-gate ld [%i1], %i5 2590Sstevel@tonic-gate.doneq: ret 2600Sstevel@tonic-gate restore %g0, %g0, %o0 ! equal return zero 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate.noteq: srl %i4, 24, %l4 2630Sstevel@tonic-gate srl %i5, 24, %l5 2640Sstevel@tonic-gate subcc %l4, %l5, %i0 2650Sstevel@tonic-gate bne 6f 2660Sstevel@tonic-gate andcc %l4, 0xff, %g0 2670Sstevel@tonic-gate bz .doneq 2680Sstevel@tonic-gate sll %i4, 8, %l4 2690Sstevel@tonic-gate sll %i5, 8, %l5 2700Sstevel@tonic-gate srl %l4, 24, %l4 2710Sstevel@tonic-gate srl %l5, 24, %l5 2720Sstevel@tonic-gate subcc %l4, %l5, %i0 2730Sstevel@tonic-gate bne 6f 2740Sstevel@tonic-gate andcc %l4, 0xff, %g0 2750Sstevel@tonic-gate bz .doneq 2760Sstevel@tonic-gate sll %i4, 16, %l4 2770Sstevel@tonic-gate sll %i5, 16, %l5 2780Sstevel@tonic-gate srl %l4, 24, %l4 2790Sstevel@tonic-gate srl %l5, 24, %l5 2800Sstevel@tonic-gate subcc %l4, %l5, %i0 2810Sstevel@tonic-gate bne 6f 2820Sstevel@tonic-gate andcc %l4, 0xff, %g0 2830Sstevel@tonic-gate bz .doneq 2840Sstevel@tonic-gate nop 2850Sstevel@tonic-gate.noteqb: 2860Sstevel@tonic-gate and %i4, 0xff, %l4 2870Sstevel@tonic-gate and %i5, 0xff, %l5 2880Sstevel@tonic-gate subcc %l4, %l5, %i0 2890Sstevel@tonic-gate6: ret 2900Sstevel@tonic-gate restore %i0, %g0, %o0 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate ! Do a byte by byte comparison, disregarding alignments 2930Sstevel@tonic-gate.cmp_bytes: 2940Sstevel@tonic-gate deccc %i2 ! --n >= 0 ? 2950Sstevel@tonic-gate1: 2960Sstevel@tonic-gate bcs .doneq 2970Sstevel@tonic-gate nop ! delay slot 2980Sstevel@tonic-gate ldub [%i1 + %i0], %i4 ! read a word from s1 2990Sstevel@tonic-gate ldub [%i1], %i5 ! read a word from s2 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate inc %i1 3020Sstevel@tonic-gate cmp %i4, %i5 3030Sstevel@tonic-gate bne .noteqb 3040Sstevel@tonic-gate tst %i4 ! terminating zero 3050Sstevel@tonic-gate bnz 1b 3060Sstevel@tonic-gate deccc %i2 ! --n >= 0 3070Sstevel@tonic-gate b,a .doneq 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate SET_SIZE(strncmp) 310