summaryrefslogtreecommitdiff
path: root/arch/x64/linux/memory/fill.S
blob: 2717aa1c2323165af55706ab1d27bf7558ae4dc2 (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
	.text

/*
 * fillMemory.
 *
 * rdi - length.
 * rsi - pointer.
 * rdx - value filled with a byte.
 */
	.globl _D5tanya6memory2op10fillMemoryFNaNbNiAvmZv
	.type _D5tanya6memory2op10fillMemoryFNaNbNiAvmZv, @function

_D5tanya6memory2op10fillMemoryFNaNbNiAvmZv:
		// Check for zero length
		test    %rdi, %rdi
		jz end

		mov     %rdi, %rax
		mov     %rsi, %r8

		movq    %rdx,  %xmm0
		movlhps %xmm0, %xmm0

		// Check if the pointer is aligned to a 16-byte boundary
		and     $-0x10, %r8

		// Compute the number of misaligned bytes
		mov  %rsi, %r9
		sub  %r8,  %r9

		test %r9,  %r9
		jz aligned

		// Get the number of bytes to be written until we are aligned
		mov $0x10, %rcx
		sub %r9,   %rcx

		mov %rsi,  %r8

		// If the length is less than the number of misaligned bytes,
		// write one byte at a time and exit
		cmp %rax, %rcx
		jg aligned_1

	naligned:
		mov %dl, (%r8) // Write a byte

		// Advance the pointer. Decrease the total number of bytes
		// and the misaligned ones
		inc %r8
		dec %rcx
		dec %rax

		// Checks if we are aligned
		test %rcx, %rcx
		jnz naligned

	aligned:
		// Checks if we're done writing bytes
		test %rax, %rax
		jz end

		// Write 1 byte at a time
		cmp $8, %rax
		jl aligned_1

		// Write 8 bytes at a time
		cmp $16, %rax
		jl aligned_8

		// Write 16 bytes at a time
		cmp $32, %rax
		jl aligned_16

		// Write 32 bytes at a time
		cmp $64, %rax
		jl aligned_32

	aligned_64:
		movdqa %xmm0, (%r8)
		movdqa %xmm0, 16(%r8)
		movdqa %xmm0, 32(%r8)
		movdqa %xmm0, 48(%r8)

		add $64, %r8
		sub $64, %rax

		cmp $64, %rax
		jge aligned_64

		// Checks if we're done writing bytes
		test %rax, %rax
		jz end

		// Write 1 byte at a time
		cmp $8, %rax
		jl aligned_1

		// Write 8 bytes at a time
		cmp $16, %rax
		jl aligned_8

		// Write 16 bytes at a time
		cmp $32, %rax
		jl aligned_16

	aligned_32:
		movdqa %xmm0, (%r8)
		movdqa %xmm0, 16(%r8)

		add $32, %r8
		sub $32, %rax

		// Checks if we're done writing bytes
		test %rax, %rax
		jz end

		// Write 1 byte at a time
		cmp $8, %rax
		jl aligned_1

		// Write 8 bytes at a time
		cmp $16, %rax
		jl aligned_8

	aligned_16:
		movdqa %xmm0, (%r8)

		add $16, %r8
		sub $16, %rax

		// Checks if we're done writing bytes
		test %rax, %rax
		jz end

		// Write 1 byte at a time
		cmp $8, %rax
		jl aligned_1

	aligned_8:
		mov %rdx, (%r8)

		add $8, %r8
		sub $8, %rax

		// Checks if we're done writing bytes
		test %rax, %rax
		jz end

	aligned_1:
		mov %dl, (%r8)

		inc %r8
		dec %rax

		test %rax, %rax
		jnz aligned_1

	end:
		ret