summaryrefslogtreecommitdiffstats
path: root/sys/mips/rmi/xlr_csum_nocopy.S
blob: 8b51a7f10f1cc6600eee01dd913fee745dec2b6a (plain)
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#include <machine/asm.h>


/*
 * a0: source address
 * a1: length of the area to checksum
 * a2: partial checksum
 * a3: dst
 */

#define src a0
#define dst a3
#define sum v0

	.text
	.set	noreorder

	.macro CSUM_BIGCHUNK_AND_COPY offset 
	pref                    0,  (\offset+0x0)(a0)
	ld			t0, (\offset+0x00)(a0)
	ld			t1, (\offset+0x08)(a0)
	.word			0x70481038  /*daddwc v0, v0, t0 */
	.word			0x70491038 /*daddwc v0, v0, t1 */
	ld			t0, (\offset + 0x10)(a0)		
	ld			t1, (\offset + 0x18)(a0)	
	.word			0x70481038 /* daddwc v0, v0, t0 */
	.word			0x70491038 /*daddwc v0, v0, t1 */
	.endm

small_csumcpy: 						/* unknown src alignment and < 8 bytes to go  */
	move 		a1, t2

	andi		t0, a1, 4
	beqz		t0, 1f
	andi		t0, a1, 2

	ulw			t1, (src) 			/* Still a full word to go  */
	daddiu		src, 4
	.word			0x70491038 /*daddwc v0, v0, t1 */

1:	move		t1, zero
	beqz		t0, 1f
	andi		t0, a1, 1

	ulhu		t1, (src) 			/* Still a halfword to go  */
	daddiu		src, 2

1:	beqz		t0, 1f
	sll			t1, t1, 16

	lbu			t2, (src)
	nop

#ifdef __MIPSEB__
	sll		t2, t2, 8
#endif
	or		t1, t2

1: 	.word			0x70491038 /*daddwc v0, v0, t1 */

	.word			0x70461038 /*daddwc v0, v0, a2 */
	.word			0x70401038 /*daddwc v0, v0, $0 */

	/* Ideally at this point of time the status flag must be cleared */
					
	dsll32      v1, sum, 0
	.word			0x70431038 /*daddwc v0, v0, v1 */
	dsrl32		sum, sum, 0
	.word			0x70401038 /*daddwc v0, v0, zero */

	/* fold the checksum */
	sll             v1, sum, 16
	addu            sum, v1
	sltu            v1, sum, v1
	srl             sum, sum, 16
	addu            sum, v1
1:
	.set		reorder
	jr			ra
	.set		noreorder

/* ------------------------------------------------------------------ */

	.align	5
LEAF(xlr_csum_partial_nocopy)
	move		sum, zero
	move		t7, zero

	sltiu		t8, a1, 0x8
	bnez		t8, small_csumcpy		/* < 8 bytes to copy */
	move		t2, a1

	beqz		a1, out
	andi		t7, src, 0x1			/* odd buffer? */

hword_align:
	beqz		t7, word_align
	andi		t8, src, 0x2

	lbu			t0, (src)
	dsubu		a1, a1, 0x1
	.word			0x70481038 /*daddwc v0, v0, t0 */
	daddu		src, src, 0x1
	andi		t8, src, 0x2

word_align:
	beqz		t8, dword_align
	sltiu		t8, a1, 56

	lhu			t0, (src)
	dsubu		a1, a1, 0x2
	.word			0x70481038 /*daddwc v0, v0, t0 */
	sltiu		t8, a1, 56
	daddu		src, src, 0x2

dword_align:
	bnez		t8, do_end_words
	move		t8, a1

	andi		t8, src, 0x4
	beqz		t8, qword_align
	andi		t8, src, 0x8

	lw			t0, 0x00(src)
	dsubu		a1, a1, 0x4
	.word			0x70481038 /*daddwc v0, v0, t0 */
	daddu		src, src, 0x4
	andi		t8, src, 0x8

qword_align:
	beqz		t8, oword_align
	andi		t8, src, 0x10

	ld			t0, 0x00(src)
	dsubu		a1, a1, 0x8
	.word			0x70481038 /*daddwc v0, v0, t0 */
	daddu		src, src, 0x8
	andi		t8, src, 0x10

oword_align:
	beqz		t8, begin_movement
	dsrl		t8, a1, 0x7

	ld			t3, 0x08(src)
	ld			t0, 0x00(src)
	.word			0x704b1038 /*daddwc v0, v0, t3 */
	.word			0x70481038 /*daddwc v0, v0, t0 */
	dsubu		a1, a1, 0x10
	daddu		src, src, 0x10
	dsrl		t8, a1, 0x7

begin_movement:
	beqz		t8, 1f
	andi		t2, a1, 0x40

move_128bytes:
	pref		0, 0x20(a0)
	pref		0, 0x40(a0)
	pref		0, 0x60(a0)
	CSUM_BIGCHUNK_AND_COPY(0x00)
	CSUM_BIGCHUNK_AND_COPY(0x20)
	CSUM_BIGCHUNK_AND_COPY(0x40)
	CSUM_BIGCHUNK_AND_COPY(0x60)
	dsubu		t8, t8, 0x01
	bnez		t8, move_128bytes	/* flag */
	daddu		src, src, 0x80

1:
	beqz		t2, 1f
	andi		t2, a1, 0x20

move_64bytes:
	pref		0, 0x20(a0)
	pref		0, 0x40(a0)
	CSUM_BIGCHUNK_AND_COPY(0x00)
	CSUM_BIGCHUNK_AND_COPY(0x20)
	daddu	src, src, 0x40

1:
	beqz		t2, do_end_words
	andi		t8, a1, 0x1c

move_32bytes:
	pref		0, 0x20(a0)
	CSUM_BIGCHUNK_AND_COPY(0x00)
	andi		t8, a1, 0x1c
	daddu		src, src, 0x20

do_end_words:
	beqz		t8, maybe_end_cruft
	dsrl		t8, t8, 0x2

end_words:
	lw			t0, (src)
	dsubu		t8, t8, 0x1
	.word			0x70481038 /*daddwc v0, v0, t0 */
	bnez		t8, end_words
	daddu		src, src, 0x4

maybe_end_cruft:
	andi		t2, a1, 0x3

small_memcpy:
 j small_csumcpy; move a1, t2
	beqz		t2, out
	move		a1, t2

end_bytes:
	lb			t0, (src)
	dsubu		a1, a1, 0x1
	bnez		a2, end_bytes
	daddu		src, src, 0x1

out:
	jr			ra
	move		v0, sum
	END(xlr_csum_partial_nocopy)
OpenPOWER on IntegriCloud