Author: whe...@chromium.org Date: Wed Jun 10 08:53:46 2009 New Revision: 2139
Modified: branches/bleeding_edge/src/x64/assembler-x64.cc branches/bleeding_edge/src/x64/assembler-x64.h branches/bleeding_edge/src/x64/builtins-x64.cc branches/bleeding_edge/src/x64/codegen-x64.cc branches/bleeding_edge/src/x64/macro-assembler-x64.cc branches/bleeding_edge/src/x64/macro-assembler-x64.h branches/bleeding_edge/test/cctest/test-assembler-x64.cc Log: Add statistics operations and long calls and jumps to x64 macro assembler. Remove unimplemented instructions from x64 assembler. Add operand-size suffixes to add, sub, inc, dec, and cmp. Review URL: http://codereview.chromium.org/118380 Modified: branches/bleeding_edge/src/x64/assembler-x64.cc ============================================================================== --- branches/bleeding_edge/src/x64/assembler-x64.cc (original) +++ branches/bleeding_edge/src/x64/assembler-x64.cc Wed Jun 10 08:53:46 2009 @@ -451,6 +451,24 @@ } +void Assembler::immediate_arithmetic_op_32(byte subcode, + const Operand& dst, + Immediate src) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_optional_rex_32(dst); + if (is_int8(src.value_)) { + emit(0x83); + emit_operand(Register::toRegister(subcode), dst); + emit(src.value_); + } else { + emit(0x81); + emit_operand(Register::toRegister(subcode), dst); + emitl(src.value_); + } +} + + void Assembler::shift(Register dst, Immediate shift_amount, int subcode) { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -530,15 +548,6 @@ } -void Assembler::cpuid() { - ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID)); - EnsureSpace ensure_space(this); - last_pc_ = pc_; - emit(0x0F); - emit(0xA2); -} - - void Assembler::call(const Operand& op) { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -549,6 +558,15 @@ } +void Assembler::cpuid() { + ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID)); + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit(0x0F); + emit(0xA2); +} + + void Assembler::cqo() { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -557,7 +575,7 @@ } -void Assembler::dec(Register dst) { +void Assembler::decq(Register dst) { EnsureSpace ensure_space(this); last_pc_ = pc_; emit_rex_64(dst); @@ -566,7 +584,7 @@ } -void Assembler::dec(const Operand& dst) { +void Assembler::decq(const Operand& dst) { EnsureSpace ensure_space(this); last_pc_ = pc_; emit_rex_64(dst); @@ -575,6 +593,15 @@ } +void Assembler::decl(const Operand& dst) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_optional_rex_32(dst); + emit(0xFF); + emit_operand(1, dst); +} + + void Assembler::enter(Immediate size) { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -626,7 +653,7 @@ } -void Assembler::inc(Register dst) { +void Assembler::incq(Register dst) { EnsureSpace ensure_space(this); last_pc_ = pc_; emit_rex_64(dst); @@ -635,7 +662,7 @@ } -void Assembler::inc(const Operand& dst) { +void Assembler::incq(const Operand& dst) { EnsureSpace ensure_space(this); last_pc_ = pc_; emit_rex_64(dst); @@ -644,6 +671,15 @@ } +void Assembler::incl(const Operand& dst) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_optional_rex_32(dst); + emit(0xFF); + emit_operand(0, dst); +} + + void Assembler::int3() { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -812,6 +848,16 @@ } +void Assembler::movl(const Operand& dst, Immediate value) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_optional_rex_32(dst); + emit(0xC7); + emit_operand(0x0, dst); + emit(value); // Only 32-bit immediates are possible, not 8-bit immediates. +} + + void Assembler::movl(Register dst, Immediate value) { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -1132,6 +1178,13 @@ } } +void Assembler::rdtsc() { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit(0x0F); + emit(0x31); +} + void Assembler::ret(int imm16) { EnsureSpace ensure_space(this); @@ -1144,6 +1197,19 @@ emit(imm16 & 0xFF); emit((imm16 >> 8) & 0xFF); } +} + + +void Assembler::setcc(Condition cc, Register reg) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + ASSERT(0 <= cc && cc < 16); + if (reg.code() > 3) { // Use x64 byte registers, where different. + emit_rex_32(reg); + } + emit(0x0F); + emit(0x90 | cc); + emit_modrm(0x0, reg); } Modified: branches/bleeding_edge/src/x64/assembler-x64.h ============================================================================== --- branches/bleeding_edge/src/x64/assembler-x64.h (original) +++ branches/bleeding_edge/src/x64/assembler-x64.h Wed Jun 10 08:53:46 2009 @@ -385,7 +385,8 @@ // // If we need versions of an assembly instruction that operate on different // width arguments, we add a single-letter suffix specifying the width. - // This is done for the following instructions: mov, cmp. + // This is done for the following instructions: mov, cmp, inc, dec, + // add, sub, and test. // There are no versions of these instructions without the suffix. // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'. // - Instructions on 16-bit (word) operands/registers have a trailing 'w'. @@ -423,6 +424,7 @@ void movl(Register dst, Register src); void movl(Register dst, const Operand& src); void movl(const Operand& dst, Register src); + void movl(const Operand& dst, Immediate imm); // Load a 32-bit immediate value, zero-extended to 64 bits. void movl(Register dst, Immediate imm32); @@ -449,61 +451,55 @@ void load_rax(void* ptr, RelocInfo::Mode rmode); void load_rax(ExternalReference ext); - void movsx_b(Register dst, const Operand& src); - - void movsx_w(Register dst, const Operand& src); - - void movzx_b(Register dst, const Operand& src); - - void movzx_w(Register dst, const Operand& src); - // Conditional moves - void cmov(Condition cc, Register dst, int32_t imm32); - void cmov(Condition cc, Register dst, Handle<Object> handle); - void cmov(Condition cc, Register dst, const Operand& src); + // Implement conditional moves here. // Exchange two registers void xchg(Register dst, Register src); // Arithmetics - void add(Register dst, Register src) { + void addq(Register dst, Register src) { arithmetic_op(0x03, dst, src); } - void add(Register dst, const Operand& src) { + void addq(Register dst, const Operand& src) { arithmetic_op(0x03, dst, src); } - void add(const Operand& dst, Register src) { + void addq(const Operand& dst, Register src) { arithmetic_op(0x01, src, dst); } - void add(Register dst, Immediate src) { + void addq(Register dst, Immediate src) { immediate_arithmetic_op(0x0, dst, src); } - void add(const Operand& dst, Immediate src) { + void addq(const Operand& dst, Immediate src) { immediate_arithmetic_op(0x0, dst, src); } - void cmp(Register dst, Register src) { + void addl(const Operand& dst, Immediate src) { + immediate_arithmetic_op_32(0x0, dst, src); + } + + void cmpq(Register dst, Register src) { arithmetic_op(0x3B, dst, src); } - void cmp(Register dst, const Operand& src) { + void cmpq(Register dst, const Operand& src) { arithmetic_op(0x3B, dst, src); } - void cmp(const Operand& dst, Register src) { + void cmpq(const Operand& dst, Register src) { arithmetic_op(0x39, src, dst); } - void cmp(Register dst, Immediate src) { + void cmpq(Register dst, Immediate src) { immediate_arithmetic_op(0x7, dst, src); } - void cmp(const Operand& dst, Immediate src) { + void cmpq(const Operand& dst, Immediate src) { immediate_arithmetic_op(0x7, dst, src); } @@ -527,15 +523,9 @@ immediate_arithmetic_op(0x4, dst, src); } - void cmpb(const Operand& op, int8_t imm8); - void cmpb_al(const Operand& op); - void cmpw_ax(const Operand& op); - void cmpw(const Operand& op, Immediate imm16); - - void dec_b(Register dst); - - void dec(Register dst); - void dec(const Operand& dst); + void decq(Register dst); + void decq(const Operand& dst); + void decl(const Operand& dst); // Sign-extends rax into rdx:rax. void cqo(); @@ -548,8 +538,9 @@ // Performs the operation dst = src * imm. void imul(Register dst, Register src, Immediate imm); - void inc(Register dst); - void inc(const Operand& dst); + void incq(Register dst); + void incq(const Operand& dst); + void incl(const Operand& dst); void lea(Register dst, const Operand& src); @@ -621,26 +612,30 @@ void store_rax(void* dst, RelocInfo::Mode mode); void store_rax(ExternalReference ref); - void sub(Register dst, Register src) { + void subq(Register dst, Register src) { arithmetic_op(0x2B, dst, src); } - void sub(Register dst, const Operand& src) { + void subq(Register dst, const Operand& src) { arithmetic_op(0x2B, dst, src); } - void sub(const Operand& dst, Register src) { + void subq(const Operand& dst, Register src) { arithmetic_op(0x29, src, dst); } - void sub(Register dst, Immediate src) { + void subq(Register dst, Immediate src) { immediate_arithmetic_op(0x5, dst, src); } - void sub(const Operand& dst, Immediate src) { + void subq(const Operand& dst, Immediate src) { immediate_arithmetic_op(0x5, dst, src); } + void subl(const Operand& dst, Immediate src) { + immediate_arithmetic_op_32(0x5, dst, src); + } + void testb(Register reg, Immediate mask); void testb(const Operand& op, Immediate mask); void testl(Register reg, Immediate mask); @@ -669,18 +664,19 @@ immediate_arithmetic_op(0x6, dst, src); } - // Bit operations. void bt(const Operand& dst, Register src); void bts(const Operand& dst, Register src); // Miscellaneous + void cpuid(); void hlt(); void int3(); void nop(); void nop(int n); void rdtsc(); void ret(int imm16); + void setcc(Condition cc, Register reg); // Label operations & relative jumps (PPUM Appendix D) // @@ -718,8 +714,6 @@ // Conditional jumps void j(Condition cc, Label* L); - void j(Condition cc, byte* entry, RelocInfo::Mode rmode); - void j(Condition cc, Handle<Code> code); // Floating-point operations void fld(int i); @@ -775,11 +769,6 @@ void frndint(); - void sahf(); - void setcc(Condition cc, Register reg); - - void cpuid(); - // SSE2 instructions void cvttss2si(Register dst, const Operand& src); void cvttsd2si(Register dst, const Operand& src); @@ -792,8 +781,8 @@ void divsd(XMMRegister dst, XMMRegister src); // Use either movsd or movlpd. - void movdbl(XMMRegister dst, const Operand& src); - void movdbl(const Operand& dst, XMMRegister src); + // void movdbl(XMMRegister dst, const Operand& src); + // void movdbl(const Operand& dst, XMMRegister src); // Debugging void Print(); @@ -814,11 +803,11 @@ // Writes a doubleword of data in the code stream. // Used for inline tables, e.g., jump-tables. - void dd(uint32_t data); + // void dd(uint32_t data); // Writes a quadword of data in the code stream. // Used for inline tables, e.g., jump-tables. - void dd(uint64_t data, RelocInfo::Mode reloc_info); + // void dd(uint64_t data, RelocInfo::Mode reloc_info); // Writes the absolute address of a bound label at the given position in // the generated code. That positions should have the relocation mode @@ -842,11 +831,11 @@ static const int kMinimalBufferSize = 4*KB; protected: - void movsd(XMMRegister dst, const Operand& src); - void movsd(const Operand& dst, XMMRegister src); + // void movsd(XMMRegister dst, const Operand& src); + // void movsd(const Operand& dst, XMMRegister src); - void emit_sse_operand(XMMRegister reg, const Operand& adr); - void emit_sse_operand(XMMRegister dst, XMMRegister src); + // void emit_sse_operand(XMMRegister reg, const Operand& adr); + // void emit_sse_operand(XMMRegister dst, XMMRegister src); private: @@ -970,15 +959,18 @@ void arithmetic_op(byte opcode, Register reg, const Operand& op); void immediate_arithmetic_op(byte subcode, Register dst, Immediate src); void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src); + void immediate_arithmetic_op_32(byte subcode, + const Operand& dst, + Immediate src); // Emit machine code for a shift operation. void shift(Register dst, Immediate shift_amount, int subcode); // Shift dst by cl % 64 bits. void shift(Register dst, int subcode); - void emit_farith(int b1, int b2, int i); + // void emit_farith(int b1, int b2, int i); // labels - void print(Label* L); + // void print(Label* L); void bind_to(Label* L, int pos); void link_to(Label* L, Label* appendix); Modified: branches/bleeding_edge/src/x64/builtins-x64.cc ============================================================================== --- branches/bleeding_edge/src/x64/builtins-x64.cc (original) +++ branches/bleeding_edge/src/x64/builtins-x64.cc Wed Jun 10 08:53:46 2009 @@ -141,9 +141,9 @@ __ bind(&loop); __ movq(kScratchRegister, Operand(rbx, rcx, kTimesPointerSize, 0)); __ push(Operand(kScratchRegister, 0)); // dereference handle - __ add(rcx, Immediate(1)); + __ addq(rcx, Immediate(1)); __ bind(&entry); - __ cmp(rcx, rax); + __ cmpq(rcx, rax); __ j(not_equal, &loop); // Invoke the code. @@ -177,5 +177,3 @@ } } } // namespace v8::internal - - Modified: branches/bleeding_edge/src/x64/codegen-x64.cc ============================================================================== --- branches/bleeding_edge/src/x64/codegen-x64.cc (original) +++ branches/bleeding_edge/src/x64/codegen-x64.cc Wed Jun 10 08:53:46 2009 @@ -259,7 +259,7 @@ // The frame pointer is NULL in the exception handler of a JS entry frame. __ xor_(rsi, rsi); // tentatively set context pointer to NULL Label skip; - __ cmp(rbp, Immediate(0)); + __ cmpq(rbp, Immediate(0)); __ j(equal, &skip); __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); __ bind(&skip); @@ -294,7 +294,7 @@ ExternalReference::heap_always_allocate_scope_depth(); if (always_allocate_scope) { __ movq(kScratchRegister, scope_depth); - __ inc(Operand(kScratchRegister, 0)); + __ incl(Operand(kScratchRegister, 0)); } // Call C function. @@ -311,7 +311,7 @@ if (always_allocate_scope) { __ movq(kScratchRegister, scope_depth); - __ dec(Operand(kScratchRegister, 0)); + __ decl(Operand(kScratchRegister, 0)); } // Check for failure result. @@ -338,7 +338,7 @@ Label continue_exception; // If the returned failure is EXCEPTION then promote Top::pending_exception(). __ movq(kScratchRegister, Failure::Exception(), RelocInfo::NONE); - __ cmp(rax, kScratchRegister); + __ cmpq(rax, kScratchRegister); __ j(not_equal, &continue_exception); // Retrieve the pending exception and clear the variable. @@ -352,7 +352,7 @@ __ bind(&continue_exception); // Special handling of out of memory exception. __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE); - __ cmp(rax, kScratchRegister); + __ cmpq(rax, kScratchRegister); __ j(equal, throw_out_of_memory_exception); // Handle normal exception. @@ -373,7 +373,7 @@ Label loop, done; __ bind(&loop); // Load the type of the current stack handler. - __ cmp(Operand(rdx, StackHandlerConstants::kStateOffset), + __ cmpq(Operand(rdx, StackHandlerConstants::kStateOffset), Immediate(StackHandler::ENTRY)); __ j(equal, &done); // Fetch the next handler in the list. @@ -549,7 +549,7 @@ __ movq(kScratchRegister, ExternalReference(Top::k_handler_address)); __ pop(Operand(kScratchRegister, 0)); // Pop next_sp. - __ add(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); + __ addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); // Restore the top frame descriptor from the stack. __ bind(&exit); @@ -564,7 +564,7 @@ __ pop(r14); __ pop(r13); __ pop(r12); - __ add(rsp, Immediate(2 * kPointerSize)); // remove markers + __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers // Restore frame pointer and return. __ pop(rbp); Modified: branches/bleeding_edge/src/x64/macro-assembler-x64.cc ============================================================================== --- branches/bleeding_edge/src/x64/macro-assembler-x64.cc (original) +++ branches/bleeding_edge/src/x64/macro-assembler-x64.cc Wed Jun 10 08:53:46 2009 @@ -120,6 +120,30 @@ } +void MacroAssembler::Jump(ExternalReference ext) { + movq(kScratchRegister, ext); + jmp(kScratchRegister); +} + + +void MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) { + movq(kScratchRegister, destination, rmode); + jmp(kScratchRegister); +} + + +void MacroAssembler::Call(ExternalReference ext) { + movq(kScratchRegister, ext); + call(kScratchRegister); +} + + +void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { + movq(kScratchRegister, destination, rmode); + call(kScratchRegister); +} + + void MacroAssembler::PushTryHandler(CodeLocation try_location, HandlerType type) { // Adjust this code if not the case. @@ -158,6 +182,47 @@ } +void MacroAssembler::Ret() { + ret(0); +} + + +void MacroAssembler::SetCounter(StatsCounter* counter, int value) { + if (FLAG_native_code_counters && counter->Enabled()) { + movq(kScratchRegister, ExternalReference(counter)); + movl(Operand(kScratchRegister, 0), Immediate(value)); + } +} + + +void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { + ASSERT(value > 0); + if (FLAG_native_code_counters && counter->Enabled()) { + movq(kScratchRegister, ExternalReference(counter)); + Operand operand(kScratchRegister, 0); + if (value == 1) { + incl(operand); + } else { + addl(operand, Immediate(value)); + } + } +} + + +void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { + ASSERT(value > 0); + if (FLAG_native_code_counters && counter->Enabled()) { + movq(kScratchRegister, ExternalReference(counter)); + Operand operand(kScratchRegister, 0); + if (value == 1) { + decl(operand); + } else { + subl(operand, Immediate(value)); + } + } +} + + #ifdef ENABLE_DEBUGGER_SUPPORT void MacroAssembler::PushRegistersFromMemory(RegList regs) { @@ -265,7 +330,7 @@ movq(kScratchRegister, Factory::undefined_value(), RelocInfo::EMBEDDED_OBJECT); - cmp(Operand(rsp, 0), kScratchRegister); + cmpq(Operand(rsp, 0), kScratchRegister); Check(not_equal, "code object not properly patched"); } } @@ -274,7 +339,7 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { if (FLAG_debug_code) { movq(kScratchRegister, Immediate(Smi::FromInt(type))); - cmp(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); + cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); Check(equal, "stack frame types must match"); } movq(rsp, rbp); @@ -328,7 +393,7 @@ #endif // Reserve space for two arguments: argc and argv. - sub(rsp, Immediate(2 * kPointerSize)); + subq(rsp, Immediate(2 * kPointerSize)); // Get the required frame alignment for the OS. static const int kFrameAlignment = OS::ActivationFrameAlignment(); Modified: branches/bleeding_edge/src/x64/macro-assembler-x64.h ============================================================================== --- branches/bleeding_edge/src/x64/macro-assembler-x64.h (original) +++ branches/bleeding_edge/src/x64/macro-assembler-x64.h Wed Jun 10 08:53:46 2009 @@ -141,9 +141,18 @@ // Store the code object for the given builtin in the target register. void GetBuiltinEntry(Register target, Builtins::JavaScript id); + // --------------------------------------------------------------------------- + // Macro instructions + // Expression support void Set(Register dst, int64_t x); void Set(const Operand& dst, int64_t x); + + // Control Flow + void Jump(Address destination, RelocInfo::Mode rmode); + void Jump(ExternalReference ext); + void Call(Address destination, RelocInfo::Mode rmode); + void Call(ExternalReference ext); // Compare object type for heap object. // Incoming register is heap_object and outgoing register is map. Modified: branches/bleeding_edge/test/cctest/test-assembler-x64.cc ============================================================================== --- branches/bleeding_edge/test/cctest/test-assembler-x64.cc (original) +++ branches/bleeding_edge/test/cctest/test-assembler-x64.cc Wed Jun 10 08:53:46 2009 @@ -132,7 +132,7 @@ // Assemble a simple function that copies argument 2 and returns it. __ movq(rax, rsi); - __ add(rax, rdi); + __ addq(rax, rdi); __ ret(0); CodeDesc desc; @@ -215,12 +215,12 @@ Label Loop1_body; __ jmp(&Loop1_test); __ bind(&Loop1_body); - __ add(rax, Immediate(7)); + __ addq(rax, Immediate(7)); __ bind(&Loop1_test); - __ cmp(rax, Immediate(20)); + __ cmpq(rax, Immediate(20)); __ j(less_equal, &Loop1_body); // Did the loop terminate with the expected value? - __ cmp(rax, Immediate(25)); + __ cmpq(rax, Immediate(25)); __ j(not_equal, &Fail); Label Loop2_test; @@ -228,12 +228,12 @@ __ movq(rax, Immediate(0x11FEED00)); __ jmp(&Loop2_test); __ bind(&Loop2_body); - __ add(rax, Immediate(-0x1100)); + __ addq(rax, Immediate(-0x1100)); __ bind(&Loop2_test); - __ cmp(rax, Immediate(0x11FE8000)); + __ cmpq(rax, Immediate(0x11FE8000)); __ j(greater, &Loop2_body); // Did the loop terminate with the expected value? - __ cmp(rax, Immediate(0x11FE7600)); + __ cmpq(rax, Immediate(0x11FE7600)); __ j(not_equal, &Fail); __ movq(rax, Immediate(1)); --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list v8-dev@googlegroups.com http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---