xref: /titanic_41/usr/src/lib/libbc/libc/crt/sparc/misalign.s (revision 40db2e2b777b79f3dd0d6d9629593a07f86b9c0a)
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