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