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