blob: 572c36c8816aed446aa478d00ccb7cbf4b498187 [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
Leon Clarkef7060e22010-06-03 12:02:55 +010030#if defined(V8_TARGET_ARCH_IA32)
31
Ben Murdoch8b112d22011-06-08 16:22:53 +010032#include "codegen.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033
34namespace v8 {
35namespace internal {
36
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010037
38// -------------------------------------------------------------------------
39// Platform-specific RuntimeCallHelper functions.
40
Ben Murdochb0fe1622011-05-05 13:52:32 +010041void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010042 masm->EnterInternalFrame();
43}
44
45
Ben Murdochb0fe1622011-05-05 13:52:32 +010046void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010047 masm->LeaveInternalFrame();
48}
49
50
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010051#define __ masm.
52
Ben Murdochb0fe1622011-05-05 13:52:32 +010053static void MemCopyWrapper(void* dest, const void* src, size_t size) {
54 memcpy(dest, src, size);
55}
56
57
Ben Murdoch8b112d22011-06-08 16:22:53 +010058OS::MemCopyFunction CreateMemCopyFunction() {
59 size_t actual_size;
60 // Allocate buffer in executable space.
61 byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB,
62 &actual_size,
63 true));
64 if (buffer == NULL) return &MemCopyWrapper;
65 MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010066
67 // Generated code is put into a fixed, unmovable, buffer, and not into
68 // the V8 heap. We can't, and don't, refer to any relocatable addresses
69 // (e.g. the JavaScript nan-object).
70
71 // 32-bit C declaration function calls pass arguments on stack.
72
73 // Stack layout:
74 // esp[12]: Third argument, size.
75 // esp[8]: Second argument, source pointer.
76 // esp[4]: First argument, destination pointer.
77 // esp[0]: return address
78
79 const int kDestinationOffset = 1 * kPointerSize;
80 const int kSourceOffset = 2 * kPointerSize;
81 const int kSizeOffset = 3 * kPointerSize;
82
83 int stack_offset = 0; // Update if we change the stack height.
84
85 if (FLAG_debug_code) {
86 __ cmp(Operand(esp, kSizeOffset + stack_offset),
Ben Murdoch8b112d22011-06-08 16:22:53 +010087 Immediate(OS::kMinComplexMemCopy));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010088 Label ok;
89 __ j(greater_equal, &ok);
90 __ int3();
91 __ bind(&ok);
92 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010093 if (CpuFeatures::IsSupported(SSE2)) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010094 CpuFeatures::Scope enable(SSE2);
95 __ push(edi);
96 __ push(esi);
97 stack_offset += 2 * kPointerSize;
98 Register dst = edi;
99 Register src = esi;
100 Register count = ecx;
101 __ mov(dst, Operand(esp, stack_offset + kDestinationOffset));
102 __ mov(src, Operand(esp, stack_offset + kSourceOffset));
103 __ mov(count, Operand(esp, stack_offset + kSizeOffset));
104
105
106 __ movdqu(xmm0, Operand(src, 0));
107 __ movdqu(Operand(dst, 0), xmm0);
108 __ mov(edx, dst);
109 __ and_(edx, 0xF);
110 __ neg(edx);
111 __ add(Operand(edx), Immediate(16));
112 __ add(dst, Operand(edx));
113 __ add(src, Operand(edx));
114 __ sub(Operand(count), edx);
115
116 // edi is now aligned. Check if esi is also aligned.
117 Label unaligned_source;
118 __ test(Operand(src), Immediate(0x0F));
119 __ j(not_zero, &unaligned_source);
120 {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100121 // Copy loop for aligned source and destination.
122 __ mov(edx, count);
123 Register loop_count = ecx;
124 Register count = edx;
125 __ shr(loop_count, 5);
126 {
127 // Main copy loop.
128 Label loop;
129 __ bind(&loop);
130 __ prefetch(Operand(src, 0x20), 1);
131 __ movdqa(xmm0, Operand(src, 0x00));
132 __ movdqa(xmm1, Operand(src, 0x10));
133 __ add(Operand(src), Immediate(0x20));
134
135 __ movdqa(Operand(dst, 0x00), xmm0);
136 __ movdqa(Operand(dst, 0x10), xmm1);
137 __ add(Operand(dst), Immediate(0x20));
138
139 __ dec(loop_count);
140 __ j(not_zero, &loop);
141 }
142
143 // At most 31 bytes to copy.
144 Label move_less_16;
145 __ test(Operand(count), Immediate(0x10));
146 __ j(zero, &move_less_16);
147 __ movdqa(xmm0, Operand(src, 0));
148 __ add(Operand(src), Immediate(0x10));
149 __ movdqa(Operand(dst, 0), xmm0);
150 __ add(Operand(dst), Immediate(0x10));
151 __ bind(&move_less_16);
152
153 // At most 15 bytes to copy. Copy 16 bytes at end of string.
154 __ and_(count, 0xF);
155 __ movdqu(xmm0, Operand(src, count, times_1, -0x10));
156 __ movdqu(Operand(dst, count, times_1, -0x10), xmm0);
157
Ben Murdochb0fe1622011-05-05 13:52:32 +0100158 __ mov(eax, Operand(esp, stack_offset + kDestinationOffset));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100159 __ pop(esi);
160 __ pop(edi);
161 __ ret(0);
162 }
163 __ Align(16);
164 {
165 // Copy loop for unaligned source and aligned destination.
166 // If source is not aligned, we can't read it as efficiently.
167 __ bind(&unaligned_source);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100168 __ mov(edx, ecx);
169 Register loop_count = ecx;
170 Register count = edx;
171 __ shr(loop_count, 5);
172 {
173 // Main copy loop
174 Label loop;
175 __ bind(&loop);
176 __ prefetch(Operand(src, 0x20), 1);
177 __ movdqu(xmm0, Operand(src, 0x00));
178 __ movdqu(xmm1, Operand(src, 0x10));
179 __ add(Operand(src), Immediate(0x20));
180
181 __ movdqa(Operand(dst, 0x00), xmm0);
182 __ movdqa(Operand(dst, 0x10), xmm1);
183 __ add(Operand(dst), Immediate(0x20));
184
185 __ dec(loop_count);
186 __ j(not_zero, &loop);
187 }
188
189 // At most 31 bytes to copy.
190 Label move_less_16;
191 __ test(Operand(count), Immediate(0x10));
192 __ j(zero, &move_less_16);
193 __ movdqu(xmm0, Operand(src, 0));
194 __ add(Operand(src), Immediate(0x10));
195 __ movdqa(Operand(dst, 0), xmm0);
196 __ add(Operand(dst), Immediate(0x10));
197 __ bind(&move_less_16);
198
199 // At most 15 bytes to copy. Copy 16 bytes at end of string.
200 __ and_(count, 0x0F);
201 __ movdqu(xmm0, Operand(src, count, times_1, -0x10));
202 __ movdqu(Operand(dst, count, times_1, -0x10), xmm0);
203
Ben Murdochb0fe1622011-05-05 13:52:32 +0100204 __ mov(eax, Operand(esp, stack_offset + kDestinationOffset));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100205 __ pop(esi);
206 __ pop(edi);
207 __ ret(0);
208 }
209
210 } else {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100211 // SSE2 not supported. Unlikely to happen in practice.
212 __ push(edi);
213 __ push(esi);
214 stack_offset += 2 * kPointerSize;
215 __ cld();
216 Register dst = edi;
217 Register src = esi;
218 Register count = ecx;
219 __ mov(dst, Operand(esp, stack_offset + kDestinationOffset));
220 __ mov(src, Operand(esp, stack_offset + kSourceOffset));
221 __ mov(count, Operand(esp, stack_offset + kSizeOffset));
222
223 // Copy the first word.
224 __ mov(eax, Operand(src, 0));
225 __ mov(Operand(dst, 0), eax);
226
227 // Increment src,dstso that dst is aligned.
228 __ mov(edx, dst);
229 __ and_(edx, 0x03);
230 __ neg(edx);
231 __ add(Operand(edx), Immediate(4)); // edx = 4 - (dst & 3)
232 __ add(dst, Operand(edx));
233 __ add(src, Operand(edx));
234 __ sub(Operand(count), edx);
235 // edi is now aligned, ecx holds number of remaning bytes to copy.
236
237 __ mov(edx, count);
238 count = edx;
239 __ shr(ecx, 2); // Make word count instead of byte count.
240 __ rep_movs();
241
242 // At most 3 bytes left to copy. Copy 4 bytes at end of string.
243 __ and_(count, 3);
244 __ mov(eax, Operand(src, count, times_1, -4));
245 __ mov(Operand(dst, count, times_1, -4), eax);
246
Ben Murdochb0fe1622011-05-05 13:52:32 +0100247 __ mov(eax, Operand(esp, stack_offset + kDestinationOffset));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100248 __ pop(esi);
249 __ pop(edi);
250 __ ret(0);
251 }
252
253 CodeDesc desc;
254 masm.GetCode(&desc);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100255 ASSERT(desc.reloc_size == 0);
256
Ben Murdoch8b112d22011-06-08 16:22:53 +0100257 CPU::FlushICache(buffer, actual_size);
258 return FUNCTION_CAST<OS::MemCopyFunction>(buffer);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100259}
260
261#undef __
262
Steve Blocka7e24c12009-10-30 11:49:00 +0000263} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +0100264
265#endif // V8_TARGET_ARCH_IA32