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