#include "SYS.h"
#define SRCREG a1
#define DSTREG a0
#define SIZEREG a2
LEAF(memmove,3)
mov DSTREG,v0
beq SIZEREG,bcopy_done
subq DSTREG,SRCREG,t5
cmpult t5,SIZEREG,t5
bne t5,bcopy_overlap
addq SRCREG,SIZEREG,a3
ldq_u t2,0(SRCREG)
xor SRCREG,DSTREG,t0
and t0,7,t0
and DSTREG,7,t1
bne t0,bcopy_different_alignment
beq t1,bcopy_all_aligned
ldq_u t3,0(DSTREG)
addq SIZEREG,t1,SIZEREG
mskqh t2,SRCREG,t2
mskql t3,SRCREG,t3
or t2,t3,t2
bcopy_all_aligned:
subq SIZEREG,1,t0
and SIZEREG,7,SIZEREG
bic t0,7,t0
beq t0,bcopy_samealign_lp_end
bcopy_samealign_lp:
stq_u t2,0(DSTREG)
addq DSTREG,8,DSTREG
ldq_u t2,8(SRCREG)
subq t0,8,t0
addq SRCREG,8,SRCREG
bne t0,bcopy_samealign_lp
bcopy_samealign_lp_end:
bne SIZEREG,bcopy_small_left
stq_u t2,0(DSTREG)
RET
bcopy_small_left:
mskql t2,SIZEREG,t4
ldq_u t3,0(DSTREG)
mskqh t3,SIZEREG,t3
or t4,t3,t4
stq_u t4,0(DSTREG)
RET
bcopy_different_alignment:
addq SRCREG,SIZEREG,a3
cmpule SIZEREG,8,t0
bne t0,bcopy_da_finish
beq t1,bcopy_da_noentry
subq zero,DSTREG,t0
and t0,7,t0
ldq_u t3,7(SRCREG)
extql t2,SRCREG,t2
extqh t3,SRCREG,t3
or t2,t3,t5
insql t5,DSTREG,t5
ldq_u t6,0(DSTREG)
mskql t6,DSTREG,t6
or t5,t6,t5
stq_u t5,0(DSTREG)
addq SRCREG,t0,SRCREG
addq DSTREG,t0,DSTREG
subq SIZEREG,t0,SIZEREG
ldq_u t2,0(SRCREG)
bcopy_da_noentry:
subq SIZEREG,1,t0
bic t0,7,t0
and SIZEREG,7,SIZEREG
beq t0,bcopy_da_finish2
bcopy_da_lp:
ldq_u t3,7(SRCREG)
addq SRCREG,8,SRCREG
extql t2,SRCREG,t4
extqh t3,SRCREG,t5
subq t0,8,t0
or t4,t5,t5
stq t5,0(DSTREG)
addq DSTREG,8,DSTREG
beq t0,bcopy_da_finish1
ldq_u t2,7(SRCREG)
addq SRCREG,8,SRCREG
extql t3,SRCREG,t4
extqh t2,SRCREG,t5
subq t0,8,t0
or t4,t5,t5
stq t5,0(DSTREG)
addq DSTREG,8,DSTREG
bne t0,bcopy_da_lp
bcopy_da_finish2:
mov t2,t3
bcopy_da_finish1:
ldq_u t2,-1(a3)
extql t3,SRCREG,t3
extqh t2,SRCREG,t2
or t2,t3,t2
br zero,bcopy_samealign_lp_end
bcopy_da_finish:
ldq_u t3,-1(a3)
extql t2,SRCREG,t2
extqh t3,SRCREG,t3
or t2,t3,t2
insqh t2,DSTREG,t3
insql t2,DSTREG,t2
lda t4,-1(zero)
mskql t4,SIZEREG,t5
cmovne t5,t5,t4
insqh t4,DSTREG,t5
insql t4,DSTREG,t4
addq DSTREG,SIZEREG,a4
ldq_u t6,0(DSTREG)
ldq_u t7,-1(a4)
bic t6,t4,t6
bic t7,t5,t7
and t2,t4,t2
and t3,t5,t3
or t2,t6,t2
or t3,t7,t3
stq_u t3,-1(a4)
stq_u t2,0(DSTREG)
RET
bcopy_overlap:
addq SRCREG,SIZEREG,a3
addq DSTREG,SIZEREG,a4
cmpule SIZEREG,8,t0
bne t0,bcopy_ov_short
and a4,7,t4
beq t4,bcopy_ov_nostart2
subq a3,t4,a3
subq a4,t4,a4
ldq_u t1,0(a3)
subq SIZEREG,t4,SIZEREG
ldq_u t2,7(a3)
ldq t3,0(a4)
extql t1,a3,t1
extqh t2,a3,t2
or t1,t2,t1
mskqh t3,t4,t3
mskql t1,t4,t1
or t1,t3,t1
stq t1,0(a4)
bcopy_ov_nostart2:
bic SIZEREG,7,t4
and SIZEREG,7,SIZEREG
beq t4,bcopy_ov_lp_end
bcopy_ov_lp:
ldq_u t0,-8(a3)
subq a4,8,a4
ldq_u t1,-1(a3)
subq a3,8,a3
extql t0,a3,t0
extqh t1,a3,t1
subq t4,8,t4
or t0,t1,t0
stq t0,0(a4)
bne t4,bcopy_ov_lp
bcopy_ov_lp_end:
beq SIZEREG,bcopy_done
ldq_u t0,0(SRCREG)
ldq_u t1,7(SRCREG)
ldq_u t2,0(DSTREG)
extql t0,SRCREG,t0
extqh t1,SRCREG,t1
or t0,t1,t0
insql t0,DSTREG,t0
mskql t2,DSTREG,t2
or t2,t0,t2
stq_u t2,0(DSTREG)
bcopy_done:
RET
bcopy_ov_short:
ldq_u t2,0(SRCREG)
br zero,bcopy_da_finish
END_STRONG(memmove)