1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // 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 <stdlib.h> 29 30 #include "src/v8.h" 31 32 #include "src/base/platform/platform.h" 33 #include "src/disassembler.h" 34 #include "src/factory.h" 35 #include "src/macro-assembler.h" 36 #include "src/ostreams.h" 37 #include "src/serialize.h" 38 #include "test/cctest/cctest.h" 39 40 using namespace v8::internal; 41 42 43 typedef int (*F0)(); 44 typedef int (*F1)(int x); 45 typedef int (*F2)(int x, int y); 46 47 48 #define __ assm. 49 50 TEST(AssemblerIa320) { 51 CcTest::InitializeVM(); 52 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate()); 53 HandleScope scope(isolate); 54 55 v8::internal::byte buffer[256]; 56 Assembler assm(isolate, buffer, sizeof buffer); 57 58 __ mov(eax, Operand(esp, 4)); 59 __ add(eax, Operand(esp, 8)); 60 __ ret(0); 61 62 CodeDesc desc; 63 assm.GetCode(&desc); 64 Handle<Code> code = isolate->factory()->NewCode( 65 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 66 #ifdef OBJECT_PRINT 67 OFStream os(stdout); 68 code->Print(os); 69 #endif 70 F2 f = FUNCTION_CAST<F2>(code->entry()); 71 int res = f(3, 4); 72 ::printf("f() = %d\n", res); 73 CHECK_EQ(7, res); 74 } 75 76 77 TEST(AssemblerIa321) { 78 CcTest::InitializeVM(); 79 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate()); 80 HandleScope scope(isolate); 81 82 v8::internal::byte buffer[256]; 83 Assembler assm(isolate, buffer, sizeof buffer); 84 Label L, C; 85 86 __ mov(edx, Operand(esp, 4)); 87 __ xor_(eax, eax); // clear eax 88 __ jmp(&C); 89 90 __ bind(&L); 91 __ add(eax, edx); 92 __ sub(edx, Immediate(1)); 93 94 __ bind(&C); 95 __ test(edx, edx); 96 __ j(not_zero, &L); 97 __ ret(0); 98 99 CodeDesc desc; 100 assm.GetCode(&desc); 101 Handle<Code> code = isolate->factory()->NewCode( 102 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 103 #ifdef OBJECT_PRINT 104 OFStream os(stdout); 105 code->Print(os); 106 #endif 107 F1 f = FUNCTION_CAST<F1>(code->entry()); 108 int res = f(100); 109 ::printf("f() = %d\n", res); 110 CHECK_EQ(5050, res); 111 } 112 113 114 TEST(AssemblerIa322) { 115 CcTest::InitializeVM(); 116 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate()); 117 HandleScope scope(isolate); 118 119 v8::internal::byte buffer[256]; 120 Assembler assm(isolate, buffer, sizeof buffer); 121 Label L, C; 122 123 __ mov(edx, Operand(esp, 4)); 124 __ mov(eax, 1); 125 __ jmp(&C); 126 127 __ bind(&L); 128 __ imul(eax, edx); 129 __ sub(edx, Immediate(1)); 130 131 __ bind(&C); 132 __ test(edx, edx); 133 __ j(not_zero, &L); 134 __ ret(0); 135 136 // some relocated stuff here, not executed 137 __ mov(eax, isolate->factory()->true_value()); 138 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY); 139 140 CodeDesc desc; 141 assm.GetCode(&desc); 142 Handle<Code> code = isolate->factory()->NewCode( 143 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 144 #ifdef OBJECT_PRINT 145 OFStream os(stdout); 146 code->Print(os); 147 #endif 148 F1 f = FUNCTION_CAST<F1>(code->entry()); 149 int res = f(10); 150 ::printf("f() = %d\n", res); 151 CHECK_EQ(3628800, res); 152 } 153 154 155 typedef int (*F3)(float x); 156 157 typedef int (*F4)(double x); 158 159 static int baz = 42; 160 TEST(AssemblerIa325) { 161 CcTest::InitializeVM(); 162 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate()); 163 HandleScope scope(isolate); 164 165 v8::internal::byte buffer[256]; 166 Assembler assm(isolate, buffer, sizeof buffer); 167 168 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32)); 169 __ ret(0); 170 171 CodeDesc desc; 172 assm.GetCode(&desc); 173 Handle<Code> code = isolate->factory()->NewCode( 174 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 175 F0 f = FUNCTION_CAST<F0>(code->entry()); 176 int res = f(); 177 CHECK_EQ(42, res); 178 } 179 180 181 typedef int (*F7)(double x, double y); 182 183 TEST(AssemblerIa329) { 184 CcTest::InitializeVM(); 185 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate()); 186 HandleScope scope(isolate); 187 v8::internal::byte buffer[256]; 188 MacroAssembler assm(isolate, buffer, sizeof buffer); 189 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 }; 190 Label equal_l, less_l, greater_l, nan_l; 191 __ fld_d(Operand(esp, 3 * kPointerSize)); 192 __ fld_d(Operand(esp, 1 * kPointerSize)); 193 __ FCmp(); 194 __ j(parity_even, &nan_l); 195 __ j(equal, &equal_l); 196 __ j(below, &less_l); 197 __ j(above, &greater_l); 198 199 __ mov(eax, kUndefined); 200 __ ret(0); 201 202 __ bind(&equal_l); 203 __ mov(eax, kEqual); 204 __ ret(0); 205 206 __ bind(&greater_l); 207 __ mov(eax, kGreater); 208 __ ret(0); 209 210 __ bind(&less_l); 211 __ mov(eax, kLess); 212 __ ret(0); 213 214 __ bind(&nan_l); 215 __ mov(eax, kNaN); 216 __ ret(0); 217 218 219 CodeDesc desc; 220 assm.GetCode(&desc); 221 Handle<Code> code = isolate->factory()->NewCode( 222 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 223 #ifdef OBJECT_PRINT 224 OFStream os(stdout); 225 code->Print(os); 226 #endif 227 228 F7 f = FUNCTION_CAST<F7>(code->entry()); 229 CHECK_EQ(kLess, f(1.1, 2.2)); 230 CHECK_EQ(kEqual, f(2.2, 2.2)); 231 CHECK_EQ(kGreater, f(3.3, 2.2)); 232 CHECK_EQ(kNaN, f(v8::base::OS::nan_value(), 1.1)); 233 } 234 235 236 TEST(AssemblerIa3210) { 237 // Test chaining of label usages within instructions (issue 1644). 238 CcTest::InitializeVM(); 239 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate()); 240 HandleScope scope(isolate); 241 Assembler assm(isolate, NULL, 0); 242 243 Label target; 244 __ j(equal, &target); 245 __ j(not_equal, &target); 246 __ bind(&target); 247 __ nop(); 248 } 249 250 251 TEST(AssemblerMultiByteNop) { 252 CcTest::InitializeVM(); 253 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate()); 254 HandleScope scope(isolate); 255 v8::internal::byte buffer[1024]; 256 Assembler assm(isolate, buffer, sizeof(buffer)); 257 __ push(ebx); 258 __ push(ecx); 259 __ push(edx); 260 __ push(edi); 261 __ push(esi); 262 __ mov(eax, 1); 263 __ mov(ebx, 2); 264 __ mov(ecx, 3); 265 __ mov(edx, 4); 266 __ mov(edi, 5); 267 __ mov(esi, 6); 268 for (int i = 0; i < 16; i++) { 269 int before = assm.pc_offset(); 270 __ Nop(i); 271 CHECK_EQ(assm.pc_offset() - before, i); 272 } 273 274 Label fail; 275 __ cmp(eax, 1); 276 __ j(not_equal, &fail); 277 __ cmp(ebx, 2); 278 __ j(not_equal, &fail); 279 __ cmp(ecx, 3); 280 __ j(not_equal, &fail); 281 __ cmp(edx, 4); 282 __ j(not_equal, &fail); 283 __ cmp(edi, 5); 284 __ j(not_equal, &fail); 285 __ cmp(esi, 6); 286 __ j(not_equal, &fail); 287 __ mov(eax, 42); 288 __ pop(esi); 289 __ pop(edi); 290 __ pop(edx); 291 __ pop(ecx); 292 __ pop(ebx); 293 __ ret(0); 294 __ bind(&fail); 295 __ mov(eax, 13); 296 __ pop(esi); 297 __ pop(edi); 298 __ pop(edx); 299 __ pop(ecx); 300 __ pop(ebx); 301 __ ret(0); 302 303 CodeDesc desc; 304 assm.GetCode(&desc); 305 Handle<Code> code = isolate->factory()->NewCode( 306 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 307 CHECK(code->IsCode()); 308 309 F0 f = FUNCTION_CAST<F0>(code->entry()); 310 int res = f(); 311 CHECK_EQ(42, res); 312 } 313 314 315 #undef __ 316