Chromium Code Reviews| Index: src/x64/assembler-x64.cc |
| =================================================================== |
| --- src/x64/assembler-x64.cc (revision 2056) |
| +++ src/x64/assembler-x64.cc (working copy) |
| @@ -189,10 +189,34 @@ |
| UNIMPLEMENTED(); |
| } |
| -void Assembler::bind(Label* a) { |
| - UNIMPLEMENTED(); |
| + |
| +void Assembler::bind_to(Label* L, int pos) { |
| + ASSERT(!L->is_bound()); // Label may only be bound once. |
| + last_pc_ = NULL; |
| + ASSERT(0 <= pos && pos <= pc_offset()); // Position must be valid. |
| + if (L->is_linked()) { |
| + int current = L->pos(); |
| + int next = long_at(current); |
| + while (next != current) { |
| + // relative address, relative to point after address |
| + int imm32 = pos - (current + sizeof(int32_t)); |
| + long_at_put(current, imm32); |
| + current = next; |
| + next = long_at(next); |
| + } |
| + // Fix up last fixup on linked list. |
| + int last_imm32 = pos - (current + sizeof(int32_t)); |
| + long_at_put(current, last_imm32); |
| + } |
| + L->bind_to(pos); |
| } |
| + |
| +void Assembler::bind(Label* L) { |
| + bind_to(L, pc_offset()); |
| +} |
| + |
| + |
| void Assembler::GrowBuffer() { |
| ASSERT(overflow()); // should not call this otherwise |
| if (!own_buffer_) FATAL("external code buffer is too small"); |
| @@ -275,6 +299,8 @@ |
| } |
| +// Assembler Instruction implementations |
| + |
| void Assembler::add(Register dst, const Operand& src) { |
| EnsureSpace ensure_space(this); |
| last_pc_ = pc_; |
| @@ -289,10 +315,31 @@ |
| last_pc_ = pc_; |
| emit_rex_64(dst, src); |
| EMIT(0x03); |
| - EMIT(0xC0 | (src.code() & 0x7) << 3 | (dst.code() & 0x7)); |
| + EMIT(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); |
|
Lasse Reichstein
2009/05/26 12:14:41
Was this incorrect before?
William Hesse
2009/05/26 15:15:32
Yes it was. Cases with two register operands shou
|
| } |
| +void Assembler::call(Label* L) { |
| + EnsureSpace ensure_space(this); |
| + last_pc_ = pc_; |
| + // 1110 1000 #32-bit disp |
| + EMIT(0xE8); |
| + if (L->is_bound()) { |
| + int offset = L->pos() - pc_offset() - sizeof(int32_t); |
| + ASSERT(offset <= 0); |
| + emit(offset); |
| + } else if (L->is_linked()) { |
| + emit(L->pos()); |
| + L->link_to(pc_offset() - sizeof(int32_t)); |
| + } else { |
| + ASSERT(L->is_unused()); |
| + int32_t current = pc_offset(); |
| + emit(current); |
| + L->link_to(current); |
| + } |
| +} |
| + |
| + |
| void Assembler::dec(Register dst) { |
| EnsureSpace ensure_space(this); |
| last_pc_ = pc_; |
| @@ -343,6 +390,73 @@ |
| } |
| +void Assembler::j(Condition cc, Label* L) { |
| + EnsureSpace ensure_space(this); |
| + last_pc_ = pc_; |
| + ASSERT(0 <= cc && cc < 16); |
| + if (L->is_bound()) { |
| + const int short_size = 2; |
| + const int long_size = 6; |
| + int offs = L->pos() - pc_offset(); |
| + ASSERT(offs <= 0); |
| + if (is_int8(offs - short_size)) { |
| + // 0111 tttn #8-bit disp |
| + EMIT(0x70 | cc); |
| + EMIT((offs - short_size) & 0xFF); |
| + } else { |
| + // 0000 1111 1000 tttn #32-bit disp |
| + EMIT(0x0F); |
| + EMIT(0x80 | cc); |
| + emit(offs - long_size); |
| + } |
| + } else if (L->is_linked()) { |
| + // 0000 1111 1000 tttn #32-bit disp |
| + EMIT(0x0F); |
| + EMIT(0x80 | cc); |
| + emit(L->pos()); |
| + L->link_to(pc_offset() - sizeof(int32_t)); |
| + } else { |
| + ASSERT(L->is_unused()); |
| + EMIT(0x0F); |
| + EMIT(0x80 | cc); |
| + int32_t current = pc_offset(); |
| + emit(current); |
| + L->link_to(current); |
| + } |
| +} |
| + |
| + |
| +void Assembler::jmp(Label* L) { |
| + EnsureSpace ensure_space(this); |
| + last_pc_ = pc_; |
| + if (L->is_bound()) { |
| + int offs = L->pos() - pc_offset() - 1; |
| + ASSERT(offs <= 0); |
| + if (is_int8(offs - sizeof(int8_t))) { |
| + // 1110 1011 #8-bit disp |
| + EMIT(0xEB); |
| + EMIT((offs - sizeof(int8_t)) & 0xFF); |
| + } else { |
| + // 1110 1001 #32-bit disp |
| + EMIT(0xE9); |
| + emit(offs - sizeof(int32_t)); |
| + } |
| + } else if (L->is_linked()) { |
| + // 1110 1001 #32-bit disp |
| + EMIT(0xE9); |
| + emit(L->pos()); |
| + L->link_to(pc_offset() - sizeof(int32_t)); |
| + } else { |
| + // 1110 1001 #32-bit disp |
| + ASSERT(L->is_unused()); |
| + EMIT(0xE9); |
| + int32_t current = pc_offset(); |
| + emit(current); |
| + L->link_to(current); |
| + } |
| +} |
| + |
| + |
| void Assembler::mov(Register dst, const Operand& src) { |
| EnsureSpace ensure_space(this); |
| last_pc_ = pc_; |
| @@ -356,8 +470,8 @@ |
| EnsureSpace ensure_space(this); |
| last_pc_ = pc_; |
| emit_rex_64(dst, src); |
| - EMIT(0x89); |
| - EMIT(0xC0 | (src.code() & 0x7) << 3 | (dst.code() & 0x7)); |
| + EMIT(0x8B); |
| + EMIT(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); |
| } |