Index: src/mips64/macro-assembler-mips64.h |
diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h |
index 117d25e7de8c2fbd827ec4b8409cb4a137fc2825..52f881aec9bc2ea13c78a35519154556756f89bd 100644 |
--- a/src/mips64/macro-assembler-mips64.h |
+++ b/src/mips64/macro-assembler-mips64.h |
@@ -236,6 +236,11 @@ class MacroAssembler: public Assembler { |
Heap::RootListIndex index, |
BranchDelaySlot bdslot = PROTECT); |
+ // GetLabelFunction must be lambda '[](size_t index) -> Label*' or a |
+ // functor/function with 'Label *func(size_t index)' declaration. |
+ template <typename Func> |
+ void GenerateSwitchTable(Register index, size_t case_count, |
+ Func GetLabelFunction); |
#undef COND_ARGS |
// Emit code to discard a non-negative number of pointer-sized elements |
@@ -1898,7 +1903,36 @@ class CodePatcher { |
FlushICache flush_cache_; // Whether to flush the I cache after patching. |
}; |
- |
+template <typename Func> |
+void MacroAssembler::GenerateSwitchTable(Register index, size_t case_count, |
+ Func GetLabelFunction) { |
+ // Ensure that dd-ed labels following this instruction use 8 bytes aligned |
+ // addresses. |
+ if (kArchVariant >= kMips64r6) { |
+ BlockTrampolinePoolFor(static_cast<int>(case_count) * 2 + 6); |
+ // Opposite of Align(8) as we have odd number of instructions in this case. |
+ if ((pc_offset() & 7) == 0) { |
+ nop(); |
+ } |
+ addiupc(at, 5); |
+ dlsa(at, at, index, kPointerSizeLog2); |
+ ld(at, MemOperand(at)); |
+ } else { |
+ Label here; |
+ BlockTrampolinePoolFor(static_cast<int>(case_count) * 2 + 7); |
+ Align(8); |
+ bal(&here); |
+ dsll(at, index, kPointerSizeLog2); // Branch delay slot. |
+ bind(&here); |
+ daddu(at, at, ra); |
+ ld(at, MemOperand(at, 4 * v8::internal::Assembler::kInstrSize)); |
+ } |
+ jr(at); |
+ nop(); // Branch delay slot nop. |
+ for (size_t index = 0; index < case_count; ++index) { |
+ dd(GetLabelFunction(index)); |
+ } |
+} |
#ifdef GENERATED_CODE_COVERAGE |
#define CODE_COVERAGE_STRINGIFY(x) #x |