1! .text 2! .asciz ident "%Z%%M% %I% %E% SMI" 3! .align 4 4! .seg "text" 5 6! Copyright 2005 Sun Microsystems, Inc. All rights reserved. 7! Use is subject to license terms. 8! 9! CDDL HEADER START 10! 11! The contents of this file are subject to the terms of the 12! Common Development and Distribution License, Version 1.0 only 13! (the "License"). You may not use this file except in compliance 14! with the License. 15! 16! You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 17! or http://www.opensolaris.org/os/licensing. 18! See the License for the specific language governing permissions 19! and limitations under the License. 20! 21! When distributing Covered Code, include this CDDL HEADER in each 22! file and include the License file at usr/src/OPENSOLARIS.LICENSE. 23! If applicable, add the following below this CDDL HEADER, with the 24! fields enclosed by brackets "[]" replaced with your own identifying 25! information: Portions Copyright [yyyy] [name of copyright owner] 26! 27! CDDL HEADER END 28! 29 30! 31! C library routines for compiler support of misaligned memory 32! references. These are called when an in-line test reveals a 33! misaligned address. 34! 35 36 .file "misalign.s" 37 38#include <SYS.h> 39 40!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 41 42! 43! int ld_int(p) 44! char *p; 45! { 46! /* 47! * load 32-bit int from misaligned address 48! * cost(16-bit aligned case): 9 cycles 49! * cost(8-bit aligned case): 18 cycles 50! */ 51! } 52! 53 RTENTRY(.ld_int) 54 andcc %o0,1,%g0 ! test 16-bit alignment 55 be,a 1f ! fast case: two loads; 56 lduh [%o0+2],%o1 ! do first one in delay slot 57! 58 ldub [%o0+3],%o3 ! slow case: load 4 bytes in <o0,o1,o2,o3> 59 ldub [%o0+2],%o2 60 ldub [%o0+1],%o1 61 ldub [%o0],%o0 ! note this has to be done last. 62 sll %o2,8,%o2 63 sll %o1,16,%o1 64 sll %o0,24,%o0 65 or %o1,%o0,%o0 ! put the pieces together. 66 or %o2,%o0,%o0 67 retl 68 or %o3,%o0,%o0 691: 70 lduh [%o0],%o0 ! 2nd half of fast case 71 sll %o0,16,%o0 ! shift, concat, done. 72 retl 73 or %o0,%o1,%o0 74 SET_SIZE(.ld_int) 75 76!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 77 78! 79! float ld_float(p) 80! char *p; 81! { 82! /* load 32-bit float (not double!) from misaligned address */ 83! } 84! 85 RTENTRY(.ld_float) 86 save %sp,-SA(MINFRAME+8),%sp 87 andcc %i0,1,%g0 ! test for short alignment 88 be,a 1f 89 lduh [%i0],%o0 ! short aligned case: 2 loads, 2 stores 90! 91 ldub [%i0],%o0 ! byte aligned case: 4 loads, 4 stores 92 ldub [%i0+1],%o1 93 ldub [%i0+2],%o2 94 ldub [%i0+3],%o3 95 stb %o0,[%fp-4] 96 stb %o1,[%fp-3] 97 stb %o2,[%fp-2] 98 b 2f 99 stb %o3,[%fp-1] 1001: 101 lduh [%i0+2],%o1 ! rest of short aligned case 102 sth %o0,[%fp-4] 103 sth %o1,[%fp-2] 1042: 105 ld [%fp-4],%f0 ! load FPU reg, done 106 ret 107 restore 108 SET_SIZE(.ld_float) 109 110!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 111 112! 113! double ld_double(p) 114! char *p; 115! { 116! /* load 64-bit float from misaligned address */ 117! } 118! 119 RTENTRY(.ld_double) 120 save %sp,-SA(MINFRAME+8),%sp 121 andcc %i0,3,%g0 ! test for long alignment 122 be,a 1f ! long aligned case: 2 loads, no stores 123 ld [%i0],%f0 124! 125 andcc %i0,1,%g0 ! test for short alignment 126 be,a 2f ! short aligned case: 4 loads, 4 stores 127 lduh [%i0],%o0 128! 129 ldub [%i0],%o0 ! worst case: byte alignment 130 ldub [%i0+1],%o1 ! 8 loads, 8 stores 131 ldub [%i0+2],%o2 132 ldub [%i0+3],%o3 133 stb %o0,[%fp-8] 134 stb %o1,[%fp-7] 135 stb %o2,[%fp-6] 136 stb %o3,[%fp-5] 137 ldub [%i0+4],%o0 138 ldub [%i0+5],%o1 139 ldub [%i0+6],%o2 140 ldub [%i0+7],%o3 141 stb %o0,[%fp-4] 142 stb %o1,[%fp-3] 143 stb %o2,[%fp-2] 144 stb %o3,[%fp-1] 145 ldd [%fp-8],%f0 ! load f0-f1, done 146 ret 147 restore 1482: 149 lduh [%i0+2],%o1 ! rest of short aligned case 150 lduh [%i0+4],%o2 151 lduh [%i0+6],%o3 152 sth %o0,[%fp-8] 153 sth %o1,[%fp-6] 154 sth %o2,[%fp-4] 155 sth %o3,[%fp-2] 156 ldd [%fp-8],%f0 ! load f0-f1, done 157 ret 158 restore 1591: 160 ld [%i0+4],%f1 ! rest of long aligned case 161 ret 162 restore 163 SET_SIZE(.ld_double) 164 165!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 166 167! 168! int st_int(x,p) 169! int x; 170! char *p; 171! { 172! /* store 32-bit int from misaligned address; 173! return stored value */ 174! } 175! 176 RTENTRY(.st_int) 177 andcc %o1,1,%g0 ! test for short alignment 178 be,a 1f 179 srl %o0,16,%o4 180! 181 srl %o0,24,%o5 ! byte aligned case 182 stb %o5,[%o1] 183 srl %o0,16,%o2 184 stb %o2,[%o1+1] 185 srl %o0,8,%o3 186 stb %o3,[%o1+2] 187 retl 188 stb %o0,[%o1+3] 1891: 190 sth %o4,[%o1] ! rest of short aligned case 191 retl 192 sth %o0,[%o1+2] 193 SET_SIZE(.st_int) 194 195!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 196 197! 198! float st_float(x,p) 199! float x; 200! char *p; 201! { 202! /* store 32-bit float from misaligned address; 203! return stored value */ 204! } 205! 206 RTENTRY(.st_float) 207 save %sp,-SA(MINFRAME+8),%sp 208 andcc %i1,1,%g0 ! test for short alignment 209 be,a 1f ! short aligned case 210 srl %i0,16,%o0 211! 212 srl %i0,24,%o0 ! byte aligned case 213 srl %i0,16,%o1 214 srl %i0,8,%o2 215 stb %o0,[%i1] 216 stb %o1,[%i1+1] 217 stb %o2,[%i1+2] 218 stb %i0,[%i1+3] 219 st %i0,[%fp-4] ! store temp, load f0, done 220 ld [%fp-4],%f0 221 ret 222 restore 2231: 224 sth %o0,[%i1] ! rest of short aligned case 225 sth %i0,[%i1+2] 226 st %i0,[%fp-4] 227 ld [%fp-4],%f0 228 ret 229 restore 230 SET_SIZE(.st_float) 231 232!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 233 234! 235! double st_double(x,p) 236! double x; 237! char *p; 238! { 239! /* store 64-bit float from misaligned address; 240! return stored value */ 241! } 242! 243 RTENTRY(.st_double) 244 save %sp,-SA(MINFRAME+8),%sp 245 andcc %i2,3,%g0 ! test for long alignment 246 be,a 1f ! long aligned case: 2 stores, 2 loads 247 st %i0,[%i2] 248! 249 andcc %i2,1,%g0 ! test for short alignment 250 be,a 2f ! short aligned case: 4 stores, 4 loads 251 srl %i0,16,%o0 252! ! byte aligned case: the pits 253 srl %i0,24,%o0 254 srl %i0,16,%o1 255 srl %i0,8,%o2 256 stb %o0,[%i2] ! store first word, a byte at a time 257 stb %o1,[%i2+1] 258 stb %o2,[%i2+2] 259 stb %i0,[%i2+3] 260 srl %i1,24,%o0 261 srl %i1,16,%o1 262 srl %i1,8,%o2 263 stb %o0,[%i2+4] ! store second word, a byte at a time 264 stb %o1,[%i2+5] 265 stb %o2,[%i2+6] 266 stb %i1,[%i2+7] 267 std %i0,[%fp-8] ! since dest is misaligned, must use temp 268 ldd [%fp-8],%f0 ! load f0,f1 from double-aligned temp, done 269 ret 270 restore 2712: ! rest of short aligned case 272 srl %i1,16,%o1 273 sth %o0,[%i2] ! store two words, a half word at a time 274 sth %i0,[%i2+2] 275 sth %o1,[%i2+4] 276 sth %i1,[%i2+6] 277 std %i0,[%fp-8] ! since dest is misaligned, must use temp 278 ldd [%fp-8],%f0 ! load f0,f1 from double-aligned temp, done 279 ret 280 restore 2811: ! rest of long aligned case 282 st %i1,[%i2+4] 283 ld [%i2],%f0 ! load f0,f1 from long-aligned memory, done 284 ld [%i2+4],%f1 285 ret 286 restore 287 SET_SIZE(.st_double) 288 289!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 290 291! 292! void st_float_foreff(x,p) 293! float x; 294! char *p; 295! { 296! /* store 32-bit float from misaligned address */ 297! } 298! 299 RTENTRY(.st_float_foreff) 300 andcc %o1,1,%g0 ! test for short alignment 301 be,a 1f 302 srl %o0,16,%o2 303! 304 srl %o0,24,%o2 ! byte aligned case 305 srl %o0,16,%o3 306 srl %o0,8,%o4 307 stb %o2,[%o1] 308 stb %o3,[%o1+1] 309 stb %o4,[%o1+2] 310 retl 311 stb %o0,[%o1+3] 3121: ! rest of short aligned case 313 sth %o2,[%o1] 314 retl 315 sth %o0,[%o1+2] 316 SET_SIZE(.st_float_foreff) 317 318!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 319 320! 321! void st_double_foreff(x,p) 322! double x; 323! char *p; 324! { 325! /* store 64-bit float from misaligned address; 326! return stored value */ 327! } 328! 329 RTENTRY(.st_double_foreff) 330 andcc %o2,3,%g0 ! test for long alignment 331 be,a 1f ! long aligned case: 2 stores 332 st %o0,[%o2] 333! 334 andcc %o2,1,%g0 ! test for short alignment 335 be,a 2f ! short aligned case: 4 stores 336 srl %o0,16,%o3 337! 338 srl %o0,24,%o3 ! byte aligned case: 8 stores 339 srl %o0,16,%o4 340 srl %o0,8,%o5 341 stb %o3,[%o2] 342 stb %o4,[%o2+1] 343 stb %o5,[%o2+2] 344 stb %o0,[%o2+3] 345 srl %o1,24,%o3 346 srl %o1,16,%o4 347 srl %o1,8,%o5 348 stb %o3,[%o2+4] 349 stb %o4,[%o2+5] 350 stb %o5,[%o2+6] 351 retl 352 stb %o1,[%o2+7] 3532: ! rest of short aligned case 354 srl %o1,16,%o4 355 sth %o3,[%o2] 356 sth %o0,[%o2+2] 357 sth %o4,[%o2+4] 358 retl 359 sth %o1,[%o2+6] 3601: ! rest of long aligned case 361 retl 362 st %o1,[%o2+4] 363 SET_SIZE(.st_double_foreff) 364