Commit 2de98f8e authored by whesse@chromium.org's avatar whesse@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2139 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 85720fc0
......@@ -451,6 +451,24 @@ void Assembler::immediate_arithmetic_op(byte subcode,
}
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::call(Register adr) {
}
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::call(const Operand& op) {
}
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::cqo() {
}
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(Register dst) {
}
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::dec(const Operand& dst) {
}
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::imul(Register dst, Register src, Immediate imm) {
}
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(Register dst) {
}
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::inc(const Operand& dst) {
}
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, Register src) {
}
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::rcl(Register dst, uint8_t imm8) {
}
}
void Assembler::rdtsc() {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0x0F);
emit(0x31);
}
void Assembler::ret(int imm16) {
EnsureSpace ensure_space(this);
......@@ -1147,6 +1200,19 @@ void Assembler::ret(int imm16) {
}
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);
}
void Assembler::shld(Register dst, Register src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
......
......@@ -385,7 +385,8 @@ class Assembler : public Malloced {
//
// 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 @@ class Assembler : public Malloced {
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 @@ class Assembler : public Malloced {
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 @@ class Assembler : public Malloced {
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 @@ class Assembler : public Malloced {
// 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 @@ class Assembler : public Malloced {
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 @@ class Assembler : public Malloced {
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 @@ class Assembler : public Malloced {
// 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 @@ class Assembler : public Malloced {
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 @@ class Assembler : public Malloced {
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 @@ class Assembler : public Malloced {
// 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 @@ class Assembler : public Malloced {
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 @@ class Assembler : public Malloced {
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);
......
......@@ -141,9 +141,9 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ 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 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
}
} } // namespace v8::internal
......@@ -259,7 +259,7 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// 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 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
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 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
if (always_allocate_scope) {
__ movq(kScratchRegister, scope_depth);
__ dec(Operand(kScratchRegister, 0));
__ decl(Operand(kScratchRegister, 0));
}
// Check for failure result.
......@@ -338,7 +338,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
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 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
__ 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 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
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 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ 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 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ 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);
......
......@@ -120,6 +120,30 @@ void MacroAssembler::Set(const Operand& dst, int64_t x) {
}
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::PushTryHandler(CodeLocation try_location,
}
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 @@ void MacroAssembler::EnterFrame(StackFrame::Type type) {
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::EnterFrame(StackFrame::Type type) {
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 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
#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();
......
......@@ -141,10 +141,19 @@ class MacroAssembler: public Assembler {
// 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.
void CmpObjectType(Register heap_object, InstanceType type, Register map);
......
......@@ -132,7 +132,7 @@ TEST(AssemblerX64ArithmeticOperations) {
// 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 @@ TEST(AssemblerX64LoopImmediates) {
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 @@ TEST(AssemblerX64LoopImmediates) {
__ 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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment