xref: /plan9-contrib/sys/src/libc/amd64/memcpy.s (revision 272efad760864ee41cfe633b56aea9b4f5cf3ae7)
1*272efad7SDavid du ColombierTEXT memcpy(SB), $0
2*272efad7SDavid du Colombier	MOVQ	RARG, DI
3*272efad7SDavid du Colombier	MOVQ	DI, AX			/* return value */
4*272efad7SDavid du Colombier	MOVQ	p2+8(FP), SI
5*272efad7SDavid du Colombier	MOVL	n+16(FP), BX
6*272efad7SDavid du Colombier	CMPL	BX, $0
7*272efad7SDavid du Colombier	JGT	_ok
8*272efad7SDavid du Colombier	JEQ	_return			/* nothing to do if n == 0 */
9*272efad7SDavid du Colombier	MOVL	$0, SI			/* fault if n < 0 */
10*272efad7SDavid du Colombier
11*272efad7SDavid du Colombier/*
12*272efad7SDavid du Colombier * check and set for backwards:
13*272efad7SDavid du Colombier *	(p2 < p1) && ((p2+n) > p1)
14*272efad7SDavid du Colombier */
15*272efad7SDavid du Colombier_ok:
16*272efad7SDavid du Colombier	CMPQ	SI, DI
17*272efad7SDavid du Colombier	JGT	_forward
18*272efad7SDavid du Colombier	JEQ	_return			/* nothing to do if p2 == p1 */
19*272efad7SDavid du Colombier	MOVQ	SI, DX
20*272efad7SDavid du Colombier	ADDQ	BX, DX
21*272efad7SDavid du Colombier	CMPQ	DX, DI
22*272efad7SDavid du Colombier	JGT	_back
23*272efad7SDavid du Colombier
24*272efad7SDavid du Colombier/*
25*272efad7SDavid du Colombier * copy whole longs if aligned
26*272efad7SDavid du Colombier */
27*272efad7SDavid du Colombier_forward:
28*272efad7SDavid du Colombier	CLD
29*272efad7SDavid du Colombier	MOVQ	SI, DX
30*272efad7SDavid du Colombier	ORQ	DI, DX
31*272efad7SDavid du Colombier	ANDL	$3, DX
32*272efad7SDavid du Colombier	JNE	c3f
33*272efad7SDavid du Colombier	MOVQ	BX, CX
34*272efad7SDavid du Colombier	SHRQ	$2, CX
35*272efad7SDavid du Colombier	ANDL	$3, BX
36*272efad7SDavid du Colombier	REP;	MOVSL
37*272efad7SDavid du Colombier
38*272efad7SDavid du Colombier/*
39*272efad7SDavid du Colombier * copy the rest, by bytes
40*272efad7SDavid du Colombier */
41*272efad7SDavid du Colombier	JEQ	_return			/* flags set by above ANDL */
42*272efad7SDavid du Colombierc3f:
43*272efad7SDavid du Colombier	MOVL	BX, CX
44*272efad7SDavid du Colombier	REP;	MOVSB
45*272efad7SDavid du Colombier
46*272efad7SDavid du Colombier	RET
47*272efad7SDavid du Colombier
48*272efad7SDavid du Colombier/*
49*272efad7SDavid du Colombier * whole thing backwards has
50*272efad7SDavid du Colombier * adjusted addresses
51*272efad7SDavid du Colombier */
52*272efad7SDavid du Colombier_back:
53*272efad7SDavid du Colombier	ADDQ	BX, DI
54*272efad7SDavid du Colombier	ADDQ	BX, SI
55*272efad7SDavid du Colombier	STD
56*272efad7SDavid du Colombier	SUBQ	$4, DI
57*272efad7SDavid du Colombier	SUBQ	$4, SI
58*272efad7SDavid du Colombier/*
59*272efad7SDavid du Colombier * copy whole longs, if aligned
60*272efad7SDavid du Colombier */
61*272efad7SDavid du Colombier	MOVQ	DI, DX
62*272efad7SDavid du Colombier	ORQ	SI, DX
63*272efad7SDavid du Colombier	ANDL	$3, DX
64*272efad7SDavid du Colombier	JNE	c3b
65*272efad7SDavid du Colombier	MOVL	BX, CX
66*272efad7SDavid du Colombier	SHRQ	$2, CX
67*272efad7SDavid du Colombier	ANDL	$3, BX
68*272efad7SDavid du Colombier	REP;	MOVSL
69*272efad7SDavid du Colombier/*
70*272efad7SDavid du Colombier * copy the rest, by bytes
71*272efad7SDavid du Colombier */
72*272efad7SDavid du Colombier	JEQ	_return			/* flags set by above ANDL */
73*272efad7SDavid du Colombier
74*272efad7SDavid du Colombierc3b:
75*272efad7SDavid du Colombier	ADDQ	$3, DI
76*272efad7SDavid du Colombier	ADDQ	$3, SI
77*272efad7SDavid du Colombier	MOVL	BX, CX
78*272efad7SDavid du Colombier	REP;	MOVSB
79*272efad7SDavid du Colombier
80*272efad7SDavid du Colombier_return:
81*272efad7SDavid du Colombier	RET
82