1 // Copyright 2007-2008 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 "v8.h" 31 32 #include "debug.h" 33 #include "disasm.h" 34 #include "disassembler.h" 35 #include "macro-assembler.h" 36 #include "serialize.h" 37 #include "cctest.h" 38 39 using namespace v8::internal; 40 41 static v8::Persistent<v8::Context> env; 42 43 static void InitializeVM() { 44 if (env.IsEmpty()) { 45 env = v8::Context::New(); 46 } 47 } 48 49 50 #define __ assm. 51 52 53 static void DummyStaticFunction(Object* result) { 54 } 55 56 57 TEST(DisasmIa320) { 58 InitializeVM(); 59 v8::HandleScope scope; 60 v8::internal::byte buffer[2048]; 61 Assembler assm(Isolate::Current(), buffer, sizeof buffer); 62 DummyStaticFunction(NULL); // just bloody use it (DELETE; debugging) 63 64 // Short immediate instructions 65 __ adc(eax, 12345678); 66 __ add(Operand(eax), Immediate(12345678)); 67 __ or_(eax, 12345678); 68 __ sub(Operand(eax), Immediate(12345678)); 69 __ xor_(eax, 12345678); 70 __ and_(eax, 12345678); 71 Handle<FixedArray> foo = FACTORY->NewFixedArray(10, TENURED); 72 __ cmp(eax, foo); 73 74 // ---- This one caused crash 75 __ mov(ebx, Operand(esp, ecx, times_2, 0)); // [esp+ecx*4] 76 77 // ---- All instructions that I can think of 78 __ add(edx, Operand(ebx)); 79 __ add(edx, Operand(12, RelocInfo::NONE)); 80 __ add(edx, Operand(ebx, 0)); 81 __ add(edx, Operand(ebx, 16)); 82 __ add(edx, Operand(ebx, 1999)); 83 __ add(edx, Operand(esp, 0)); 84 __ add(edx, Operand(esp, 16)); 85 __ add(edx, Operand(esp, 1999)); 86 __ nop(); 87 __ add(edi, Operand(ebp, ecx, times_4, 0)); 88 __ add(edi, Operand(ebp, ecx, times_4, 12)); 89 __ add(Operand(ebp, ecx, times_4, 12), Immediate(12)); 90 91 __ nop(); 92 __ add(Operand(ebx), Immediate(12)); 93 __ nop(); 94 __ adc(ecx, 12); 95 __ adc(ecx, 1000); 96 __ nop(); 97 __ and_(edx, 3); 98 __ and_(edx, Operand(esp, 4)); 99 __ cmp(edx, 3); 100 __ cmp(edx, Operand(esp, 4)); 101 __ cmp(Operand(ebp, ecx, times_4, 0), Immediate(1000)); 102 Handle<FixedArray> foo2 = FACTORY->NewFixedArray(10, TENURED); 103 __ cmp(ebx, foo2); 104 __ cmpb(ebx, Operand(ebp, ecx, times_2, 0)); 105 __ cmpb(Operand(ebp, ecx, times_2, 0), ebx); 106 __ or_(edx, 3); 107 __ xor_(edx, 3); 108 __ nop(); 109 { 110 CHECK(CpuFeatures::IsSupported(CPUID)); 111 CpuFeatures::Scope fscope(CPUID); 112 __ cpuid(); 113 } 114 { 115 CHECK(CpuFeatures::IsSupported(RDTSC)); 116 CpuFeatures::Scope fscope(RDTSC); 117 __ rdtsc(); 118 } 119 __ movsx_b(edx, Operand(ecx)); 120 __ movsx_w(edx, Operand(ecx)); 121 __ movzx_b(edx, Operand(ecx)); 122 __ movzx_w(edx, Operand(ecx)); 123 124 __ nop(); 125 __ imul(edx, Operand(ecx)); 126 __ shld(edx, Operand(ecx)); 127 __ shrd(edx, Operand(ecx)); 128 __ bts(Operand(edx), ecx); 129 __ bts(Operand(ebx, ecx, times_4, 0), ecx); 130 __ nop(); 131 __ pushad(); 132 __ popad(); 133 __ pushfd(); 134 __ popfd(); 135 __ push(Immediate(12)); 136 __ push(Immediate(23456)); 137 __ push(ecx); 138 __ push(esi); 139 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 140 __ push(Operand(ebx, ecx, times_4, 0)); 141 __ push(Operand(ebx, ecx, times_4, 0)); 142 __ push(Operand(ebx, ecx, times_4, 10000)); 143 __ pop(edx); 144 __ pop(eax); 145 __ pop(Operand(ebx, ecx, times_4, 0)); 146 __ nop(); 147 148 __ add(edx, Operand(esp, 16)); 149 __ add(edx, Operand(ecx)); 150 __ mov_b(edx, Operand(ecx)); 151 __ mov_b(Operand(ecx), 6); 152 __ mov_b(Operand(ebx, ecx, times_4, 10000), 6); 153 __ mov_b(Operand(esp, 16), edx); 154 __ mov_w(edx, Operand(esp, 16)); 155 __ mov_w(Operand(esp, 16), edx); 156 __ nop(); 157 __ movsx_w(edx, Operand(esp, 12)); 158 __ movsx_b(edx, Operand(esp, 12)); 159 __ movzx_w(edx, Operand(esp, 12)); 160 __ movzx_b(edx, Operand(esp, 12)); 161 __ nop(); 162 __ mov(edx, 1234567); 163 __ mov(edx, Operand(esp, 12)); 164 __ mov(Operand(ebx, ecx, times_4, 10000), Immediate(12345)); 165 __ mov(Operand(ebx, ecx, times_4, 10000), edx); 166 __ nop(); 167 __ dec_b(edx); 168 __ dec_b(Operand(eax, 10)); 169 __ dec_b(Operand(ebx, ecx, times_4, 10000)); 170 __ dec(edx); 171 __ cdq(); 172 173 __ nop(); 174 __ idiv(edx); 175 __ mul(edx); 176 __ neg(edx); 177 __ not_(edx); 178 __ test(Operand(ebx, ecx, times_4, 10000), Immediate(123456)); 179 180 __ imul(edx, Operand(ebx, ecx, times_4, 10000)); 181 __ imul(edx, ecx, 12); 182 __ imul(edx, ecx, 1000); 183 184 __ inc(edx); 185 __ inc(Operand(ebx, ecx, times_4, 10000)); 186 __ push(Operand(ebx, ecx, times_4, 10000)); 187 __ pop(Operand(ebx, ecx, times_4, 10000)); 188 __ call(Operand(ebx, ecx, times_4, 10000)); 189 __ jmp(Operand(ebx, ecx, times_4, 10000)); 190 191 __ lea(edx, Operand(ebx, ecx, times_4, 10000)); 192 __ or_(edx, 12345); 193 __ or_(edx, Operand(ebx, ecx, times_4, 10000)); 194 195 __ nop(); 196 197 __ rcl(edx, 1); 198 __ rcl(edx, 7); 199 __ rcr(edx, 1); 200 __ rcr(edx, 7); 201 __ sar(edx, 1); 202 __ sar(edx, 6); 203 __ sar_cl(edx); 204 __ sbb(edx, Operand(ebx, ecx, times_4, 10000)); 205 __ shld(edx, Operand(ebx, ecx, times_4, 10000)); 206 __ shl(edx, 1); 207 __ shl(edx, 6); 208 __ shl_cl(edx); 209 __ shrd(edx, Operand(ebx, ecx, times_4, 10000)); 210 __ shr(edx, 1); 211 __ shr(edx, 7); 212 __ shr_cl(edx); 213 214 215 // Immediates 216 217 __ adc(edx, 12345); 218 219 __ add(Operand(ebx), Immediate(12)); 220 __ add(Operand(edx, ecx, times_4, 10000), Immediate(12)); 221 222 __ and_(ebx, 12345); 223 224 __ cmp(ebx, 12345); 225 __ cmp(Operand(ebx), Immediate(12)); 226 __ cmp(Operand(edx, ecx, times_4, 10000), Immediate(12)); 227 228 __ or_(ebx, 12345); 229 230 __ sub(Operand(ebx), Immediate(12)); 231 __ sub(Operand(edx, ecx, times_4, 10000), Immediate(12)); 232 __ subb(Operand(edx, ecx, times_4, 10000), 100); 233 __ subb(Operand(eax), 100); 234 __ subb(eax, Operand(edx, ecx, times_4, 10000)); 235 236 __ xor_(ebx, 12345); 237 238 __ imul(edx, ecx, 12); 239 __ imul(edx, ecx, 1000); 240 241 __ cld(); 242 __ rep_movs(); 243 __ rep_stos(); 244 __ stos(); 245 246 __ sub(edx, Operand(ebx, ecx, times_4, 10000)); 247 __ sub(edx, Operand(ebx)); 248 249 __ test(edx, Immediate(12345)); 250 __ test(edx, Operand(ebx, ecx, times_8, 10000)); 251 __ test(Operand(esi, edi, times_1, -20000000), Immediate(300000000)); 252 __ test_b(edx, Operand(ecx, ebx, times_2, 1000)); 253 __ test_b(Operand(eax, -20), 0x9A); 254 __ nop(); 255 256 __ xor_(edx, 12345); 257 __ xor_(edx, Operand(ebx, ecx, times_8, 10000)); 258 __ bts(Operand(ebx, ecx, times_8, 10000), edx); 259 __ hlt(); 260 __ int3(); 261 __ ret(0); 262 __ ret(8); 263 264 // Calls 265 266 Label L1, L2; 267 __ bind(&L1); 268 __ nop(); 269 __ call(&L1); 270 __ call(&L2); 271 __ nop(); 272 __ bind(&L2); 273 __ call(Operand(ebx, ecx, times_4, 10000)); 274 __ nop(); 275 Handle<Code> ic(Isolate::Current()->builtins()->builtin( 276 Builtins::kLoadIC_Initialize)); 277 __ call(ic, RelocInfo::CODE_TARGET); 278 __ nop(); 279 __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY); 280 __ nop(); 281 282 __ jmp(&L1); 283 __ jmp(Operand(ebx, ecx, times_4, 10000)); 284 #ifdef ENABLE_DEBUGGER_SUPPORT 285 ExternalReference after_break_target = 286 ExternalReference(Debug_Address::AfterBreakTarget(), 287 assm.isolate()); 288 __ jmp(Operand::StaticVariable(after_break_target)); 289 #endif // ENABLE_DEBUGGER_SUPPORT 290 __ jmp(ic, RelocInfo::CODE_TARGET); 291 __ nop(); 292 293 294 Label Ljcc; 295 __ nop(); 296 // long jumps 297 __ j(overflow, &Ljcc); 298 __ j(no_overflow, &Ljcc); 299 __ j(below, &Ljcc); 300 __ j(above_equal, &Ljcc); 301 __ j(equal, &Ljcc); 302 __ j(not_equal, &Ljcc); 303 __ j(below_equal, &Ljcc); 304 __ j(above, &Ljcc); 305 __ j(sign, &Ljcc); 306 __ j(not_sign, &Ljcc); 307 __ j(parity_even, &Ljcc); 308 __ j(parity_odd, &Ljcc); 309 __ j(less, &Ljcc); 310 __ j(greater_equal, &Ljcc); 311 __ j(less_equal, &Ljcc); 312 __ j(greater, &Ljcc); 313 __ nop(); 314 __ bind(&Ljcc); 315 // short jumps 316 __ j(overflow, &Ljcc); 317 __ j(no_overflow, &Ljcc); 318 __ j(below, &Ljcc); 319 __ j(above_equal, &Ljcc); 320 __ j(equal, &Ljcc); 321 __ j(not_equal, &Ljcc); 322 __ j(below_equal, &Ljcc); 323 __ j(above, &Ljcc); 324 __ j(sign, &Ljcc); 325 __ j(not_sign, &Ljcc); 326 __ j(parity_even, &Ljcc); 327 __ j(parity_odd, &Ljcc); 328 __ j(less, &Ljcc); 329 __ j(greater_equal, &Ljcc); 330 __ j(less_equal, &Ljcc); 331 __ j(greater, &Ljcc); 332 333 // checking hints 334 __ j(zero, &Ljcc, taken); 335 __ j(zero, &Ljcc, not_taken); 336 337 // __ mov(Operand::StaticVariable(Isolate::handler_address()), eax); 338 // 0xD9 instructions 339 __ nop(); 340 341 __ fld(1); 342 __ fld1(); 343 __ fldz(); 344 __ fldpi(); 345 __ fabs(); 346 __ fchs(); 347 __ fprem(); 348 __ fprem1(); 349 __ fincstp(); 350 __ ftst(); 351 __ fxch(3); 352 __ fld_s(Operand(ebx, ecx, times_4, 10000)); 353 __ fstp_s(Operand(ebx, ecx, times_4, 10000)); 354 __ ffree(3); 355 __ fld_d(Operand(ebx, ecx, times_4, 10000)); 356 __ fstp_d(Operand(ebx, ecx, times_4, 10000)); 357 __ nop(); 358 359 __ fild_s(Operand(ebx, ecx, times_4, 10000)); 360 __ fistp_s(Operand(ebx, ecx, times_4, 10000)); 361 __ fild_d(Operand(ebx, ecx, times_4, 10000)); 362 __ fistp_d(Operand(ebx, ecx, times_4, 10000)); 363 __ fnstsw_ax(); 364 __ nop(); 365 __ fadd(3); 366 __ fsub(3); 367 __ fmul(3); 368 __ fdiv(3); 369 370 __ faddp(3); 371 __ fsubp(3); 372 __ fmulp(3); 373 __ fdivp(3); 374 __ fcompp(); 375 __ fwait(); 376 __ nop(); 377 { 378 if (CpuFeatures::IsSupported(SSE2)) { 379 CpuFeatures::Scope fscope(SSE2); 380 __ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000)); 381 __ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000)); 382 __ addsd(xmm1, xmm0); 383 __ mulsd(xmm1, xmm0); 384 __ subsd(xmm1, xmm0); 385 __ divsd(xmm1, xmm0); 386 __ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000)); 387 __ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1); 388 __ ucomisd(xmm0, xmm1); 389 390 // 128 bit move instructions. 391 __ movdqa(xmm0, Operand(ebx, ecx, times_4, 10000)); 392 __ movdqa(Operand(ebx, ecx, times_4, 10000), xmm0); 393 __ movdqu(xmm0, Operand(ebx, ecx, times_4, 10000)); 394 __ movdqu(Operand(ebx, ecx, times_4, 10000), xmm0); 395 } 396 } 397 398 // cmov. 399 { 400 if (CpuFeatures::IsSupported(CMOV)) { 401 CpuFeatures::Scope use_cmov(CMOV); 402 __ cmov(overflow, eax, Operand(eax, 0)); 403 __ cmov(no_overflow, eax, Operand(eax, 1)); 404 __ cmov(below, eax, Operand(eax, 2)); 405 __ cmov(above_equal, eax, Operand(eax, 3)); 406 __ cmov(equal, eax, Operand(ebx, 0)); 407 __ cmov(not_equal, eax, Operand(ebx, 1)); 408 __ cmov(below_equal, eax, Operand(ebx, 2)); 409 __ cmov(above, eax, Operand(ebx, 3)); 410 __ cmov(sign, eax, Operand(ecx, 0)); 411 __ cmov(not_sign, eax, Operand(ecx, 1)); 412 __ cmov(parity_even, eax, Operand(ecx, 2)); 413 __ cmov(parity_odd, eax, Operand(ecx, 3)); 414 __ cmov(less, eax, Operand(edx, 0)); 415 __ cmov(greater_equal, eax, Operand(edx, 1)); 416 __ cmov(less_equal, eax, Operand(edx, 2)); 417 __ cmov(greater, eax, Operand(edx, 3)); 418 } 419 } 420 421 // andpd, cmpltsd, movaps, psllq, psrlq, por. 422 { 423 if (CpuFeatures::IsSupported(SSE2)) { 424 CpuFeatures::Scope fscope(SSE2); 425 __ andpd(xmm0, xmm1); 426 __ andpd(xmm1, xmm2); 427 428 __ cmpltsd(xmm0, xmm1); 429 __ cmpltsd(xmm1, xmm2); 430 431 __ movaps(xmm0, xmm1); 432 __ movaps(xmm1, xmm2); 433 434 __ psllq(xmm0, 17); 435 __ psllq(xmm1, 42); 436 437 __ psllq(xmm0, xmm1); 438 __ psllq(xmm1, xmm2); 439 440 __ psrlq(xmm0, 17); 441 __ psrlq(xmm1, 42); 442 443 __ psrlq(xmm0, xmm1); 444 __ psrlq(xmm1, xmm2); 445 446 __ por(xmm0, xmm1); 447 __ por(xmm1, xmm2); 448 } 449 } 450 451 { 452 if (CpuFeatures::IsSupported(SSE4_1)) { 453 CpuFeatures::Scope scope(SSE4_1); 454 __ pextrd(Operand(eax), xmm0, 1); 455 __ pinsrd(xmm1, Operand(eax), 0); 456 } 457 } 458 459 __ ret(0); 460 461 CodeDesc desc; 462 assm.GetCode(&desc); 463 Object* code = HEAP->CreateCode( 464 desc, 465 Code::ComputeFlags(Code::STUB), 466 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); 467 CHECK(code->IsCode()); 468 #ifdef OBJECT_PRINT 469 Code::cast(code)->Print(); 470 byte* begin = Code::cast(code)->instruction_start(); 471 byte* end = begin + Code::cast(code)->instruction_size(); 472 disasm::Disassembler::Disassemble(stdout, begin, end); 473 #endif 474 } 475 476 #undef __ 477