OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 uint64_t CpuFeatures::supported_ = 0; | 75 uint64_t CpuFeatures::supported_ = 0; |
76 uint64_t CpuFeatures::enabled_ = 0; | 76 uint64_t CpuFeatures::enabled_ = 0; |
77 | 77 |
78 void CpuFeatures::Probe() { | 78 void CpuFeatures::Probe() { |
79 // TODO(X64): UNIMPLEMENTED | 79 // TODO(X64): UNIMPLEMENTED |
80 } | 80 } |
81 | 81 |
82 // ----------------------------------------------------------------------------- | 82 // ----------------------------------------------------------------------------- |
83 // Implementation of Assembler | 83 // Implementation of Assembler |
84 | 84 |
85 // Emit a single byte. Must always be inlined. | |
86 #define EMIT(x) \ | |
87 *pc_++ = (x) | |
88 | |
89 #ifdef GENERATED_CODE_COVERAGE | 85 #ifdef GENERATED_CODE_COVERAGE |
90 static void InitCoverageLog(); | 86 static void InitCoverageLog(); |
91 #endif | 87 #endif |
92 | 88 |
93 byte* Assembler::spare_buffer_ = NULL; | 89 byte* Assembler::spare_buffer_ = NULL; |
94 | 90 |
95 Assembler::Assembler(void* buffer, int buffer_size) { | 91 Assembler::Assembler(void* buffer, int buffer_size) { |
96 if (buffer == NULL) { | 92 if (buffer == NULL) { |
97 // do our own buffer management | 93 // do our own buffer management |
98 if (buffer_size <= kMinimalBufferSize) { | 94 if (buffer_size <= kMinimalBufferSize) { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 pc_ += length; | 294 pc_ += length; |
299 } | 295 } |
300 | 296 |
301 | 297 |
302 // Assembler Instruction implementations | 298 // Assembler Instruction implementations |
303 | 299 |
304 void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) { | 300 void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) { |
305 EnsureSpace ensure_space(this); | 301 EnsureSpace ensure_space(this); |
306 last_pc_ = pc_; | 302 last_pc_ = pc_; |
307 emit_rex_64(reg, op); | 303 emit_rex_64(reg, op); |
308 EMIT(opcode); | 304 emit(opcode); |
309 emit_operand(reg, op); | 305 emit_operand(reg, op); |
310 } | 306 } |
311 | 307 |
312 | 308 |
313 void Assembler::arithmetic_op(byte opcode, Register dst, Register src) { | 309 void Assembler::arithmetic_op(byte opcode, Register dst, Register src) { |
314 EnsureSpace ensure_space(this); | 310 EnsureSpace ensure_space(this); |
315 last_pc_ = pc_; | 311 last_pc_ = pc_; |
316 emit_rex_64(dst, src); | 312 emit_rex_64(dst, src); |
317 EMIT(opcode); | 313 emit(opcode); |
318 EMIT(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); | 314 emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); |
319 } | 315 } |
320 | 316 |
321 void Assembler::immediate_arithmetic_op(byte subcode, | 317 void Assembler::immediate_arithmetic_op(byte subcode, |
322 Register dst, | 318 Register dst, |
323 Immediate src) { | 319 Immediate src) { |
324 EnsureSpace ensure_space(this); | 320 EnsureSpace ensure_space(this); |
325 last_pc_ = pc_; | 321 last_pc_ = pc_; |
326 emit_rex_64(rax, dst); | 322 emit_rex_64(rax, dst); |
327 if (is_int8(src.value_)) { | 323 if (is_int8(src.value_)) { |
328 EMIT(0x83); | 324 emit(0x83); |
329 EMIT(0xC0 | (subcode << 3) | (dst.code() & 0x7)); | 325 emit(0xC0 | (subcode << 3) | (dst.code() & 0x7)); |
330 EMIT(src.value_); | 326 emit(src.value_); |
331 } else { | 327 } else { |
332 EMIT(0x81); | 328 emit(0x81); |
333 EMIT(0xC0 | (subcode << 3) | (dst.code() & 0x7)); | 329 emit(0xC0 | (subcode << 3) | (dst.code() & 0x7)); |
334 emitl(src.value_); | 330 emitl(src.value_); |
335 } | 331 } |
336 } | 332 } |
337 | 333 |
338 void Assembler::immediate_arithmetic_op(byte subcode, | 334 void Assembler::immediate_arithmetic_op(byte subcode, |
339 const Operand& dst, | 335 const Operand& dst, |
340 Immediate src) { | 336 Immediate src) { |
341 EnsureSpace ensure_space(this); | 337 EnsureSpace ensure_space(this); |
342 last_pc_ = pc_; | 338 last_pc_ = pc_; |
343 emit_rex_64(rax, dst); | 339 emit_rex_64(rax, dst); |
344 if (is_int8(src.value_)) { | 340 if (is_int8(src.value_)) { |
345 EMIT(0x83); | 341 emit(0x83); |
346 emit_operand(Register::toRegister(subcode), dst); | 342 emit_operand(Register::toRegister(subcode), dst); |
347 EMIT(src.value_); | 343 emit(src.value_); |
348 } else { | 344 } else { |
349 EMIT(0x81); | 345 emit(0x81); |
350 emit_operand(Register::toRegister(subcode), dst); | 346 emit_operand(Register::toRegister(subcode), dst); |
351 emitl(src.value_); | 347 emitl(src.value_); |
352 } | 348 } |
353 } | 349 } |
354 | 350 |
355 | 351 |
356 void Assembler::call(Label* L) { | 352 void Assembler::call(Label* L) { |
357 EnsureSpace ensure_space(this); | 353 EnsureSpace ensure_space(this); |
358 last_pc_ = pc_; | 354 last_pc_ = pc_; |
359 // 1110 1000 #32-bit disp | 355 // 1110 1000 #32-bit disp |
360 EMIT(0xE8); | 356 emit(0xE8); |
361 if (L->is_bound()) { | 357 if (L->is_bound()) { |
362 int offset = L->pos() - pc_offset() - sizeof(int32_t); | 358 int offset = L->pos() - pc_offset() - sizeof(int32_t); |
363 ASSERT(offset <= 0); | 359 ASSERT(offset <= 0); |
364 emitl(offset); | 360 emitl(offset); |
365 } else if (L->is_linked()) { | 361 } else if (L->is_linked()) { |
366 emitl(L->pos()); | 362 emitl(L->pos()); |
367 L->link_to(pc_offset() - sizeof(int32_t)); | 363 L->link_to(pc_offset() - sizeof(int32_t)); |
368 } else { | 364 } else { |
369 ASSERT(L->is_unused()); | 365 ASSERT(L->is_unused()); |
370 int32_t current = pc_offset(); | 366 int32_t current = pc_offset(); |
371 emitl(current); | 367 emitl(current); |
372 L->link_to(current); | 368 L->link_to(current); |
373 } | 369 } |
374 } | 370 } |
375 | 371 |
376 | 372 |
377 void Assembler::dec(Register dst) { | 373 void Assembler::dec(Register dst) { |
378 EnsureSpace ensure_space(this); | 374 EnsureSpace ensure_space(this); |
379 last_pc_ = pc_; | 375 last_pc_ = pc_; |
380 emit_rex_64(rcx, dst); | 376 emit_rex_64(rcx, dst); |
381 EMIT(0xFF); | 377 emit(0xFF); |
382 EMIT(0xC8 | (dst.code() & 0x7)); | 378 emit(0xC8 | (dst.code() & 0x7)); |
383 } | 379 } |
384 | 380 |
385 | 381 |
386 void Assembler::dec(const Operand& dst) { | 382 void Assembler::dec(const Operand& dst) { |
387 EnsureSpace ensure_space(this); | 383 EnsureSpace ensure_space(this); |
388 last_pc_ = pc_; | 384 last_pc_ = pc_; |
389 emit_rex_64(rax, dst); | 385 emit_rex_64(rax, dst); |
390 EMIT(0xFF); | 386 emit(0xFF); |
391 emit_operand(rcx, dst); | 387 emit_operand(rcx, dst); |
392 } | 388 } |
393 | 389 |
394 | 390 |
395 void Assembler::hlt() { | 391 void Assembler::hlt() { |
396 EnsureSpace ensure_space(this); | 392 EnsureSpace ensure_space(this); |
397 last_pc_ = pc_; | 393 last_pc_ = pc_; |
398 EMIT(0xF4); | 394 emit(0xF4); |
399 } | 395 } |
400 | 396 |
401 | 397 |
402 void Assembler::inc(Register dst) { | 398 void Assembler::inc(Register dst) { |
403 EnsureSpace ensure_space(this); | 399 EnsureSpace ensure_space(this); |
404 last_pc_ = pc_; | 400 last_pc_ = pc_; |
405 emit_rex_64(rax, dst); | 401 emit_rex_64(rax, dst); |
406 EMIT(0xFF); | 402 emit(0xFF); |
407 EMIT(0xC0 | (dst.code() & 0x7)); | 403 emit(0xC0 | (dst.code() & 0x7)); |
408 } | 404 } |
409 | 405 |
410 | 406 |
411 void Assembler::inc(const Operand& dst) { | 407 void Assembler::inc(const Operand& dst) { |
412 EnsureSpace ensure_space(this); | 408 EnsureSpace ensure_space(this); |
413 last_pc_ = pc_; | 409 last_pc_ = pc_; |
414 emit_rex_64(rax, dst); | 410 emit_rex_64(rax, dst); |
415 EMIT(0xFF); | 411 emit(0xFF); |
416 emit_operand(rax, dst); | 412 emit_operand(rax, dst); |
417 } | 413 } |
418 | 414 |
419 | 415 |
420 void Assembler::int3() { | 416 void Assembler::int3() { |
421 EnsureSpace ensure_space(this); | 417 EnsureSpace ensure_space(this); |
422 last_pc_ = pc_; | 418 last_pc_ = pc_; |
423 EMIT(0xCC); | 419 emit(0xCC); |
424 } | 420 } |
425 | 421 |
426 | 422 |
427 void Assembler::j(Condition cc, Label* L) { | 423 void Assembler::j(Condition cc, Label* L) { |
428 EnsureSpace ensure_space(this); | 424 EnsureSpace ensure_space(this); |
429 last_pc_ = pc_; | 425 last_pc_ = pc_; |
430 ASSERT(0 <= cc && cc < 16); | 426 ASSERT(0 <= cc && cc < 16); |
431 if (L->is_bound()) { | 427 if (L->is_bound()) { |
432 const int short_size = 2; | 428 const int short_size = 2; |
433 const int long_size = 6; | 429 const int long_size = 6; |
434 int offs = L->pos() - pc_offset(); | 430 int offs = L->pos() - pc_offset(); |
435 ASSERT(offs <= 0); | 431 ASSERT(offs <= 0); |
436 if (is_int8(offs - short_size)) { | 432 if (is_int8(offs - short_size)) { |
437 // 0111 tttn #8-bit disp | 433 // 0111 tttn #8-bit disp |
438 EMIT(0x70 | cc); | 434 emit(0x70 | cc); |
439 EMIT((offs - short_size) & 0xFF); | 435 emit((offs - short_size) & 0xFF); |
440 } else { | 436 } else { |
441 // 0000 1111 1000 tttn #32-bit disp | 437 // 0000 1111 1000 tttn #32-bit disp |
442 EMIT(0x0F); | 438 emit(0x0F); |
443 EMIT(0x80 | cc); | 439 emit(0x80 | cc); |
444 emitl(offs - long_size); | 440 emitl(offs - long_size); |
445 } | 441 } |
446 } else if (L->is_linked()) { | 442 } else if (L->is_linked()) { |
447 // 0000 1111 1000 tttn #32-bit disp | 443 // 0000 1111 1000 tttn #32-bit disp |
448 EMIT(0x0F); | 444 emit(0x0F); |
449 EMIT(0x80 | cc); | 445 emit(0x80 | cc); |
450 emitl(L->pos()); | 446 emitl(L->pos()); |
451 L->link_to(pc_offset() - sizeof(int32_t)); | 447 L->link_to(pc_offset() - sizeof(int32_t)); |
452 } else { | 448 } else { |
453 ASSERT(L->is_unused()); | 449 ASSERT(L->is_unused()); |
454 EMIT(0x0F); | 450 emit(0x0F); |
455 EMIT(0x80 | cc); | 451 emit(0x80 | cc); |
456 int32_t current = pc_offset(); | 452 int32_t current = pc_offset(); |
457 emitl(current); | 453 emitl(current); |
458 L->link_to(current); | 454 L->link_to(current); |
459 } | 455 } |
460 } | 456 } |
461 | 457 |
462 | 458 |
463 void Assembler::jmp(Label* L) { | 459 void Assembler::jmp(Label* L) { |
464 EnsureSpace ensure_space(this); | 460 EnsureSpace ensure_space(this); |
465 last_pc_ = pc_; | 461 last_pc_ = pc_; |
466 if (L->is_bound()) { | 462 if (L->is_bound()) { |
467 int offs = L->pos() - pc_offset() - 1; | 463 int offs = L->pos() - pc_offset() - 1; |
468 ASSERT(offs <= 0); | 464 ASSERT(offs <= 0); |
469 if (is_int8(offs - sizeof(int8_t))) { | 465 if (is_int8(offs - sizeof(int8_t))) { |
470 // 1110 1011 #8-bit disp | 466 // 1110 1011 #8-bit disp |
471 EMIT(0xEB); | 467 emit(0xEB); |
472 EMIT((offs - sizeof(int8_t)) & 0xFF); | 468 emit((offs - sizeof(int8_t)) & 0xFF); |
473 } else { | 469 } else { |
474 // 1110 1001 #32-bit disp | 470 // 1110 1001 #32-bit disp |
475 EMIT(0xE9); | 471 emit(0xE9); |
476 emitl(offs - sizeof(int32_t)); | 472 emitl(offs - sizeof(int32_t)); |
477 } | 473 } |
478 } else if (L->is_linked()) { | 474 } else if (L->is_linked()) { |
479 // 1110 1001 #32-bit disp | 475 // 1110 1001 #32-bit disp |
480 EMIT(0xE9); | 476 emit(0xE9); |
481 emitl(L->pos()); | 477 emitl(L->pos()); |
482 L->link_to(pc_offset() - sizeof(int32_t)); | 478 L->link_to(pc_offset() - sizeof(int32_t)); |
483 } else { | 479 } else { |
484 // 1110 1001 #32-bit disp | 480 // 1110 1001 #32-bit disp |
485 ASSERT(L->is_unused()); | 481 ASSERT(L->is_unused()); |
486 EMIT(0xE9); | 482 emit(0xE9); |
487 int32_t current = pc_offset(); | 483 int32_t current = pc_offset(); |
488 emitl(current); | 484 emitl(current); |
489 L->link_to(current); | 485 L->link_to(current); |
490 } | 486 } |
491 } | 487 } |
492 | 488 |
493 | 489 |
494 void Assembler::movq(Register dst, const Operand& src) { | 490 void Assembler::movq(Register dst, const Operand& src) { |
495 EnsureSpace ensure_space(this); | 491 EnsureSpace ensure_space(this); |
496 last_pc_ = pc_; | 492 last_pc_ = pc_; |
497 emit_rex_64(dst, src); | 493 emit_rex_64(dst, src); |
498 EMIT(0x8B); | 494 emit(0x8B); |
499 emit_operand(dst, src); | 495 emit_operand(dst, src); |
500 } | 496 } |
501 | 497 |
502 | 498 |
503 void Assembler::movq(Register dst, Register src) { | 499 void Assembler::movq(Register dst, Register src) { |
504 EnsureSpace ensure_space(this); | 500 EnsureSpace ensure_space(this); |
505 last_pc_ = pc_; | 501 last_pc_ = pc_; |
506 emit_rex_64(dst, src); | 502 emit_rex_64(dst, src); |
507 EMIT(0x8B); | 503 emit(0x8B); |
508 EMIT(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); | 504 emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); |
509 } | 505 } |
510 | 506 |
511 | 507 |
512 void Assembler::movq(Register dst, Immediate value) { | 508 void Assembler::movq(Register dst, Immediate value) { |
513 EnsureSpace ensure_space(this); | 509 EnsureSpace ensure_space(this); |
514 last_pc_ = pc_; | 510 last_pc_ = pc_; |
515 emit_rex_64(rax, dst); | 511 emit_rex_64(rax, dst); |
516 EMIT(0xC7); | 512 emit(0xC7); |
517 EMIT(0xC0 | (dst.code() & 0x7)); | 513 emit(0xC0 | (dst.code() & 0x7)); |
518 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates. | 514 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates. |
519 } | 515 } |
520 | 516 |
521 | 517 |
522 void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) { | 518 void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) { |
523 EnsureSpace ensure_space(this); | 519 EnsureSpace ensure_space(this); |
524 last_pc_ = pc_; | 520 last_pc_ = pc_; |
525 emit_rex_64(rax, dst); | 521 emit_rex_64(rax, dst); |
526 EMIT(0xB8 | (dst.code() & 0x7)); | 522 emit(0xB8 | (dst.code() & 0x7)); |
527 emitq(value, rmode); | 523 emitq(value, rmode); |
528 } | 524 } |
529 | 525 |
530 | 526 |
531 void Assembler::nop() { | 527 void Assembler::nop() { |
532 EnsureSpace ensure_space(this); | 528 EnsureSpace ensure_space(this); |
533 last_pc_ = pc_; | 529 last_pc_ = pc_; |
534 EMIT(0x90); | 530 emit(0x90); |
535 } | 531 } |
536 | 532 |
537 | 533 |
538 void Assembler::pop(Register dst) { | 534 void Assembler::pop(Register dst) { |
539 EnsureSpace ensure_space(this); | 535 EnsureSpace ensure_space(this); |
540 last_pc_ = pc_; | 536 last_pc_ = pc_; |
541 if (dst.code() & 0x8) { | 537 if (dst.code() & 0x8) { |
542 emit_rex_64(rax, dst); | 538 emit_rex_64(rax, dst); |
543 } | 539 } |
544 EMIT(0x58 | (dst.code() & 0x7)); | 540 emit(0x58 | (dst.code() & 0x7)); |
545 } | 541 } |
546 | 542 |
547 | 543 |
548 void Assembler::pop(const Operand& dst) { | 544 void Assembler::pop(const Operand& dst) { |
549 EnsureSpace ensure_space(this); | 545 EnsureSpace ensure_space(this); |
550 last_pc_ = pc_; | 546 last_pc_ = pc_; |
551 emit_rex_64(rax, dst); // Could be omitted in some cases. | 547 emit_rex_64(rax, dst); // Could be omitted in some cases. |
552 EMIT(0x8F); | 548 emit(0x8F); |
553 emit_operand(rax, dst); | 549 emit_operand(rax, dst); |
554 } | 550 } |
555 | 551 |
556 | 552 |
557 void Assembler::push(Register src) { | 553 void Assembler::push(Register src) { |
558 EnsureSpace ensure_space(this); | 554 EnsureSpace ensure_space(this); |
559 last_pc_ = pc_; | 555 last_pc_ = pc_; |
560 if (src.code() & 0x8) { | 556 if (src.code() & 0x8) { |
561 emit_rex_64(rax, src); | 557 emit_rex_64(rax, src); |
562 } | 558 } |
563 EMIT(0x50 | (src.code() & 0x7)); | 559 emit(0x50 | (src.code() & 0x7)); |
564 } | 560 } |
565 | 561 |
566 | 562 |
567 void Assembler::push(const Operand& src) { | 563 void Assembler::push(const Operand& src) { |
568 EnsureSpace ensure_space(this); | 564 EnsureSpace ensure_space(this); |
569 last_pc_ = pc_; | 565 last_pc_ = pc_; |
570 emit_rex_64(rsi, src); // Could be omitted in some cases. | 566 emit_rex_64(rsi, src); // Could be omitted in some cases. |
571 EMIT(0xFF); | 567 emit(0xFF); |
572 emit_operand(rsi, src); | 568 emit_operand(rsi, src); |
573 } | 569 } |
574 | 570 |
575 | 571 |
576 void Assembler::ret(int imm16) { | 572 void Assembler::ret(int imm16) { |
577 EnsureSpace ensure_space(this); | 573 EnsureSpace ensure_space(this); |
578 last_pc_ = pc_; | 574 last_pc_ = pc_; |
579 ASSERT(is_uint16(imm16)); | 575 ASSERT(is_uint16(imm16)); |
580 if (imm16 == 0) { | 576 if (imm16 == 0) { |
581 EMIT(0xC3); | 577 emit(0xC3); |
582 } else { | 578 } else { |
583 EMIT(0xC2); | 579 emit(0xC2); |
584 EMIT(imm16 & 0xFF); | 580 emit(imm16 & 0xFF); |
585 EMIT((imm16 >> 8) & 0xFF); | 581 emit((imm16 >> 8) & 0xFF); |
586 } | 582 } |
587 } | 583 } |
588 | 584 |
589 } } // namespace v8::internal | 585 } } // namespace v8::internal |
590 | 586 |
591 | 587 |
592 // TODO(x64): Implement and move these to their correct cc-files: | 588 // TODO(x64): Implement and move these to their correct cc-files: |
593 #include "ast.h" | 589 #include "ast.h" |
594 #include "bootstrapper.h" | 590 #include "bootstrapper.h" |
595 #include "codegen-inl.h" | 591 #include "codegen-inl.h" |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 UNIMPLEMENTED(); | 856 UNIMPLEMENTED(); |
861 return NULL; | 857 return NULL; |
862 } | 858 } |
863 | 859 |
864 byte* JavaScriptFrame::GetCallerStackPointer() const { | 860 byte* JavaScriptFrame::GetCallerStackPointer() const { |
865 UNIMPLEMENTED(); | 861 UNIMPLEMENTED(); |
866 return NULL; | 862 return NULL; |
867 } | 863 } |
868 | 864 |
869 } } // namespace v8::internal | 865 } } // namespace v8::internal |
OLD | NEW |