summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/mpc55xx/misc/copy.S
blob: ef529d6e4b03bde373b9c72b10617ef92438935d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**
 * @file
 *
 * @ingroup mpc55xx_asm
 *
 * @brief Memory copy and zero functions.
 */

/*
 * Copyright (c) 2008
 * Embedded Brains GmbH
 * Obere Lagerstr. 30
 * D-82178 Puchheim
 * Germany
 * rtems@embedded-brains.de
 *
 * The license and distribution terms for this file may be found in the file
 * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
 */

#include <libcpu/powerpc-utility.h>

.section ".text"

/**
 * @fn int mpc55xx_copy_8( const void *src, void *dest, size_t n)
 *
 * @brief Copy @a n bytes from @a src to @a dest with 8 byte reads and writes.
 *
 * The memory areas should not overlap.  The addresses @a src and @a dest have
 * to be aligned on 8 byte boundaries.  The size @a n must be evenly divisible by 8.
 * The SPE operations @b evxor, @b evlddx and @b evstddx will be used.
 */
GLOBAL_FUNCTION mpc55xx_copy_8
	/* Loop counter = data size / 8 */
	srwi. r5, r5, 3
	beqlr
	mtctr r5

	/* Set offset */
	evxor r5, r5, r5

copy_data:
	evlddx r6, r3, r5
	evstddx r6, r4, r5
	addi r5, r5, 8
	bdnz copy_data

	/* Return */
	blr

/**
 * @fn int mpc55xx_zero_8( void *dest, size_t n)
 *
 * @brief Zero all @a n bytes starting at @a dest with 8 byte writes.
 *
 * The address @a dest has to be aligned on 8 byte boundaries.  The size @a n
 * must be evenly divisible by 8.  The SPE operations @b evxor and @b evstddx will be used.
 */
GLOBAL_FUNCTION mpc55xx_zero_8
	/* Create zero */
	evxor r0, r0, r0

	/* Set offset */
	evxor r5, r5, r5

	/* Loop counter for the first bytes up to 32 bytes */
	rlwinm. r9, r4, 29, 30, 31
	beq zero_more
	mtctr r9

zero_data:
	evstddx r0, r3, r5
	addi r5, r5, 8
	bdnz zero_data

zero_more:
	/* More than 32 bytes? */
	srwi. r9, r4, 5
	beqlr
	mtctr r9

	/* Set offsets */
	addi r6, r5, 8
	addi r7, r5, 16
	addi r8, r5, 24

zero_big_data:
	evstddx r0, r3, r5
	addi r5, r5, 32
	evstddx r0, r3, r6
	addi r6, r6, 32
	evstddx r0, r3, r7
	addi r7, r7, 32
	evstddx r0, r3, r8
	addi r8, r8, 32
	bdnz zero_big_data
	
	/* Return */
	blr

/**
 * @fn int mpc55xx_zero_32( void *dest, size_t n)
 *
 * @brief Zero all @a n bytes starting at @a dest with 32 byte writes.
 *
 * The address @a dest has to be aligned on 32 byte boundaries.  The size @a n
 * must be evenly divisible by 32.  The function operates with the cache block zero
 * operation @b dcbz.
 *
 * @note The cache has to be enabled for the desired memory area.
 */
GLOBAL_FUNCTION mpc55xx_zero_32
	/* Set offset */
	xor r5, r5, r5

	/* Loop counter for the first bytes up to 128 bytes */
	rlwinm. r9, r4, 27, 28, 31
	beq zero_more_lines
	mtctr r9

zero_line:
	dcbz r3, r5
	addi r5, r5, 32
	bdnz zero_line

zero_more_lines:
	/* More than 128 bytes? */
	srwi. r9, r4, 7
	beqlr
	mtctr r9

	/* Set offsets */
	addi r6, r5, 32
	addi r7, r5, 64
	addi r8, r5, 96

zero_big_line:
	dcbz r3, r5
	addi r5, r5, 128
	dcbz r3, r6
	addi r6, r6, 128
	dcbz r3, r7
	addi r7, r7, 128
	dcbz r3, r8
	addi r8, r8, 128
	bdnz zero_big_line
	
	/* Return */
	blr