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 40 using namespace v8::internal; 41 42 43 #define __ assm. 44 45 46 static void DummyStaticFunction(Object* result) { 47 } 48 49 50 TEST(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 __ mul(edx); 172 __ neg(edx); 173 __ not_(edx); 174 __ test(Operand(ebx, ecx, times_4, 10000), Immediate(123456)); 175 176 __ imul(edx, Operand(ebx, ecx, times_4, 10000)); 177 __ imul(edx, ecx, 12); 178 __ imul(edx, ecx, 1000); 179 180 __ inc(edx); 181 __ inc(Operand(ebx, ecx, times_4, 10000)); 182 __ push(Operand(ebx, ecx, times_4, 10000)); 183 __ pop(Operand(ebx, ecx, times_4, 10000)); 184 __ call(Operand(ebx, ecx, times_4, 10000)); 185 __ jmp(Operand(ebx, ecx, times_4, 10000)); 186 187 __ lea(edx, Operand(ebx, ecx, times_4, 10000)); 188 __ or_(edx, 12345); 189 __ or_(edx, Operand(ebx, ecx, times_4, 10000)); 190 191 __ nop(); 192 193 __ rcl(edx, 1); 194 __ rcl(edx, 7); 195 __ rcr(edx, 1); 196 __ rcr(edx, 7); 197 __ sar(edx, 1); 198 __ sar(edx, 6); 199 __ sar_cl(edx); 200 __ sbb(edx, Operand(ebx, ecx, times_4, 10000)); 201 __ shld(edx, Operand(ebx, ecx, times_4, 10000)); 202 __ shl(edx, 1); 203 __ shl(edx, 6); 204 __ shl_cl(edx); 205 __ shrd(edx, Operand(ebx, ecx, times_4, 10000)); 206 __ shr(edx, 1); 207 __ shr(edx, 7); 208 __ shr_cl(edx); 209 210 211 // Immediates 212 213 __ adc(edx, 12345); 214 215 __ add(ebx, Immediate(12)); 216 __ add(Operand(edx, ecx, times_4, 10000), Immediate(12)); 217 218 __ and_(ebx, 12345); 219 220 __ cmp(ebx, 12345); 221 __ cmp(ebx, Immediate(12)); 222 __ cmp(Operand(edx, ecx, times_4, 10000), Immediate(12)); 223 __ cmpb(eax, 100); 224 225 __ or_(ebx, 12345); 226 227 __ sub(ebx, Immediate(12)); 228 __ sub(Operand(edx, ecx, times_4, 10000), Immediate(12)); 229 230 __ xor_(ebx, 12345); 231 232 __ imul(edx, ecx, 12); 233 __ imul(edx, ecx, 1000); 234 235 __ cld(); 236 __ rep_movs(); 237 __ rep_stos(); 238 __ stos(); 239 240 __ sub(edx, Operand(ebx, ecx, times_4, 10000)); 241 __ sub(edx, ebx); 242 243 __ test(edx, Immediate(12345)); 244 __ test(edx, Operand(ebx, ecx, times_8, 10000)); 245 __ test(Operand(esi, edi, times_1, -20000000), Immediate(300000000)); 246 __ test_b(edx, Operand(ecx, ebx, times_2, 1000)); 247 __ test_b(Operand(eax, -20), 0x9A); 248 __ nop(); 249 250 __ xor_(edx, 12345); 251 __ xor_(edx, Operand(ebx, ecx, times_8, 10000)); 252 __ bts(Operand(ebx, ecx, times_8, 10000), edx); 253 __ hlt(); 254 __ int3(); 255 __ ret(0); 256 __ ret(8); 257 258 // Calls 259 260 Label L1, L2; 261 __ bind(&L1); 262 __ nop(); 263 __ call(&L1); 264 __ call(&L2); 265 __ nop(); 266 __ bind(&L2); 267 __ call(Operand(ebx, ecx, times_4, 10000)); 268 __ nop(); 269 Handle<Code> ic(LoadIC::initialize_stub(isolate, NOT_CONTEXTUAL)); 270 __ call(ic, RelocInfo::CODE_TARGET); 271 __ nop(); 272 __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY); 273 __ nop(); 274 275 __ jmp(&L1); 276 __ jmp(Operand(ebx, ecx, times_4, 10000)); 277 ExternalReference after_break_target = 278 ExternalReference::debug_after_break_target_address(isolate); 279 __ jmp(Operand::StaticVariable(after_break_target)); 280 __ jmp(ic, RelocInfo::CODE_TARGET); 281 __ nop(); 282 283 284 Label Ljcc; 285 __ nop(); 286 // long 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 __ nop(); 304 __ bind(&Ljcc); 305 // short jumps 306 __ j(overflow, &Ljcc); 307 __ j(no_overflow, &Ljcc); 308 __ j(below, &Ljcc); 309 __ j(above_equal, &Ljcc); 310 __ j(equal, &Ljcc); 311 __ j(not_equal, &Ljcc); 312 __ j(below_equal, &Ljcc); 313 __ j(above, &Ljcc); 314 __ j(sign, &Ljcc); 315 __ j(not_sign, &Ljcc); 316 __ j(parity_even, &Ljcc); 317 __ j(parity_odd, &Ljcc); 318 __ j(less, &Ljcc); 319 __ j(greater_equal, &Ljcc); 320 __ j(less_equal, &Ljcc); 321 __ j(greater, &Ljcc); 322 323 // 0xD9 instructions 324 __ nop(); 325 326 __ fld(1); 327 __ fld1(); 328 __ fldz(); 329 __ fldpi(); 330 __ fabs(); 331 __ fchs(); 332 __ fprem(); 333 __ fprem1(); 334 __ fincstp(); 335 __ ftst(); 336 __ fxch(3); 337 __ fld_s(Operand(ebx, ecx, times_4, 10000)); 338 __ fstp_s(Operand(ebx, ecx, times_4, 10000)); 339 __ ffree(3); 340 __ fld_d(Operand(ebx, ecx, times_4, 10000)); 341 __ fstp_d(Operand(ebx, ecx, times_4, 10000)); 342 __ nop(); 343 344 __ fild_s(Operand(ebx, ecx, times_4, 10000)); 345 __ fistp_s(Operand(ebx, ecx, times_4, 10000)); 346 __ fild_d(Operand(ebx, ecx, times_4, 10000)); 347 __ fistp_d(Operand(ebx, ecx, times_4, 10000)); 348 __ fnstsw_ax(); 349 __ nop(); 350 __ fadd(3); 351 __ fsub(3); 352 __ fmul(3); 353 __ fdiv(3); 354 355 __ faddp(3); 356 __ fsubp(3); 357 __ fmulp(3); 358 __ fdivp(3); 359 __ fcompp(); 360 __ fwait(); 361 __ frndint(); 362 __ fninit(); 363 __ nop(); 364 365 // SSE instruction 366 { 367 // Move operation 368 __ movaps(xmm0, xmm1); 369 __ shufps(xmm0, xmm0, 0x0); 370 371 // logic operation 372 __ andps(xmm0, xmm1); 373 __ andps(xmm0, Operand(ebx, ecx, times_4, 10000)); 374 __ orps(xmm0, xmm1); 375 __ orps(xmm0, Operand(ebx, ecx, times_4, 10000)); 376 __ xorps(xmm0, xmm1); 377 __ xorps(xmm0, Operand(ebx, ecx, times_4, 10000)); 378 379 // Arithmetic operation 380 __ addps(xmm1, xmm0); 381 __ addps(xmm1, Operand(ebx, ecx, times_4, 10000)); 382 __ subps(xmm1, xmm0); 383 __ subps(xmm1, Operand(ebx, ecx, times_4, 10000)); 384 __ mulps(xmm1, xmm0); 385 __ mulps(xmm1, Operand(ebx, ecx, times_4, 10000)); 386 __ divps(xmm1, xmm0); 387 __ divps(xmm1, Operand(ebx, ecx, times_4, 10000)); 388 } 389 { 390 __ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000)); 391 __ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000)); 392 __ movsd(xmm1, Operand(ebx, ecx, times_4, 10000)); 393 __ movsd(Operand(ebx, ecx, times_4, 10000), xmm1); 394 // 128 bit move instructions. 395 __ movdqa(xmm0, Operand(ebx, ecx, times_4, 10000)); 396 __ movdqa(Operand(ebx, ecx, times_4, 10000), xmm0); 397 __ movdqu(xmm0, Operand(ebx, ecx, times_4, 10000)); 398 __ movdqu(Operand(ebx, ecx, times_4, 10000), xmm0); 399 400 __ addsd(xmm1, xmm0); 401 __ mulsd(xmm1, xmm0); 402 __ subsd(xmm1, xmm0); 403 __ divsd(xmm1, xmm0); 404 __ ucomisd(xmm0, xmm1); 405 __ cmpltsd(xmm0, xmm1); 406 407 __ andpd(xmm0, xmm1); 408 __ psllq(xmm0, 17); 409 __ psllq(xmm0, xmm1); 410 __ psrlq(xmm0, 17); 411 __ psrlq(xmm0, xmm1); 412 __ por(xmm0, xmm1); 413 } 414 415 // cmov. 416 { 417 __ cmov(overflow, eax, Operand(eax, 0)); 418 __ cmov(no_overflow, eax, Operand(eax, 1)); 419 __ cmov(below, eax, Operand(eax, 2)); 420 __ cmov(above_equal, eax, Operand(eax, 3)); 421 __ cmov(equal, eax, Operand(ebx, 0)); 422 __ cmov(not_equal, eax, Operand(ebx, 1)); 423 __ cmov(below_equal, eax, Operand(ebx, 2)); 424 __ cmov(above, eax, Operand(ebx, 3)); 425 __ cmov(sign, eax, Operand(ecx, 0)); 426 __ cmov(not_sign, eax, Operand(ecx, 1)); 427 __ cmov(parity_even, eax, Operand(ecx, 2)); 428 __ cmov(parity_odd, eax, Operand(ecx, 3)); 429 __ cmov(less, eax, Operand(edx, 0)); 430 __ cmov(greater_equal, eax, Operand(edx, 1)); 431 __ cmov(less_equal, eax, Operand(edx, 2)); 432 __ cmov(greater, eax, Operand(edx, 3)); 433 } 434 435 { 436 if (CpuFeatures::IsSupported(SSE4_1)) { 437 CpuFeatureScope scope(&assm, SSE4_1); 438 __ pextrd(eax, xmm0, 1); 439 __ pinsrd(xmm1, eax, 0); 440 __ extractps(eax, xmm1, 0); 441 } 442 } 443 444 // Nop instructions 445 for (int i = 0; i < 16; i++) { 446 __ Nop(i); 447 } 448 449 __ ret(0); 450 451 CodeDesc desc; 452 assm.GetCode(&desc); 453 Handle<Code> code = isolate->factory()->NewCode( 454 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 455 USE(code); 456 #ifdef OBJECT_PRINT 457 code->Print(); 458 byte* begin = code->instruction_start(); 459 byte* end = begin + code->instruction_size(); 460 disasm::Disassembler::Disassemble(stdout, begin, end); 461 #endif 462 } 463 464 #undef __ 465