Chromium Code Reviews| Index: src/mips/macro-assembler-mips.h |
| =================================================================== |
| --- src/mips/macro-assembler-mips.h (revision 4259) |
| +++ src/mips/macro-assembler-mips.h (working copy) |
| @@ -37,11 +37,18 @@ |
| // Forward declaration. |
| class JumpTarget; |
| -// Register at is used for instruction generation. So it is not safe to use it |
| -// unless we know exactly what we do. |
| +// Register at is used for instruction generation. So it is not always safe to |
| +// use it. Instead t8 and t9 registers are used by the MacroAssembler when |
| +// necessary. |
| +// The programmer should know that the MacroAssembler may clobber these two, |
| +// but won't touch other registers except in special cases. |
| +// Unless we know exactly what we do. Therefore we create another scratch reg. |
|
Søren Thygesen Gjesse
2010/05/25 09:00:56
Remove "Unless we know exactly what we do."?
|
| +const Register ip = t8; // Alias ip (equivalent to arm ip scratch register). |
| + |
| // Registers aliases |
| // cp is assumed to be a callee saved register. |
| +const Register roots = s6; // Roots array pointer. |
| const Register cp = s7; // JavaScript context pointer |
| const Register fp = s8_fp; // Alias fp |
| @@ -55,45 +62,87 @@ |
| public: |
| MacroAssembler(void* buffer, int size); |
| - // Jump, Call, and Ret pseudo instructions implementing inter-working. |
| - void Jump(const Operand& target, |
| - Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| - void Call(const Operand& target, |
| - Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| - void Jump(Register target, |
| - Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| - void Jump(byte* target, RelocInfo::Mode rmode, |
| - Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| - void Jump(Handle<Code> code, RelocInfo::Mode rmode, |
| - Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| - void Call(Register target, |
| - Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| - void Call(byte* target, RelocInfo::Mode rmode, |
| - Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| - void Call(Handle<Code> code, RelocInfo::Mode rmode, |
| - Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| - void Ret(Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| - void Branch(Condition cond, int16_t offset, Register rs = zero_reg, |
| - const Operand& rt = Operand(zero_reg), Register scratch = at); |
| - void Branch(Condition cond, Label* L, Register rs = zero_reg, |
| - const Operand& rt = Operand(zero_reg), Register scratch = at); |
| - // conditionnal branch and link |
| - void BranchAndLink(Condition cond, int16_t offset, Register rs = zero_reg, |
| - const Operand& rt = Operand(zero_reg), |
| - Register scratch = at); |
| - void BranchAndLink(Condition cond, Label* L, Register rs = zero_reg, |
| - const Operand& rt = Operand(zero_reg), |
| - Register scratch = at); |
| +// Arguments macros |
|
Søren Thygesen Gjesse
2010/05/25 09:00:56
Are you sure that using these macros here are bene
|
| +#define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2 |
| +#define COND_ARGS cond, r1, r2 |
| +// ** Prototypes |
| + |
| +// * Prototypes for functions with no target (eg Ret()). |
| +#define DECLARE_NOTARGET_PROTOTYPE(Name) \ |
| + void Name(bool ProtectBranchDelaySlot = true); \ |
| + void Name(COND_TYPED_ARGS, bool ProtectBranchDelaySlot = true); \ |
| + inline void Name(bool ProtectBranchDelaySlot, COND_TYPED_ARGS) { \ |
| + Name(COND_ARGS, ProtectBranchDelaySlot); \ |
| + } |
| + |
| +// * Prototypes for functions with a target. |
| + |
| +// Cases when relocation may be needed. |
| +#define DECLARE_RELOC_PROTOTYPE(Name, target_type) \ |
| + void Name(target_type target, \ |
| + RelocInfo::Mode rmode, \ |
| + bool ProtectBranchDelaySlot = true); \ |
| + inline void Name(bool ProtectBranchDelaySlot, \ |
| + target_type target, \ |
| + RelocInfo::Mode rmode) { \ |
| + Name(target, rmode, ProtectBranchDelaySlot); \ |
| + } \ |
| + void Name(target_type target, \ |
| + RelocInfo::Mode rmode, \ |
| + COND_TYPED_ARGS, \ |
| + bool ProtectBranchDelaySlot = true); \ |
| + inline void Name(bool ProtectBranchDelaySlot, \ |
| + target_type target, \ |
| + RelocInfo::Mode rmode, \ |
| + COND_TYPED_ARGS) { \ |
| + Name(target, rmode, COND_ARGS, ProtectBranchDelaySlot); \ |
| + } |
| + |
| +// Cases when relocation is not needed. |
| +#define DECLARE_NORELOC_PROTOTYPE(Name, target_type) \ |
| + void Name(target_type target, bool ProtectBranchDelaySlot = true); \ |
| + inline void Name(bool ProtectBranchDelaySlot, target_type target) { \ |
| + Name(target, ProtectBranchDelaySlot); \ |
| + } \ |
| + void Name(target_type target, \ |
| + COND_TYPED_ARGS, \ |
| + bool ProtectBranchDelaySlot = true); \ |
| + inline void Name(bool ProtectBranchDelaySlot, \ |
| + target_type target, \ |
| + COND_TYPED_ARGS) { \ |
| + Name(target, COND_ARGS, ProtectBranchDelaySlot); \ |
| + } |
| + |
| +// ** Target prototypes. |
| + |
| +#define DECLARE_JUMP_CALL_PROTOTYPES(Name) \ |
| + DECLARE_NORELOC_PROTOTYPE(Name, Register) \ |
| + DECLARE_NORELOC_PROTOTYPE(Name, const Operand&) \ |
| + DECLARE_RELOC_PROTOTYPE(Name, byte*) \ |
| + DECLARE_RELOC_PROTOTYPE(Name, Handle<Code>) |
| + |
| +#define DECLARE_BRANCH_PROTOTYPES(Name) \ |
| + DECLARE_NORELOC_PROTOTYPE(Name, Label*) \ |
| + DECLARE_NORELOC_PROTOTYPE(Name, int16_t) |
| + |
| + |
| +DECLARE_JUMP_CALL_PROTOTYPES(Jump) |
| +DECLARE_JUMP_CALL_PROTOTYPES(Call) |
| + |
| +DECLARE_BRANCH_PROTOTYPES(Branch) |
| +DECLARE_BRANCH_PROTOTYPES(BranchAndLink) |
| + |
| +DECLARE_NOTARGET_PROTOTYPE(Ret) |
| + |
| +#undef COND_TYPED_ARGS |
| +#undef COND_ARGS |
| +#undef DECLARE_NOTARGET_PROTOTYPE |
| +#undef DECLARE_NORELOC_PROTOTYPE |
| +#undef DECLARE_RELOC_PROTOTYPE |
| +#undef DECLARE_JUMP_CALL_PROTOTYPES |
| +#undef DECLARE_BRANCH_PROTOTYPES |
| + |
| // Emit code to discard a non-negative number of pointer-sized elements |
| // from the stack, clobbering only the sp register. |
| void Drop(int count, Condition cond = cc_always); |
| @@ -106,7 +155,7 @@ |
| // Currently the branch delay slot is filled by the MacroAssembler. |
| // Use rather b(Label) for code generation. |
| void jmp(Label* L) { |
| - Branch(cc_always, L); |
| + Branch(L); |
| } |
| // Load an object from the root table. |
| @@ -128,7 +177,7 @@ |
| // --------------------------------------------------------------------------- |
| // Instruction macros |
| -#define DEFINE_INSTRUCTION(instr) \ |
| +#define DEFINE_INSTRUCTION(instr) \ |
| void instr(Register rd, Register rs, const Operand& rt); \ |
| void instr(Register rd, Register rs, Register rt) { \ |
| instr(rd, rs, Operand(rt)); \ |
| @@ -137,7 +186,7 @@ |
| instr(rs, rt, Operand(j)); \ |
| } |
| -#define DEFINE_INSTRUCTION2(instr) \ |
| +#define DEFINE_INSTRUCTION2(instr) \ |
| void instr(Register rs, const Operand& rt); \ |
| void instr(Register rs, Register rt) { \ |
| instr(rs, Operand(rt)); \ |
| @@ -146,8 +195,8 @@ |
| instr(rs, Operand(j)); \ |
| } |
| - DEFINE_INSTRUCTION(Add); |
| DEFINE_INSTRUCTION(Addu); |
| + DEFINE_INSTRUCTION(Subu); |
| DEFINE_INSTRUCTION(Mul); |
| DEFINE_INSTRUCTION2(Mult); |
| DEFINE_INSTRUCTION2(Multu); |
| @@ -169,10 +218,7 @@ |
| //------------Pseudo-instructions------------- |
| void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); } |
| - // Move the logical ones complement of source to dest. |
| - void movn(Register rd, Register rt); |
| - |
| // load int32 in the rd register |
| void li(Register rd, Operand j, bool gen2instr = false); |
| inline void li(Register rd, int32_t j, bool gen2instr = false) { |
| @@ -196,7 +242,7 @@ |
| void Push(Register src, Condition cond, Register tst1, Register tst2) { |
| // Since we don't have conditionnal execution we use a Branch. |
| - Branch(cond, 3, tst1, Operand(tst2)); |
| + Branch(3, cond, tst1, Operand(tst2)); |
|
Søren Thygesen Gjesse
2010/05/25 09:00:56
The constant 3 relies on Addu only generates one i
|
| Addu(sp, sp, Operand(-kPointerSize)); |
| sw(src, MemOperand(sp, 0)); |
| } |
| @@ -209,8 +255,8 @@ |
| lw(dst, MemOperand(sp, 0)); |
| Addu(sp, sp, Operand(kPointerSize)); |
| } |
| - void Pop() { |
| - Add(sp, sp, Operand(kPointerSize)); |
| + void Pop(uint32_t count = 1) { |
| + Addu(sp, sp, Operand(count * kPointerSize)); |
| } |
| @@ -280,6 +326,7 @@ |
| // Push a new try handler and link into try handler chain. |
| // The return address must be passed in register ra. |
| + // Clobber t0, t1, t2. |
|
Søren Thygesen Gjesse
2010/05/25 09:00:56
Clobber -> Clobbers
|
| void PushTryHandler(CodeLocation try_location, HandlerType type); |
| // Unlink the stack handler on top of the stack from the try handler chain. |
| @@ -298,7 +345,7 @@ |
| Register scratch = at) { |
| ASSERT_EQ(0, kSmiTag); |
| andi(scratch, value, kSmiTagMask); |
| - Branch(eq, smi_label, scratch, Operand(zero_reg)); |
| + Branch(smi_label, eq, scratch, Operand(zero_reg)); |
| } |
| @@ -306,7 +353,7 @@ |
| Register scratch = at) { |
| ASSERT_EQ(0, kSmiTag); |
| andi(scratch, value, kSmiTagMask); |
| - Branch(ne, not_smi_label, scratch, Operand(zero_reg)); |
| + Branch(not_smi_label, ne, scratch, Operand(zero_reg)); |
| } |
| void CallBuiltin(ExternalReference builtin_entry); |
| @@ -412,10 +459,16 @@ |
| // This handle will be patched with the code object on installation. |
| Handle<Object> code_object_; |
| + void Jump(intptr_t target, RelocInfo::Mode rmode, |
| + bool ProtectBranchDelaySlot = true); |
| void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| + Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg), |
| + bool ProtectBranchDelaySlot = true); |
| + void Call(intptr_t target, RelocInfo::Mode rmode, |
| + bool ProtectBranchDelaySlot = true); |
| void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = cc_always, |
| - Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg)); |
| + Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg), |
| + bool ProtectBranchDelaySlot = true); |
| // Helper functions for generating invokes. |
| void InvokePrologue(const ParameterCount& expected, |
| @@ -430,7 +483,6 @@ |
| Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved); |
| // Activation support. |
| - // EnterFrame clobbers t0 and t1. |
| void EnterFrame(StackFrame::Type type); |
| void LeaveFrame(StackFrame::Type type); |
| }; |