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/debug.h" 33#include "src/disasm.h" 34#include "src/disassembler.h" 35#include "src/macro-assembler.h" 36#include "src/serialize.h" 37#include "src/stub-cache.h" 38#include "test/cctest/cctest.h" 39 40using namespace v8::internal; 41 42 43#define __ assm. 44 45 46static void DummyStaticFunction(Object* result) { 47} 48 49 50TEST(DisasmX64) { 51 CcTest::InitializeVM(); 52 Isolate* isolate = CcTest::i_isolate(); 53 HandleScope scope(isolate); 54 v8::internal::byte buffer[2048]; 55 Assembler assm(isolate, buffer, sizeof buffer); 56 DummyStaticFunction(NULL); // just bloody use it (DELETE; debugging) 57 58 // Short immediate instructions 59 __ addq(rax, Immediate(12345678)); 60 __ orq(rax, Immediate(12345678)); 61 __ subq(rax, Immediate(12345678)); 62 __ xorq(rax, Immediate(12345678)); 63 __ andq(rax, Immediate(12345678)); 64 65 // ---- This one caused crash 66 __ movq(rbx, Operand(rsp, rcx, times_2, 0)); // [rsp+rcx*4] 67 68 // ---- All instructions that I can think of 69 __ addq(rdx, rbx); 70 __ addq(rdx, Operand(rbx, 0)); 71 __ addq(rdx, Operand(rbx, 16)); 72 __ addq(rdx, Operand(rbx, 1999)); 73 __ addq(rdx, Operand(rbx, -4)); 74 __ addq(rdx, Operand(rbx, -1999)); 75 __ addq(rdx, Operand(rsp, 0)); 76 __ addq(rdx, Operand(rsp, 16)); 77 __ addq(rdx, Operand(rsp, 1999)); 78 __ addq(rdx, Operand(rsp, -4)); 79 __ addq(rdx, Operand(rsp, -1999)); 80 __ nop(); 81 __ addq(rsi, Operand(rcx, times_4, 0)); 82 __ addq(rsi, Operand(rcx, times_4, 24)); 83 __ addq(rsi, Operand(rcx, times_4, -4)); 84 __ addq(rsi, Operand(rcx, times_4, -1999)); 85 __ nop(); 86 __ addq(rdi, Operand(rbp, rcx, times_4, 0)); 87 __ addq(rdi, Operand(rbp, rcx, times_4, 12)); 88 __ addq(rdi, Operand(rbp, rcx, times_4, -8)); 89 __ addq(rdi, Operand(rbp, rcx, times_4, -3999)); 90 __ addq(Operand(rbp, rcx, times_4, 12), Immediate(12)); 91 92 __ nop(); 93 __ addq(rbx, Immediate(12)); 94 __ nop(); 95 __ nop(); 96 __ andq(rdx, Immediate(3)); 97 __ andq(rdx, Operand(rsp, 4)); 98 __ cmpq(rdx, Immediate(3)); 99 __ cmpq(rdx, Operand(rsp, 4)); 100 __ cmpq(Operand(rbp, rcx, times_4, 0), Immediate(1000)); 101 __ cmpb(rbx, Operand(rbp, rcx, times_2, 0)); 102 __ cmpb(Operand(rbp, rcx, times_2, 0), rbx); 103 __ orq(rdx, Immediate(3)); 104 __ xorq(rdx, Immediate(3)); 105 __ nop(); 106 __ cpuid(); 107 __ movsxbl(rdx, Operand(rcx, 0)); 108 __ movsxbq(rdx, Operand(rcx, 0)); 109 __ movsxwl(rdx, Operand(rcx, 0)); 110 __ movsxwq(rdx, Operand(rcx, 0)); 111 __ movzxbl(rdx, Operand(rcx, 0)); 112 __ movzxwl(rdx, Operand(rcx, 0)); 113 __ movzxbq(rdx, Operand(rcx, 0)); 114 __ movzxwq(rdx, Operand(rcx, 0)); 115 116 __ nop(); 117 __ imulq(rdx, rcx); 118 __ shld(rdx, rcx); 119 __ shrd(rdx, rcx); 120 __ bts(Operand(rdx, 0), rcx); 121 __ bts(Operand(rbx, rcx, times_4, 0), rcx); 122 __ nop(); 123 __ pushq(Immediate(12)); 124 __ pushq(Immediate(23456)); 125 __ pushq(rcx); 126 __ pushq(rsi); 127 __ pushq(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 128 __ pushq(Operand(rbx, rcx, times_4, 0)); 129 __ pushq(Operand(rbx, rcx, times_4, 0)); 130 __ pushq(Operand(rbx, rcx, times_4, 10000)); 131 __ popq(rdx); 132 __ popq(rax); 133 __ popq(Operand(rbx, rcx, times_4, 0)); 134 __ nop(); 135 136 __ addq(rdx, Operand(rsp, 16)); 137 __ addq(rdx, rcx); 138 __ movb(rdx, Operand(rcx, 0)); 139 __ movb(rcx, Immediate(6)); 140 __ movb(Operand(rsp, 16), rdx); 141 __ movw(Operand(rsp, 16), rdx); 142 __ nop(); 143 __ movsxwq(rdx, Operand(rsp, 12)); 144 __ movsxbq(rdx, Operand(rsp, 12)); 145 __ movsxlq(rdx, Operand(rsp, 12)); 146 __ movzxwq(rdx, Operand(rsp, 12)); 147 __ movzxbq(rdx, Operand(rsp, 12)); 148 __ nop(); 149 __ movq(rdx, Immediate(1234567)); 150 __ movq(rdx, Operand(rsp, 12)); 151 __ movq(Operand(rbx, rcx, times_4, 10000), Immediate(12345)); 152 __ movq(Operand(rbx, rcx, times_4, 10000), rdx); 153 __ nop(); 154 __ decb(rdx); 155 __ decb(Operand(rax, 10)); 156 __ decb(Operand(rbx, rcx, times_4, 10000)); 157 __ decq(rdx); 158 __ cdq(); 159 160 __ nop(); 161 __ idivq(rdx); 162 __ mul(rdx); 163 __ negq(rdx); 164 __ notq(rdx); 165 __ testq(Operand(rbx, rcx, times_4, 10000), rdx); 166 167 __ imulq(rdx, Operand(rbx, rcx, times_4, 10000)); 168 __ imulq(rdx, rcx, Immediate(12)); 169 __ imulq(rdx, rcx, Immediate(1000)); 170 171 __ incq(rdx); 172 __ incq(Operand(rbx, rcx, times_4, 10000)); 173 __ pushq(Operand(rbx, rcx, times_4, 10000)); 174 __ popq(Operand(rbx, rcx, times_4, 10000)); 175 // TODO(mstarzinger): The following is protected. 176 // __ jmp(Operand(rbx, rcx, times_4, 10000)); 177 178 __ leaq(rdx, Operand(rbx, rcx, times_4, 10000)); 179 __ orq(rdx, Immediate(12345)); 180 __ orq(rdx, Operand(rbx, rcx, times_4, 10000)); 181 182 __ nop(); 183 184 __ rclq(rdx, Immediate(1)); 185 __ rclq(rdx, Immediate(7)); 186 __ rcrq(rdx, Immediate(1)); 187 __ rcrq(rdx, Immediate(7)); 188 __ sarq(rdx, Immediate(1)); 189 __ sarq(rdx, Immediate(6)); 190 __ sarq_cl(rdx); 191 __ sbbq(rdx, rbx); 192 __ shld(rdx, rbx); 193 __ shlq(rdx, Immediate(1)); 194 __ shlq(rdx, Immediate(6)); 195 __ shlq_cl(rdx); 196 __ shrd(rdx, rbx); 197 __ shrq(rdx, Immediate(1)); 198 __ shrq(rdx, Immediate(7)); 199 __ shrq_cl(rdx); 200 201 202 // Immediates 203 204 __ addq(rbx, Immediate(12)); 205 __ addq(Operand(rdx, rcx, times_4, 10000), Immediate(12)); 206 207 __ andq(rbx, Immediate(12345)); 208 209 __ cmpq(rbx, Immediate(12345)); 210 __ cmpq(rbx, Immediate(12)); 211 __ cmpq(Operand(rdx, rcx, times_4, 10000), Immediate(12)); 212 __ cmpb(rax, Immediate(100)); 213 214 __ orq(rbx, Immediate(12345)); 215 216 __ subq(rbx, Immediate(12)); 217 __ subq(Operand(rdx, rcx, times_4, 10000), Immediate(12)); 218 219 __ xorq(rbx, Immediate(12345)); 220 221 __ imulq(rdx, rcx, Immediate(12)); 222 __ imulq(rdx, rcx, Immediate(1000)); 223 224 __ cld(); 225 226 __ subq(rdx, Operand(rbx, rcx, times_4, 10000)); 227 __ subq(rdx, rbx); 228 229 __ testq(rdx, Immediate(12345)); 230 __ testq(Operand(rbx, rcx, times_8, 10000), rdx); 231 __ testb(Operand(rcx, rbx, times_2, 1000), rdx); 232 __ testb(Operand(rax, -20), Immediate(0x9A)); 233 __ nop(); 234 235 __ xorq(rdx, Immediate(12345)); 236 __ xorq(rdx, Operand(rbx, rcx, times_8, 10000)); 237 __ bts(Operand(rbx, rcx, times_8, 10000), rdx); 238 __ hlt(); 239 __ int3(); 240 __ ret(0); 241 __ ret(8); 242 243 // Calls 244 245 Label L1, L2; 246 __ bind(&L1); 247 __ nop(); 248 __ call(&L1); 249 __ call(&L2); 250 __ nop(); 251 __ bind(&L2); 252 // TODO(mstarzinger): The following is protected. 253 // __ call(Operand(rbx, rcx, times_4, 10000)); 254 __ nop(); 255 Handle<Code> ic(LoadIC::initialize_stub(isolate, NOT_CONTEXTUAL)); 256 __ call(ic, RelocInfo::CODE_TARGET); 257 __ nop(); 258 __ nop(); 259 260 __ jmp(&L1); 261 // TODO(mstarzinger): The following is protected. 262 // __ jmp(Operand(rbx, rcx, times_4, 10000)); 263 ExternalReference after_break_target = 264 ExternalReference::debug_after_break_target_address(isolate); 265 USE(after_break_target); 266 __ jmp(ic, RelocInfo::CODE_TARGET); 267 __ nop(); 268 269 270 Label Ljcc; 271 __ nop(); 272 // long jumps 273 __ j(overflow, &Ljcc); 274 __ j(no_overflow, &Ljcc); 275 __ j(below, &Ljcc); 276 __ j(above_equal, &Ljcc); 277 __ j(equal, &Ljcc); 278 __ j(not_equal, &Ljcc); 279 __ j(below_equal, &Ljcc); 280 __ j(above, &Ljcc); 281 __ j(sign, &Ljcc); 282 __ j(not_sign, &Ljcc); 283 __ j(parity_even, &Ljcc); 284 __ j(parity_odd, &Ljcc); 285 __ j(less, &Ljcc); 286 __ j(greater_equal, &Ljcc); 287 __ j(less_equal, &Ljcc); 288 __ j(greater, &Ljcc); 289 __ nop(); 290 __ bind(&Ljcc); 291 // short jumps 292 __ j(overflow, &Ljcc); 293 __ j(no_overflow, &Ljcc); 294 __ j(below, &Ljcc); 295 __ j(above_equal, &Ljcc); 296 __ j(equal, &Ljcc); 297 __ j(not_equal, &Ljcc); 298 __ j(below_equal, &Ljcc); 299 __ j(above, &Ljcc); 300 __ j(sign, &Ljcc); 301 __ j(not_sign, &Ljcc); 302 __ j(parity_even, &Ljcc); 303 __ j(parity_odd, &Ljcc); 304 __ j(less, &Ljcc); 305 __ j(greater_equal, &Ljcc); 306 __ j(less_equal, &Ljcc); 307 __ j(greater, &Ljcc); 308 309 // 0xD9 instructions 310 __ nop(); 311 312 __ fld(1); 313 __ fld1(); 314 __ fldz(); 315 __ fldpi(); 316 __ fabs(); 317 __ fchs(); 318 __ fprem(); 319 __ fprem1(); 320 __ fincstp(); 321 __ ftst(); 322 __ fxch(3); 323 __ fld_s(Operand(rbx, rcx, times_4, 10000)); 324 __ fstp_s(Operand(rbx, rcx, times_4, 10000)); 325 __ ffree(3); 326 __ fld_d(Operand(rbx, rcx, times_4, 10000)); 327 __ fstp_d(Operand(rbx, rcx, times_4, 10000)); 328 __ nop(); 329 330 __ fild_s(Operand(rbx, rcx, times_4, 10000)); 331 __ fistp_s(Operand(rbx, rcx, times_4, 10000)); 332 __ fild_d(Operand(rbx, rcx, times_4, 10000)); 333 __ fistp_d(Operand(rbx, rcx, times_4, 10000)); 334 __ fnstsw_ax(); 335 __ nop(); 336 __ fadd(3); 337 __ fsub(3); 338 __ fmul(3); 339 __ fdiv(3); 340 341 __ faddp(3); 342 __ fsubp(3); 343 __ fmulp(3); 344 __ fdivp(3); 345 __ fcompp(); 346 __ fwait(); 347 __ frndint(); 348 __ fninit(); 349 __ nop(); 350 351 // SSE instruction 352 { 353 // Move operation 354 __ cvttss2si(rdx, Operand(rbx, rcx, times_4, 10000)); 355 __ cvttss2si(rdx, xmm1); 356 __ movaps(xmm0, xmm1); 357 358 // logic operation 359 __ andps(xmm0, xmm1); 360 __ andps(xmm0, Operand(rbx, rcx, times_4, 10000)); 361 __ orps(xmm0, xmm1); 362 __ orps(xmm0, Operand(rbx, rcx, times_4, 10000)); 363 __ xorps(xmm0, xmm1); 364 __ xorps(xmm0, Operand(rbx, rcx, times_4, 10000)); 365 366 // Arithmetic operation 367 __ addps(xmm1, xmm0); 368 __ addps(xmm1, Operand(rbx, rcx, times_4, 10000)); 369 __ subps(xmm1, xmm0); 370 __ subps(xmm1, Operand(rbx, rcx, times_4, 10000)); 371 __ mulps(xmm1, xmm0); 372 __ mulps(xmm1, Operand(rbx, rcx, times_4, 10000)); 373 __ divps(xmm1, xmm0); 374 __ divps(xmm1, Operand(rbx, rcx, times_4, 10000)); 375 } 376 // SSE 2 instructions 377 { 378 __ cvttsd2si(rdx, Operand(rbx, rcx, times_4, 10000)); 379 __ cvttsd2si(rdx, xmm1); 380 __ cvttsd2siq(rdx, xmm1); 381 __ movsd(xmm1, Operand(rbx, rcx, times_4, 10000)); 382 __ movsd(Operand(rbx, rcx, times_4, 10000), xmm1); 383 // 128 bit move instructions. 384 __ movdqa(xmm0, Operand(rbx, rcx, times_4, 10000)); 385 __ movdqa(Operand(rbx, rcx, times_4, 10000), xmm0); 386 387 __ addsd(xmm1, xmm0); 388 __ mulsd(xmm1, xmm0); 389 __ subsd(xmm1, xmm0); 390 __ divsd(xmm1, xmm0); 391 __ ucomisd(xmm0, xmm1); 392 393 __ andpd(xmm0, xmm1); 394 } 395 396 // cmov. 397 { 398 __ cmovq(overflow, rax, Operand(rax, 0)); 399 __ cmovq(no_overflow, rax, Operand(rax, 1)); 400 __ cmovq(below, rax, Operand(rax, 2)); 401 __ cmovq(above_equal, rax, Operand(rax, 3)); 402 __ cmovq(equal, rax, Operand(rbx, 0)); 403 __ cmovq(not_equal, rax, Operand(rbx, 1)); 404 __ cmovq(below_equal, rax, Operand(rbx, 2)); 405 __ cmovq(above, rax, Operand(rbx, 3)); 406 __ cmovq(sign, rax, Operand(rcx, 0)); 407 __ cmovq(not_sign, rax, Operand(rcx, 1)); 408 __ cmovq(parity_even, rax, Operand(rcx, 2)); 409 __ cmovq(parity_odd, rax, Operand(rcx, 3)); 410 __ cmovq(less, rax, Operand(rdx, 0)); 411 __ cmovq(greater_equal, rax, Operand(rdx, 1)); 412 __ cmovq(less_equal, rax, Operand(rdx, 2)); 413 __ cmovq(greater, rax, Operand(rdx, 3)); 414 } 415 416 { 417 if (CpuFeatures::IsSupported(SSE4_1)) { 418 CpuFeatureScope scope(&assm, SSE4_1); 419 __ extractps(rax, xmm1, 0); 420 } 421 } 422 423 // Nop instructions 424 for (int i = 0; i < 16; i++) { 425 __ Nop(i); 426 } 427 428 __ ret(0); 429 430 CodeDesc desc; 431 assm.GetCode(&desc); 432 Handle<Code> code = isolate->factory()->NewCode( 433 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 434 USE(code); 435#ifdef OBJECT_PRINT 436 code->Print(); 437 byte* begin = code->instruction_start(); 438 byte* end = begin + code->instruction_size(); 439 disasm::Disassembler::Disassemble(stdout, begin, end); 440#endif 441} 442 443#undef __ 444