Files
Arquivotheca.SunOS-4.1.4/lib/libc/crt/sparc/misalign.s
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

331 lines
6.6 KiB
ArmAsm

.text
.asciz "@(#)misalign.s 1.1 94/10/31 Copyr 1987 Sun Micro"
.align 4
! Copyright (c) 1987 by Sun Microsystems,Inc.
!
! C library routines for compiler support of misaligned memory
! references. These are called when an in-line test reveals a
! misaligned address.
!
#include <machine/asm_linkage.h>
!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
! int ld_int(p)
! char *p;
! {
! /*
! * load 32-bit int from misaligned address
! * cost(16-bit aligned case): 9 cycles
! * cost(8-bit aligned case): 18 cycles
! */
! }
!
RTENTRY(ld_int)
andcc %o0,1,%g0 ! test 16-bit alignment
be,a 1f ! fast case: two loads;
lduh [%o0+2],%o1 ! do first one in delay slot
!
ldub [%o0+3],%o3 ! slow case: load 4 bytes in <o0,o1,o2,o3>
ldub [%o0+2],%o2
ldub [%o0+1],%o1
ldub [%o0],%o0 ! note this has to be done last.
sll %o2,8,%o2
sll %o1,16,%o1
sll %o0,24,%o0
or %o1,%o0,%o0 ! put the pieces together.
or %o2,%o0,%o0
retl
or %o3,%o0,%o0
1:
lduh [%o0],%o0 ! 2nd half of fast case
sll %o0,16,%o0 ! shift, concat, done.
retl
or %o0,%o1,%o0
!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
! float ld_float(p)
! char *p;
! {
! /* load 32-bit float (not double!) from misaligned address */
! }
!
RTENTRY(ld_float)
save %sp,-SA(MINFRAME+8),%sp
andcc %i0,1,%g0 ! test for short alignment
be,a 1f
lduh [%i0],%o0 ! short aligned case: 2 loads, 2 stores
!
ldub [%i0],%o0 ! byte aligned case: 4 loads, 4 stores
ldub [%i0+1],%o1
ldub [%i0+2],%o2
ldub [%i0+3],%o3
stb %o0,[%fp-4]
stb %o1,[%fp-3]
stb %o2,[%fp-2]
b 2f
stb %o3,[%fp-1]
1:
lduh [%i0+2],%o1 ! rest of short aligned case
sth %o0,[%fp-4]
sth %o1,[%fp-2]
2:
ld [%fp-4],%f0 ! load FPU reg, done
ret
restore
!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
! double ld_double(p)
! char *p;
! {
! /* load 64-bit float from misaligned address */
! }
!
RTENTRY(ld_double)
save %sp,-SA(MINFRAME+8),%sp
andcc %i0,3,%g0 ! test for long alignment
be,a 1f ! long aligned case: 2 loads, no stores
ld [%i0],%f0
!
andcc %i0,1,%g0 ! test for short alignment
be,a 2f ! short aligned case: 4 loads, 4 stores
lduh [%i0],%o0
!
ldub [%i0],%o0 ! worst case: byte alignment
ldub [%i0+1],%o1 ! 8 loads, 8 stores
ldub [%i0+2],%o2
ldub [%i0+3],%o3
stb %o0,[%fp-8]
stb %o1,[%fp-7]
stb %o2,[%fp-6]
stb %o3,[%fp-5]
ldub [%i0+4],%o0
ldub [%i0+5],%o1
ldub [%i0+6],%o2
ldub [%i0+7],%o3
stb %o0,[%fp-4]
stb %o1,[%fp-3]
stb %o2,[%fp-2]
stb %o3,[%fp-1]
ldd [%fp-8],%f0 ! load f0-f1, done
ret
restore
2:
lduh [%i0+2],%o1 ! rest of short aligned case
lduh [%i0+4],%o2
lduh [%i0+6],%o3
sth %o0,[%fp-8]
sth %o1,[%fp-6]
sth %o2,[%fp-4]
sth %o3,[%fp-2]
ldd [%fp-8],%f0 ! load f0-f1, done
ret
restore
1:
ld [%i0+4],%f1 ! rest of long aligned case
ret
restore
!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
! int st_int(x,p)
! int x;
! char *p;
! {
! /* store 32-bit int from misaligned address;
! return stored value */
! }
!
RTENTRY(st_int)
andcc %o1,1,%g0 ! test for short alignment
be,a 1f
srl %o0,16,%o4
!
srl %o0,24,%o5 ! byte aligned case
stb %o5,[%o1]
srl %o0,16,%o2
stb %o2,[%o1+1]
srl %o0,8,%o3
stb %o3,[%o1+2]
retl
stb %o0,[%o1+3]
1:
sth %o4,[%o1] ! rest of short aligned case
retl
sth %o0,[%o1+2]
!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
! float st_float(x,p)
! float x;
! char *p;
! {
! /* store 32-bit float from misaligned address;
! return stored value */
! }
!
RTENTRY(st_float)
save %sp,-SA(MINFRAME+8),%sp
andcc %i1,1,%g0 ! test for short alignment
be,a 1f ! short aligned case
srl %i0,16,%o0
!
srl %i0,24,%o0 ! byte aligned case
srl %i0,16,%o1
srl %i0,8,%o2
stb %o0,[%i1]
stb %o1,[%i1+1]
stb %o2,[%i1+2]
stb %i0,[%i1+3]
st %i0,[%fp-4] ! store temp, load f0, done
ld [%fp-4],%f0
ret
restore
1:
sth %o0,[%i1] ! rest of short aligned case
sth %i0,[%i1+2]
st %i0,[%fp-4]
ld [%fp-4],%f0
ret
restore
!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
! double st_double(x,p)
! double x;
! char *p;
! {
! /* store 64-bit float from misaligned address;
! return stored value */
! }
!
RTENTRY(st_double)
save %sp,-SA(MINFRAME+8),%sp
andcc %i2,3,%g0 ! test for long alignment
be,a 1f ! long aligned case: 2 stores, 2 loads
st %i0,[%i2]
!
andcc %i2,1,%g0 ! test for short alignment
be,a 2f ! short aligned case: 4 stores, 4 loads
srl %i0,16,%o0
! ! byte aligned case: the pits
srl %i0,24,%o0
srl %i0,16,%o1
srl %i0,8,%o2
stb %o0,[%i2] ! store first word, a byte at a time
stb %o1,[%i2+1]
stb %o2,[%i2+2]
stb %i0,[%i2+3]
srl %i1,24,%o0
srl %i1,16,%o1
srl %i1,8,%o2
stb %o0,[%i2+4] ! store second word, a byte at a time
stb %o1,[%i2+5]
stb %o2,[%i2+6]
stb %i1,[%i2+7]
std %i0,[%fp-8] ! since dest is misaligned, must use temp
ldd [%fp-8],%f0 ! load f0,f1 from double-aligned temp, done
ret
restore
2: ! rest of short aligned case
srl %i1,16,%o1
sth %o0,[%i2] ! store two words, a half word at a time
sth %i0,[%i2+2]
sth %o1,[%i2+4]
sth %i1,[%i2+6]
std %i0,[%fp-8] ! since dest is misaligned, must use temp
ldd [%fp-8],%f0 ! load f0,f1 from double-aligned temp, done
ret
restore
1: ! rest of long aligned case
st %i1,[%i2+4]
ld [%i2],%f0 ! load f0,f1 from long-aligned memory, done
ld [%i2+4],%f1
ret
restore
!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
! void st_float_foreff(x,p)
! float x;
! char *p;
! {
! /* store 32-bit float from misaligned address */
! }
!
RTENTRY(st_float_foreff)
andcc %o1,1,%g0 ! test for short alignment
be,a 1f
srl %o0,16,%o2
!
srl %o0,24,%o2 ! byte aligned case
srl %o0,16,%o3
srl %o0,8,%o4
stb %o2,[%o1]
stb %o3,[%o1+1]
stb %o4,[%o1+2]
retl
stb %o0,[%o1+3]
1: ! rest of short aligned case
sth %o2,[%o1]
retl
sth %o0,[%o1+2]
!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
! void st_double_foreff(x,p)
! double x;
! char *p;
! {
! /* store 64-bit float from misaligned address;
! return stored value */
! }
!
RTENTRY(st_double_foreff)
andcc %o2,3,%g0 ! test for long alignment
be,a 1f ! long aligned case: 2 stores
st %o0,[%o2]
!
andcc %o2,1,%g0 ! test for short alignment
be,a 2f ! short aligned case: 4 stores
srl %o0,16,%o3
!
srl %o0,24,%o3 ! byte aligned case: 8 stores
srl %o0,16,%o4
srl %o0,8,%o5
stb %o3,[%o2]
stb %o4,[%o2+1]
stb %o5,[%o2+2]
stb %o0,[%o2+3]
srl %o1,24,%o3
srl %o1,16,%o4
srl %o1,8,%o5
stb %o3,[%o2+4]
stb %o4,[%o2+5]
stb %o5,[%o2+6]
retl
stb %o1,[%o2+7]
2: ! rest of short aligned case
srl %o1,16,%o4
sth %o3,[%o2]
sth %o0,[%o2+2]
sth %o4,[%o2+4]
retl
sth %o1,[%o2+6]
1: ! rest of long aligned case
retl
st %o1,[%o2+4]