| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include <stdlib.h> | 28 #include <stdlib.h> |
| 29 | 29 |
| 30 #include "src/v8.h" | 30 #include "src/v8.h" |
| 31 | 31 |
| 32 #include "src/base/platform/platform.h" |
| 32 #include "src/factory.h" | 33 #include "src/factory.h" |
| 33 #include "src/macro-assembler.h" | 34 #include "src/macro-assembler.h" |
| 34 #include "src/platform.h" | |
| 35 #include "src/serialize.h" | 35 #include "src/serialize.h" |
| 36 #include "test/cctest/cctest.h" | 36 #include "test/cctest/cctest.h" |
| 37 | 37 |
| 38 using namespace v8::internal; | 38 using namespace v8::internal; |
| 39 | 39 |
| 40 // Test the x64 assembler by compiling some simple functions into | 40 // Test the x64 assembler by compiling some simple functions into |
| 41 // a buffer and executing them. These tests do not initialize the | 41 // a buffer and executing them. These tests do not initialize the |
| 42 // V8 library, create a context, or use any V8 objects. | 42 // V8 library, create a context, or use any V8 objects. |
| 43 // The AMD64 calling convention is used, with the first six arguments | 43 // The AMD64 calling convention is used, with the first six arguments |
| 44 // in RDI, RSI, RDX, RCX, R8, and R9, and floating point arguments in | 44 // in RDI, RSI, RDX, RCX, R8, and R9, and floating point arguments in |
| (...skipping 17 matching lines...) Expand all Loading... |
| 62 static const Register arg2 = rsi; | 62 static const Register arg2 = rsi; |
| 63 #endif | 63 #endif |
| 64 | 64 |
| 65 #define __ assm. | 65 #define __ assm. |
| 66 | 66 |
| 67 | 67 |
| 68 TEST(AssemblerX64ReturnOperation) { | 68 TEST(AssemblerX64ReturnOperation) { |
| 69 CcTest::InitializeVM(); | 69 CcTest::InitializeVM(); |
| 70 // Allocate an executable page of memory. | 70 // Allocate an executable page of memory. |
| 71 size_t actual_size; | 71 size_t actual_size; |
| 72 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 72 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 73 &actual_size, | 73 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 74 true)); | |
| 75 CHECK(buffer); | 74 CHECK(buffer); |
| 76 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 75 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 77 | 76 |
| 78 // Assemble a simple function that copies argument 2 and returns it. | 77 // Assemble a simple function that copies argument 2 and returns it. |
| 79 __ movq(rax, arg2); | 78 __ movq(rax, arg2); |
| 80 __ nop(); | 79 __ nop(); |
| 81 __ ret(0); | 80 __ ret(0); |
| 82 | 81 |
| 83 CodeDesc desc; | 82 CodeDesc desc; |
| 84 assm.GetCode(&desc); | 83 assm.GetCode(&desc); |
| 85 // Call the function from C++. | 84 // Call the function from C++. |
| 86 int result = FUNCTION_CAST<F2>(buffer)(3, 2); | 85 int result = FUNCTION_CAST<F2>(buffer)(3, 2); |
| 87 CHECK_EQ(2, result); | 86 CHECK_EQ(2, result); |
| 88 } | 87 } |
| 89 | 88 |
| 90 | 89 |
| 91 TEST(AssemblerX64StackOperations) { | 90 TEST(AssemblerX64StackOperations) { |
| 92 CcTest::InitializeVM(); | 91 CcTest::InitializeVM(); |
| 93 // Allocate an executable page of memory. | 92 // Allocate an executable page of memory. |
| 94 size_t actual_size; | 93 size_t actual_size; |
| 95 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 94 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 96 &actual_size, | 95 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 97 true)); | |
| 98 CHECK(buffer); | 96 CHECK(buffer); |
| 99 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 97 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 100 | 98 |
| 101 // Assemble a simple function that copies argument 2 and returns it. | 99 // Assemble a simple function that copies argument 2 and returns it. |
| 102 // We compile without stack frame pointers, so the gdb debugger shows | 100 // We compile without stack frame pointers, so the gdb debugger shows |
| 103 // incorrect stack frames when debugging this function (which has them). | 101 // incorrect stack frames when debugging this function (which has them). |
| 104 __ pushq(rbp); | 102 __ pushq(rbp); |
| 105 __ movq(rbp, rsp); | 103 __ movq(rbp, rsp); |
| 106 __ pushq(arg2); // Value at (rbp - 8) | 104 __ pushq(arg2); // Value at (rbp - 8) |
| 107 __ pushq(arg2); // Value at (rbp - 16) | 105 __ pushq(arg2); // Value at (rbp - 16) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 118 // Call the function from C++. | 116 // Call the function from C++. |
| 119 int result = FUNCTION_CAST<F2>(buffer)(3, 2); | 117 int result = FUNCTION_CAST<F2>(buffer)(3, 2); |
| 120 CHECK_EQ(2, result); | 118 CHECK_EQ(2, result); |
| 121 } | 119 } |
| 122 | 120 |
| 123 | 121 |
| 124 TEST(AssemblerX64ArithmeticOperations) { | 122 TEST(AssemblerX64ArithmeticOperations) { |
| 125 CcTest::InitializeVM(); | 123 CcTest::InitializeVM(); |
| 126 // Allocate an executable page of memory. | 124 // Allocate an executable page of memory. |
| 127 size_t actual_size; | 125 size_t actual_size; |
| 128 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 126 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 129 &actual_size, | 127 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 130 true)); | |
| 131 CHECK(buffer); | 128 CHECK(buffer); |
| 132 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 129 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 133 | 130 |
| 134 // Assemble a simple function that adds arguments returning the sum. | 131 // Assemble a simple function that adds arguments returning the sum. |
| 135 __ movq(rax, arg2); | 132 __ movq(rax, arg2); |
| 136 __ addq(rax, arg1); | 133 __ addq(rax, arg1); |
| 137 __ ret(0); | 134 __ ret(0); |
| 138 | 135 |
| 139 CodeDesc desc; | 136 CodeDesc desc; |
| 140 assm.GetCode(&desc); | 137 assm.GetCode(&desc); |
| 141 // Call the function from C++. | 138 // Call the function from C++. |
| 142 int result = FUNCTION_CAST<F2>(buffer)(3, 2); | 139 int result = FUNCTION_CAST<F2>(buffer)(3, 2); |
| 143 CHECK_EQ(5, result); | 140 CHECK_EQ(5, result); |
| 144 } | 141 } |
| 145 | 142 |
| 146 | 143 |
| 147 TEST(AssemblerX64CmpbOperation) { | 144 TEST(AssemblerX64CmpbOperation) { |
| 148 CcTest::InitializeVM(); | 145 CcTest::InitializeVM(); |
| 149 // Allocate an executable page of memory. | 146 // Allocate an executable page of memory. |
| 150 size_t actual_size; | 147 size_t actual_size; |
| 151 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 148 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 152 &actual_size, | 149 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 153 true)); | |
| 154 CHECK(buffer); | 150 CHECK(buffer); |
| 155 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 151 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 156 | 152 |
| 157 // Assemble a function that compare argument byte returing 1 if equal else 0. | 153 // Assemble a function that compare argument byte returing 1 if equal else 0. |
| 158 // On Windows, it compares rcx with rdx which does not require REX prefix; | 154 // On Windows, it compares rcx with rdx which does not require REX prefix; |
| 159 // on Linux, it compares rdi with rsi which requires REX prefix. | 155 // on Linux, it compares rdi with rsi which requires REX prefix. |
| 160 | 156 |
| 161 Label done; | 157 Label done; |
| 162 __ movq(rax, Immediate(1)); | 158 __ movq(rax, Immediate(1)); |
| 163 __ cmpb(arg1, arg2); | 159 __ cmpb(arg1, arg2); |
| 164 __ j(equal, &done); | 160 __ j(equal, &done); |
| 165 __ movq(rax, Immediate(0)); | 161 __ movq(rax, Immediate(0)); |
| 166 __ bind(&done); | 162 __ bind(&done); |
| 167 __ ret(0); | 163 __ ret(0); |
| 168 | 164 |
| 169 CodeDesc desc; | 165 CodeDesc desc; |
| 170 assm.GetCode(&desc); | 166 assm.GetCode(&desc); |
| 171 // Call the function from C++. | 167 // Call the function from C++. |
| 172 int result = FUNCTION_CAST<F2>(buffer)(0x1002, 0x2002); | 168 int result = FUNCTION_CAST<F2>(buffer)(0x1002, 0x2002); |
| 173 CHECK_EQ(1, result); | 169 CHECK_EQ(1, result); |
| 174 result = FUNCTION_CAST<F2>(buffer)(0x1002, 0x2003); | 170 result = FUNCTION_CAST<F2>(buffer)(0x1002, 0x2003); |
| 175 CHECK_EQ(0, result); | 171 CHECK_EQ(0, result); |
| 176 } | 172 } |
| 177 | 173 |
| 178 | 174 |
| 179 TEST(AssemblerX64ImulOperation) { | 175 TEST(AssemblerX64ImulOperation) { |
| 180 CcTest::InitializeVM(); | 176 CcTest::InitializeVM(); |
| 181 // Allocate an executable page of memory. | 177 // Allocate an executable page of memory. |
| 182 size_t actual_size; | 178 size_t actual_size; |
| 183 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 179 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 184 &actual_size, | 180 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 185 true)); | |
| 186 CHECK(buffer); | 181 CHECK(buffer); |
| 187 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 182 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 188 | 183 |
| 189 // Assemble a simple function that multiplies arguments returning the high | 184 // Assemble a simple function that multiplies arguments returning the high |
| 190 // word. | 185 // word. |
| 191 __ movq(rax, arg2); | 186 __ movq(rax, arg2); |
| 192 __ imulq(arg1); | 187 __ imulq(arg1); |
| 193 __ movq(rax, rdx); | 188 __ movq(rax, rdx); |
| 194 __ ret(0); | 189 __ ret(0); |
| 195 | 190 |
| 196 CodeDesc desc; | 191 CodeDesc desc; |
| 197 assm.GetCode(&desc); | 192 assm.GetCode(&desc); |
| 198 // Call the function from C++. | 193 // Call the function from C++. |
| 199 int result = FUNCTION_CAST<F2>(buffer)(3, 2); | 194 int result = FUNCTION_CAST<F2>(buffer)(3, 2); |
| 200 CHECK_EQ(0, result); | 195 CHECK_EQ(0, result); |
| 201 result = FUNCTION_CAST<F2>(buffer)(0x100000000l, 0x100000000l); | 196 result = FUNCTION_CAST<F2>(buffer)(0x100000000l, 0x100000000l); |
| 202 CHECK_EQ(1, result); | 197 CHECK_EQ(1, result); |
| 203 result = FUNCTION_CAST<F2>(buffer)(-0x100000000l, 0x100000000l); | 198 result = FUNCTION_CAST<F2>(buffer)(-0x100000000l, 0x100000000l); |
| 204 CHECK_EQ(-1, result); | 199 CHECK_EQ(-1, result); |
| 205 } | 200 } |
| 206 | 201 |
| 207 | 202 |
| 208 TEST(AssemblerX64XchglOperations) { | 203 TEST(AssemblerX64XchglOperations) { |
| 209 CcTest::InitializeVM(); | 204 CcTest::InitializeVM(); |
| 210 // Allocate an executable page of memory. | 205 // Allocate an executable page of memory. |
| 211 size_t actual_size; | 206 size_t actual_size; |
| 212 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 207 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 213 &actual_size, | 208 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 214 true)); | |
| 215 CHECK(buffer); | 209 CHECK(buffer); |
| 216 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 210 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 217 | 211 |
| 218 __ movq(rax, Operand(arg1, 0)); | 212 __ movq(rax, Operand(arg1, 0)); |
| 219 __ movq(r11, Operand(arg2, 0)); | 213 __ movq(r11, Operand(arg2, 0)); |
| 220 __ xchgl(rax, r11); | 214 __ xchgl(rax, r11); |
| 221 __ movq(Operand(arg1, 0), rax); | 215 __ movq(Operand(arg1, 0), rax); |
| 222 __ movq(Operand(arg2, 0), r11); | 216 __ movq(Operand(arg2, 0), r11); |
| 223 __ ret(0); | 217 __ ret(0); |
| 224 | 218 |
| 225 CodeDesc desc; | 219 CodeDesc desc; |
| 226 assm.GetCode(&desc); | 220 assm.GetCode(&desc); |
| 227 // Call the function from C++. | 221 // Call the function from C++. |
| 228 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); | 222 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); |
| 229 int64_t right = V8_2PART_UINT64_C(0x30000000, 40000000); | 223 int64_t right = V8_2PART_UINT64_C(0x30000000, 40000000); |
| 230 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); | 224 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); |
| 231 CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 40000000), left); | 225 CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 40000000), left); |
| 232 CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 20000000), right); | 226 CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 20000000), right); |
| 233 USE(result); | 227 USE(result); |
| 234 } | 228 } |
| 235 | 229 |
| 236 | 230 |
| 237 TEST(AssemblerX64OrlOperations) { | 231 TEST(AssemblerX64OrlOperations) { |
| 238 CcTest::InitializeVM(); | 232 CcTest::InitializeVM(); |
| 239 // Allocate an executable page of memory. | 233 // Allocate an executable page of memory. |
| 240 size_t actual_size; | 234 size_t actual_size; |
| 241 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 235 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 242 &actual_size, | 236 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 243 true)); | |
| 244 CHECK(buffer); | 237 CHECK(buffer); |
| 245 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 238 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 246 | 239 |
| 247 __ movq(rax, Operand(arg2, 0)); | 240 __ movq(rax, Operand(arg2, 0)); |
| 248 __ orl(Operand(arg1, 0), rax); | 241 __ orl(Operand(arg1, 0), rax); |
| 249 __ ret(0); | 242 __ ret(0); |
| 250 | 243 |
| 251 CodeDesc desc; | 244 CodeDesc desc; |
| 252 assm.GetCode(&desc); | 245 assm.GetCode(&desc); |
| 253 // Call the function from C++. | 246 // Call the function from C++. |
| 254 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); | 247 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); |
| 255 int64_t right = V8_2PART_UINT64_C(0x30000000, 40000000); | 248 int64_t right = V8_2PART_UINT64_C(0x30000000, 40000000); |
| 256 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); | 249 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); |
| 257 CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 60000000), left); | 250 CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 60000000), left); |
| 258 USE(result); | 251 USE(result); |
| 259 } | 252 } |
| 260 | 253 |
| 261 | 254 |
| 262 TEST(AssemblerX64RollOperations) { | 255 TEST(AssemblerX64RollOperations) { |
| 263 CcTest::InitializeVM(); | 256 CcTest::InitializeVM(); |
| 264 // Allocate an executable page of memory. | 257 // Allocate an executable page of memory. |
| 265 size_t actual_size; | 258 size_t actual_size; |
| 266 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 259 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 267 &actual_size, | 260 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 268 true)); | |
| 269 CHECK(buffer); | 261 CHECK(buffer); |
| 270 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 262 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 271 | 263 |
| 272 __ movq(rax, arg1); | 264 __ movq(rax, arg1); |
| 273 __ roll(rax, Immediate(1)); | 265 __ roll(rax, Immediate(1)); |
| 274 __ ret(0); | 266 __ ret(0); |
| 275 | 267 |
| 276 CodeDesc desc; | 268 CodeDesc desc; |
| 277 assm.GetCode(&desc); | 269 assm.GetCode(&desc); |
| 278 // Call the function from C++. | 270 // Call the function from C++. |
| 279 int64_t src = V8_2PART_UINT64_C(0x10000000, C0000000); | 271 int64_t src = V8_2PART_UINT64_C(0x10000000, C0000000); |
| 280 int64_t result = FUNCTION_CAST<F5>(buffer)(src); | 272 int64_t result = FUNCTION_CAST<F5>(buffer)(src); |
| 281 CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 80000001), result); | 273 CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 80000001), result); |
| 282 } | 274 } |
| 283 | 275 |
| 284 | 276 |
| 285 TEST(AssemblerX64SublOperations) { | 277 TEST(AssemblerX64SublOperations) { |
| 286 CcTest::InitializeVM(); | 278 CcTest::InitializeVM(); |
| 287 // Allocate an executable page of memory. | 279 // Allocate an executable page of memory. |
| 288 size_t actual_size; | 280 size_t actual_size; |
| 289 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 281 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 290 &actual_size, | 282 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 291 true)); | |
| 292 CHECK(buffer); | 283 CHECK(buffer); |
| 293 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 284 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 294 | 285 |
| 295 __ movq(rax, Operand(arg2, 0)); | 286 __ movq(rax, Operand(arg2, 0)); |
| 296 __ subl(Operand(arg1, 0), rax); | 287 __ subl(Operand(arg1, 0), rax); |
| 297 __ ret(0); | 288 __ ret(0); |
| 298 | 289 |
| 299 CodeDesc desc; | 290 CodeDesc desc; |
| 300 assm.GetCode(&desc); | 291 assm.GetCode(&desc); |
| 301 // Call the function from C++. | 292 // Call the function from C++. |
| 302 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); | 293 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); |
| 303 int64_t right = V8_2PART_UINT64_C(0x30000000, 40000000); | 294 int64_t right = V8_2PART_UINT64_C(0x30000000, 40000000); |
| 304 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); | 295 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); |
| 305 CHECK_EQ(V8_2PART_UINT64_C(0x10000000, e0000000), left); | 296 CHECK_EQ(V8_2PART_UINT64_C(0x10000000, e0000000), left); |
| 306 USE(result); | 297 USE(result); |
| 307 } | 298 } |
| 308 | 299 |
| 309 | 300 |
| 310 TEST(AssemblerX64TestlOperations) { | 301 TEST(AssemblerX64TestlOperations) { |
| 311 CcTest::InitializeVM(); | 302 CcTest::InitializeVM(); |
| 312 // Allocate an executable page of memory. | 303 // Allocate an executable page of memory. |
| 313 size_t actual_size; | 304 size_t actual_size; |
| 314 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 305 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 315 &actual_size, | 306 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 316 true)); | |
| 317 CHECK(buffer); | 307 CHECK(buffer); |
| 318 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 308 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 319 | 309 |
| 320 // Set rax with the ZF flag of the testl instruction. | 310 // Set rax with the ZF flag of the testl instruction. |
| 321 Label done; | 311 Label done; |
| 322 __ movq(rax, Immediate(1)); | 312 __ movq(rax, Immediate(1)); |
| 323 __ movq(r11, Operand(arg2, 0)); | 313 __ movq(r11, Operand(arg2, 0)); |
| 324 __ testl(Operand(arg1, 0), r11); | 314 __ testl(Operand(arg1, 0), r11); |
| 325 __ j(zero, &done, Label::kNear); | 315 __ j(zero, &done, Label::kNear); |
| 326 __ movq(rax, Immediate(0)); | 316 __ movq(rax, Immediate(0)); |
| 327 __ bind(&done); | 317 __ bind(&done); |
| 328 __ ret(0); | 318 __ ret(0); |
| 329 | 319 |
| 330 CodeDesc desc; | 320 CodeDesc desc; |
| 331 assm.GetCode(&desc); | 321 assm.GetCode(&desc); |
| 332 // Call the function from C++. | 322 // Call the function from C++. |
| 333 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); | 323 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); |
| 334 int64_t right = V8_2PART_UINT64_C(0x30000000, 00000000); | 324 int64_t right = V8_2PART_UINT64_C(0x30000000, 00000000); |
| 335 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); | 325 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); |
| 336 CHECK_EQ(static_cast<int64_t>(1), result); | 326 CHECK_EQ(static_cast<int64_t>(1), result); |
| 337 } | 327 } |
| 338 | 328 |
| 339 | 329 |
| 340 TEST(AssemblerX64XorlOperations) { | 330 TEST(AssemblerX64XorlOperations) { |
| 341 CcTest::InitializeVM(); | 331 CcTest::InitializeVM(); |
| 342 // Allocate an executable page of memory. | 332 // Allocate an executable page of memory. |
| 343 size_t actual_size; | 333 size_t actual_size; |
| 344 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 334 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 345 &actual_size, | 335 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 346 true)); | |
| 347 CHECK(buffer); | 336 CHECK(buffer); |
| 348 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 337 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 349 | 338 |
| 350 __ movq(rax, Operand(arg2, 0)); | 339 __ movq(rax, Operand(arg2, 0)); |
| 351 __ xorl(Operand(arg1, 0), rax); | 340 __ xorl(Operand(arg1, 0), rax); |
| 352 __ ret(0); | 341 __ ret(0); |
| 353 | 342 |
| 354 CodeDesc desc; | 343 CodeDesc desc; |
| 355 assm.GetCode(&desc); | 344 assm.GetCode(&desc); |
| 356 // Call the function from C++. | 345 // Call the function from C++. |
| 357 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); | 346 int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000); |
| 358 int64_t right = V8_2PART_UINT64_C(0x30000000, 60000000); | 347 int64_t right = V8_2PART_UINT64_C(0x30000000, 60000000); |
| 359 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); | 348 int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right); |
| 360 CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 40000000), left); | 349 CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 40000000), left); |
| 361 USE(result); | 350 USE(result); |
| 362 } | 351 } |
| 363 | 352 |
| 364 | 353 |
| 365 TEST(AssemblerX64MemoryOperands) { | 354 TEST(AssemblerX64MemoryOperands) { |
| 366 CcTest::InitializeVM(); | 355 CcTest::InitializeVM(); |
| 367 // Allocate an executable page of memory. | 356 // Allocate an executable page of memory. |
| 368 size_t actual_size; | 357 size_t actual_size; |
| 369 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 358 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 370 &actual_size, | 359 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 371 true)); | |
| 372 CHECK(buffer); | 360 CHECK(buffer); |
| 373 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 361 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 374 | 362 |
| 375 // Assemble a simple function that copies argument 2 and returns it. | 363 // Assemble a simple function that copies argument 2 and returns it. |
| 376 __ pushq(rbp); | 364 __ pushq(rbp); |
| 377 __ movq(rbp, rsp); | 365 __ movq(rbp, rsp); |
| 378 | 366 |
| 379 __ pushq(arg2); // Value at (rbp - 8) | 367 __ pushq(arg2); // Value at (rbp - 8) |
| 380 __ pushq(arg2); // Value at (rbp - 16) | 368 __ pushq(arg2); // Value at (rbp - 16) |
| 381 __ pushq(arg1); // Value at (rbp - 24) | 369 __ pushq(arg1); // Value at (rbp - 24) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 394 // Call the function from C++. | 382 // Call the function from C++. |
| 395 int result = FUNCTION_CAST<F2>(buffer)(3, 2); | 383 int result = FUNCTION_CAST<F2>(buffer)(3, 2); |
| 396 CHECK_EQ(3, result); | 384 CHECK_EQ(3, result); |
| 397 } | 385 } |
| 398 | 386 |
| 399 | 387 |
| 400 TEST(AssemblerX64ControlFlow) { | 388 TEST(AssemblerX64ControlFlow) { |
| 401 CcTest::InitializeVM(); | 389 CcTest::InitializeVM(); |
| 402 // Allocate an executable page of memory. | 390 // Allocate an executable page of memory. |
| 403 size_t actual_size; | 391 size_t actual_size; |
| 404 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 392 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 405 &actual_size, | 393 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 406 true)); | |
| 407 CHECK(buffer); | 394 CHECK(buffer); |
| 408 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 395 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 409 | 396 |
| 410 // Assemble a simple function that copies argument 1 and returns it. | 397 // Assemble a simple function that copies argument 1 and returns it. |
| 411 __ pushq(rbp); | 398 __ pushq(rbp); |
| 412 | 399 |
| 413 __ movq(rbp, rsp); | 400 __ movq(rbp, rsp); |
| 414 __ movq(rax, arg1); | 401 __ movq(rax, arg1); |
| 415 Label target; | 402 Label target; |
| 416 __ jmp(&target); | 403 __ jmp(&target); |
| 417 __ movq(rax, arg2); | 404 __ movq(rax, arg2); |
| 418 __ bind(&target); | 405 __ bind(&target); |
| 419 __ popq(rbp); | 406 __ popq(rbp); |
| 420 __ ret(0); | 407 __ ret(0); |
| 421 | 408 |
| 422 CodeDesc desc; | 409 CodeDesc desc; |
| 423 assm.GetCode(&desc); | 410 assm.GetCode(&desc); |
| 424 // Call the function from C++. | 411 // Call the function from C++. |
| 425 int result = FUNCTION_CAST<F2>(buffer)(3, 2); | 412 int result = FUNCTION_CAST<F2>(buffer)(3, 2); |
| 426 CHECK_EQ(3, result); | 413 CHECK_EQ(3, result); |
| 427 } | 414 } |
| 428 | 415 |
| 429 | 416 |
| 430 TEST(AssemblerX64LoopImmediates) { | 417 TEST(AssemblerX64LoopImmediates) { |
| 431 CcTest::InitializeVM(); | 418 CcTest::InitializeVM(); |
| 432 // Allocate an executable page of memory. | 419 // Allocate an executable page of memory. |
| 433 size_t actual_size; | 420 size_t actual_size; |
| 434 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 421 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 435 &actual_size, | 422 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 436 true)); | |
| 437 CHECK(buffer); | 423 CHECK(buffer); |
| 438 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); | 424 Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); |
| 439 // Assemble two loops using rax as counter, and verify the ending counts. | 425 // Assemble two loops using rax as counter, and verify the ending counts. |
| 440 Label Fail; | 426 Label Fail; |
| 441 __ movq(rax, Immediate(-3)); | 427 __ movq(rax, Immediate(-3)); |
| 442 Label Loop1_test; | 428 Label Loop1_test; |
| 443 Label Loop1_body; | 429 Label Loop1_body; |
| 444 __ jmp(&Loop1_test); | 430 __ jmp(&Loop1_test); |
| 445 __ bind(&Loop1_body); | 431 __ bind(&Loop1_body); |
| 446 __ addq(rax, Immediate(7)); | 432 __ addq(rax, Immediate(7)); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 628 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 643 | 629 |
| 644 F0 f = FUNCTION_CAST<F0>(code->entry()); | 630 F0 f = FUNCTION_CAST<F0>(code->entry()); |
| 645 int res = f(); | 631 int res = f(); |
| 646 args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res)); | 632 args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res)); |
| 647 } | 633 } |
| 648 | 634 |
| 649 | 635 |
| 650 TEST(StackAlignmentForSSE2) { | 636 TEST(StackAlignmentForSSE2) { |
| 651 CcTest::InitializeVM(); | 637 CcTest::InitializeVM(); |
| 652 CHECK_EQ(0, OS::ActivationFrameAlignment() % 16); | 638 CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16); |
| 653 | 639 |
| 654 v8::Isolate* isolate = CcTest::isolate(); | 640 v8::Isolate* isolate = CcTest::isolate(); |
| 655 v8::HandleScope handle_scope(isolate); | 641 v8::HandleScope handle_scope(isolate); |
| 656 v8::Handle<v8::ObjectTemplate> global_template = | 642 v8::Handle<v8::ObjectTemplate> global_template = |
| 657 v8::ObjectTemplate::New(isolate); | 643 v8::ObjectTemplate::New(isolate); |
| 658 global_template->Set(v8_str("do_sse2"), | 644 global_template->Set(v8_str("do_sse2"), |
| 659 v8::FunctionTemplate::New(isolate, DoSSE2)); | 645 v8::FunctionTemplate::New(isolate, DoSSE2)); |
| 660 | 646 |
| 661 LocalContext env(NULL, global_template); | 647 LocalContext env(NULL, global_template); |
| 662 CompileRun( | 648 CompileRun( |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 Code::ComputeFlags(Code::STUB), | 727 Code::ComputeFlags(Code::STUB), |
| 742 Handle<Code>()); | 728 Handle<Code>()); |
| 743 #ifdef OBJECT_PRINT | 729 #ifdef OBJECT_PRINT |
| 744 code->Print(); | 730 code->Print(); |
| 745 #endif | 731 #endif |
| 746 | 732 |
| 747 F6 f = FUNCTION_CAST<F6>(code->entry()); | 733 F6 f = FUNCTION_CAST<F6>(code->entry()); |
| 748 CHECK_EQ(2, f(1.0, 2.0)); | 734 CHECK_EQ(2, f(1.0, 2.0)); |
| 749 } | 735 } |
| 750 #undef __ | 736 #undef __ |
| OLD | NEW |