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