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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 .file "memset.s" 27 28/* 29 * char *memset(sp, c, n) 30 * 31 * Set an array of n chars starting at sp to the character c. 32 * Return sp. 33 * 34 * Fast assembler language version of the following C-program for memset 35 * which represents the `standard' for the C-library. 36 * 37 * void * 38 * memset(void *sp1, int c, size_t n) 39 * { 40 * if (n != 0) { 41 * char *sp = sp1; 42 * do { 43 * *sp++ = (char)c; 44 * } while (--n != 0); 45 * } 46 * return (sp1); 47 * } 48 * 49 * Flow : 50 * 51 * For small 6 or fewer bytes stores, bytes will be stored. 52 * 53 * For less than 32 bytes stores, align the address on 4 byte boundary. 54 * Then store as many 4-byte chunks, followed by trailing bytes. 55 * 56 * For sizes greater than 32 bytes, align the address on 8 byte boundary. 57 * if (count > 64) { 58 * store as many 8-bytes chunks to block align the address 59 * store using ASI_BLK_INIT_ST_QUAD_LDD_P 60 * } 61 * Store as many 8-byte chunks, followed by trialing bytes. 62 * 63 */ 64 65#include <sys/asm_linkage.h> 66#include <sys/niagaraasi.h> 67#include <sys/asi.h> 68 69 ANSI_PRAGMA_WEAK(memset,function) 70 71 .section ".text" 72 .align 32 73 74 ENTRY(memset) 75 76 mov %o0, %o5 ! copy sp1 before using it 77 cmp %o2, 7 ! if small counts, just write bytes 78 blu,pn %ncc, .wrchar 79 and %o1, 0xff, %o1 ! o1 is (char)c 80 81 sll %o1, 8, %o3 82 or %o1, %o3, %o1 ! now o1 has 2 bytes of c 83 sll %o1, 16, %o3 84 85 cmp %o2, 0x20 86 blu,pn %ncc, .wdalign 87 or %o1, %o3, %o1 ! now o1 has 4 bytes of c 88 89 sllx %o1, 32, %o3 90 or %o1, %o3, %o1 ! now o1 has 8 bytes of c 91 92.dbalign: 93 andcc %o5, 7, %o3 ! is sp1 aligned on a 8 byte bound 94 bz,pt %ncc, .blkalign ! already double aligned 95 sub %o3, 8, %o3 ! -(bytes till double aligned) 96 add %o2, %o3, %o2 ! update o2 with new count 97 98 ! Set -(%o3) bytes till sp1 double aligned 991: stb %o1, [%o5] ! there is at least 1 byte to set 100 inccc %o3 ! byte clearing loop 101 bl,pt %ncc, 1b 102 inc %o5 103 104 ! Now sp1 is double aligned (sp1 is found in %o5) 105.blkalign: 106 mov ASI_BLK_INIT_ST_QUAD_LDD_P, %asi 107 108 cmp %o2, 0x40 ! check if there are 64 bytes to set 109 blu,pn %ncc, 5f 110 mov %o2, %o3 111 112 andcc %o5, 63, %o3 ! is sp1 block aligned? 113 bz,pt %ncc, .blkwr ! now block aligned 114 sub %o3, 64, %o3 ! o3 is -(bytes till block aligned) 115 add %o2, %o3, %o2 ! o2 is the remainder 116 117 ! Store -(%o3) bytes till dst is block (64 byte) aligned. 118 ! Use double word stores. 119 ! Recall that dst is already double word aligned 1201: 121 stx %o1, [%o5] 122 addcc %o3, 8, %o3 123 bl,pt %ncc, 1b 124 add %o5, 8, %o5 125 126 ! Now sp1 is block aligned 127.blkwr: 128 and %o2, 63, %o3 ! calc bytes left after blk store. 129 andn %o2, 63, %o4 ! calc size of blocks in bytes 130 131 cmp %o4, 0x100 ! check if there are 256 bytes to set 132 blu,pn %ncc, 3f 133 nop 1342: 135 stxa %o1, [%o5+0x0]%asi 136 stxa %o1, [%o5+0x40]%asi 137 stxa %o1, [%o5+0x80]%asi 138 stxa %o1, [%o5+0xc0]%asi 139 140 stxa %o1, [%o5+0x8]%asi 141 stxa %o1, [%o5+0x10]%asi 142 stxa %o1, [%o5+0x18]%asi 143 stxa %o1, [%o5+0x20]%asi 144 stxa %o1, [%o5+0x28]%asi 145 stxa %o1, [%o5+0x30]%asi 146 stxa %o1, [%o5+0x38]%asi 147 148 stxa %o1, [%o5+0x48]%asi 149 stxa %o1, [%o5+0x50]%asi 150 stxa %o1, [%o5+0x58]%asi 151 stxa %o1, [%o5+0x60]%asi 152 stxa %o1, [%o5+0x68]%asi 153 stxa %o1, [%o5+0x70]%asi 154 stxa %o1, [%o5+0x78]%asi 155 156 stxa %o1, [%o5+0x88]%asi 157 stxa %o1, [%o5+0x90]%asi 158 stxa %o1, [%o5+0x98]%asi 159 stxa %o1, [%o5+0xa0]%asi 160 stxa %o1, [%o5+0xa8]%asi 161 stxa %o1, [%o5+0xb0]%asi 162 stxa %o1, [%o5+0xb8]%asi 163 164 stxa %o1, [%o5+0xc8]%asi 165 stxa %o1, [%o5+0xd0]%asi 166 stxa %o1, [%o5+0xd8]%asi 167 stxa %o1, [%o5+0xe0]%asi 168 stxa %o1, [%o5+0xe8]%asi 169 stxa %o1, [%o5+0xf0]%asi 170 stxa %o1, [%o5+0xf8]%asi 171 172 sub %o4, 0x100, %o4 173 cmp %o4, 0x100 174 bgu,pt %ncc, 2b 175 add %o5, 0x100, %o5 176 1773: 178 cmp %o4, 0x40 ! check if 64 bytes to set 179 blu %ncc, 5f 180 nop 1814: 182 stxa %o1, [%o5+0x0]%asi 183 stxa %o1, [%o5+0x8]%asi 184 stxa %o1, [%o5+0x10]%asi 185 stxa %o1, [%o5+0x18]%asi 186 stxa %o1, [%o5+0x20]%asi 187 stxa %o1, [%o5+0x28]%asi 188 stxa %o1, [%o5+0x30]%asi 189 stxa %o1, [%o5+0x38]%asi 190 191 subcc %o4, 0x40, %o4 192 bgu,pt %ncc, 4b 193 add %o5, 0x40, %o5 194 1955: 196 ! Set the remaining doubles 197 membar #Sync 198 mov ASI_PNF, %asi ! restore %asi to default 199 ! ASI_PRIMARY_NOFAULT value 200 subcc %o3, 8, %o3 ! Can we store any doubles? 201 blu,pn %ncc, .wrchar 202 and %o2, 7, %o2 ! calc bytes left after doubles 203 2046: 205 stx %o1, [%o5] ! store the doubles 206 subcc %o3, 8, %o3 207 bgeu,pt %ncc, 6b 208 add %o5, 8, %o5 209 210 ba .wrchar 211 nop 212 213.wdalign: 214 andcc %o5, 3, %o3 ! is sp1 aligned on a word boundary 215 bz,pn %ncc, .wrword 216 andn %o2, 3, %o3 ! create word sized count in %o3 217 218 dec %o2 ! decrement count 219 stb %o1, [%o5] ! clear a byte 220 b .wdalign 221 inc %o5 ! next byte 222 223.wrword: 224 st %o1, [%o5] ! 4-byte writing loop 225 subcc %o3, 4, %o3 226 bnz,pt %ncc, .wrword 227 inc 4, %o5 228 229 and %o2, 3, %o2 ! leftover count, if any 230 231.wrchar: 232 ! Set the remaining bytes, if any 233 cmp %o2, 0 234 be %ncc, .exit 235 nop 236 2377: 238 deccc %o2 239 stb %o1, [%o5] 240 bgu,pt %ncc, 7b 241 inc %o5 242 243.exit: 244 retl ! %o0 was preserved 245 nop 246 247 SET_SIZE(memset) 248