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