A64: Introduce 'branch types' that extend the architectural conditions.

The branch types include 'always' and 'never', and types like reg_zero (CBZ) and
reg_bit_clear (TBZ).
This will be used by incoming improvements to the code generated for
deoptimization exit points.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/170783002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19497 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent bbd233fc
...@@ -666,6 +666,26 @@ bool MacroAssembler::NeedExtraInstructionsOrRegisterBranch( ...@@ -666,6 +666,26 @@ bool MacroAssembler::NeedExtraInstructionsOrRegisterBranch(
} }
void MacroAssembler::B(Label* label, BranchType type, Register reg, int bit) {
ASSERT((reg.Is(NoReg) || type >= kBranchTypeFirstUsingReg) &&
(bit == -1 || type >= kBranchTypeFirstUsingBit));
if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
B(static_cast<Condition>(type), label);
} else {
switch (type) {
case always: B(label); break;
case never: break;
case reg_zero: Cbz(reg, label); break;
case reg_not_zero: Cbnz(reg, label); break;
case reg_bit_clear: Tbz(reg, bit, label); break;
case reg_bit_set: Tbnz(reg, bit, label); break;
default:
UNREACHABLE();
}
}
}
void MacroAssembler::B(Label* label, Condition cond) { void MacroAssembler::B(Label* label, Condition cond) {
ASSERT(allow_macro_instructions_); ASSERT(allow_macro_instructions_);
ASSERT((cond != al) && (cond != nv)); ASSERT((cond != al) && (cond != nv));
......
...@@ -64,6 +64,53 @@ inline MemOperand UntagSmiMemOperand(Register object, int offset); ...@@ -64,6 +64,53 @@ inline MemOperand UntagSmiMemOperand(Register object, int offset);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// MacroAssembler // MacroAssembler
enum BranchType {
// Copies of architectural conditions.
// The associated conditions can be used in place of those, the code will
// take care of reinterpreting them with the correct type.
integer_eq = eq,
integer_ne = ne,
integer_hs = hs,
integer_lo = lo,
integer_mi = mi,
integer_pl = pl,
integer_vs = vs,
integer_vc = vc,
integer_hi = hi,
integer_ls = ls,
integer_ge = ge,
integer_lt = lt,
integer_gt = gt,
integer_le = le,
integer_al = al,
integer_nv = nv,
// These two are *different* from the architectural codes al and nv.
// 'always' is used to generate unconditional branches.
// 'never' is used to not generate a branch (generally as the inverse
// branch type of 'always).
always, never,
// cbz and cbnz
reg_zero, reg_not_zero,
// tbz and tbnz
reg_bit_clear, reg_bit_set,
// Aliases.
kBranchTypeFirstCondition = eq,
kBranchTypeLastCondition = nv,
kBranchTypeFirstUsingReg = reg_zero,
kBranchTypeFirstUsingBit = reg_bit_clear
};
inline BranchType InvertBranchType(BranchType type) {
if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
return static_cast<BranchType>(
InvertCondition(static_cast<Condition>(type)));
} else {
return static_cast<BranchType>(type ^ 1);
}
}
enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved }; enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
...@@ -212,6 +259,14 @@ class MacroAssembler : public Assembler { ...@@ -212,6 +259,14 @@ class MacroAssembler : public Assembler {
inline void Adr(const Register& rd, Label* label); inline void Adr(const Register& rd, Label* label);
inline void Asr(const Register& rd, const Register& rn, unsigned shift); inline void Asr(const Register& rd, const Register& rn, unsigned shift);
inline void Asr(const Register& rd, const Register& rn, const Register& rm); inline void Asr(const Register& rd, const Register& rn, const Register& rm);
// Branch type inversion relies on these relations.
STATIC_ASSERT((reg_zero == (reg_not_zero ^ 1)) &&
(reg_bit_clear == (reg_bit_set ^ 1)) &&
(always == (never ^ 1)));
void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1);
inline void B(Label* label); inline void B(Label* label);
inline void B(Condition cond, Label* label); inline void B(Condition cond, Label* label);
void B(Label* label, Condition cond); void B(Label* label, Condition cond);
......
...@@ -2276,6 +2276,63 @@ TEST(far_branch_veneer_broken_link_chain) { ...@@ -2276,6 +2276,63 @@ TEST(far_branch_veneer_broken_link_chain) {
} }
TEST(branch_type) {
INIT_V8();
SETUP();
Label fail, done;
START();
__ Mov(x0, 0x0);
__ Mov(x10, 0x7);
__ Mov(x11, 0x0);
// Test non taken branches.
__ Cmp(x10, 0x7);
__ B(&fail, ne);
__ B(&fail, never);
__ B(&fail, reg_zero, x10);
__ B(&fail, reg_not_zero, x11);
__ B(&fail, reg_bit_clear, x10, 0);
__ B(&fail, reg_bit_set, x10, 3);
// Test taken branches.
Label l1, l2, l3, l4, l5;
__ Cmp(x10, 0x7);
__ B(&l1, eq);
__ B(&fail);
__ Bind(&l1);
__ B(&l2, always);
__ B(&fail);
__ Bind(&l2);
__ B(&l3, reg_not_zero, x10);
__ B(&fail);
__ Bind(&l3);
__ B(&l4, reg_bit_clear, x10, 15);
__ B(&fail);
__ Bind(&l4);
__ B(&l5, reg_bit_set, x10, 1);
__ B(&fail);
__ Bind(&l5);
__ B(&done);
__ Bind(&fail);
__ Mov(x0, 0x1);
__ Bind(&done);
END();
RUN();
ASSERT_EQUAL_64(0x0, x0);
TEARDOWN();
}
TEST(ldr_str_offset) { TEST(ldr_str_offset) {
INIT_V8(); INIT_V8();
SETUP(); SETUP();
......
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