Merge "Cache DexRegisterMaps when writing native debug info."
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 422d82f..11d0c9a 100755
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1140,6 +1140,12 @@
RegLocation rl_offset = info->args[0];
RegLocation rl_count = info->args[1];
RegLocation rl_data = info->args[2];
+ // No need to emit code checking whether `rl_data` is a null
+ // pointer, as callers of the native method
+ //
+ // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)
+ //
+ // all include a null check on `data` before calling that method.
CallRuntimeHelperRegLocationRegLocationRegLocation(
kQuickAllocStringFromChars, rl_offset, rl_count, rl_data, true);
RegLocation rl_return = GetReturn(kRefReg);
@@ -1357,6 +1363,7 @@
LoadValueDirectFixed(rl_start, reg_start);
}
RegStorage r_tgt = LoadHelper(kQuickIndexOf);
+ CheckEntrypointTypes<kQuickIndexOf, int32_t, void*, uint32_t, uint32_t>();
GenExplicitNullCheck(reg_ptr, info->opt_flags);
LIR* high_code_point_branch =
rl_char.is_const ? nullptr : OpCmpImmBranch(kCondGt, reg_char, 0xFFFF, nullptr);
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 23601c3..6ff1e2e 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -85,7 +85,7 @@
exit(EXIT_FAILURE);
}
-JitCompiler::JitCompiler() : total_time_(0) {
+JitCompiler::JitCompiler() {
compiler_options_.reset(new CompilerOptions(
CompilerOptions::kDefaultCompilerFilter,
CompilerOptions::kDefaultHugeMethodThreshold,
@@ -195,7 +195,6 @@
bool JitCompiler::CompileMethod(Thread* self, ArtMethod* method, bool osr) {
DCHECK(!method->IsProxyMethod());
TimingLogger logger("JIT compiler timing logger", true, VLOG_IS_ON(jit));
- const uint64_t start_time = NanoTime();
StackHandleScope<2> hs(self);
self->AssertNoPendingException();
Runtime* runtime = Runtime::Current();
@@ -230,13 +229,12 @@
}
// Trim maps to reduce memory usage.
- // TODO: measure how much this increases compile time.
+ // TODO: move this to an idle phase.
{
TimingLogger::ScopedTiming t2("TrimMaps", &logger);
- runtime->GetArenaPool()->TrimMaps();
+ runtime->GetJitArenaPool()->TrimMaps();
}
- total_time_ += NanoTime() - start_time;
runtime->GetJit()->AddTimingLogger(logger);
return success;
}
diff --git a/compiler/jit/jit_compiler.h b/compiler/jit/jit_compiler.h
index 5294d0e..bc134fe 100644
--- a/compiler/jit/jit_compiler.h
+++ b/compiler/jit/jit_compiler.h
@@ -18,13 +18,10 @@
#define ART_COMPILER_JIT_JIT_COMPILER_H_
#include "base/mutex.h"
-#include "compiler_callbacks.h"
#include "compiled_method.h"
-#include "dex/verification_results.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
-#include "oat_file.h"
namespace art {
@@ -37,23 +34,19 @@
public:
static JitCompiler* Create();
virtual ~JitCompiler();
+
+ // Compilation entrypoint. Returns whether the compilation succeeded.
bool CompileMethod(Thread* self, ArtMethod* method, bool osr)
SHARED_REQUIRES(Locks::mutator_lock_);
- CompilerCallbacks* GetCompilerCallbacks() const;
- size_t GetTotalCompileTime() const {
- return total_time_;
- }
+
CompilerOptions* GetCompilerOptions() const {
return compiler_options_.get();
}
private:
- uint64_t total_time_;
std::unique_ptr<CompilerOptions> compiler_options_;
std::unique_ptr<CumulativeLogger> cumulative_logger_;
- std::unique_ptr<VerificationResults> verification_results_;
std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
- std::unique_ptr<CompilerCallbacks> callbacks_;
std::unique_ptr<CompilerDriver> compiler_driver_;
std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
std::unique_ptr<File> perf_file_;
@@ -62,8 +55,7 @@
// This is in the compiler since the runtime doesn't have access to the compiled method
// structures.
- bool AddToCodeCache(ArtMethod* method,
- const CompiledMethod* compiled_method)
+ bool AddToCodeCache(ArtMethod* method, const CompiledMethod* compiled_method)
SHARED_REQUIRES(Locks::mutator_lock_);
DISALLOW_COPY_AND_ASSIGN(JitCompiler);
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index 8d60be2..cf836a9 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -220,8 +220,7 @@
std::string reason;
ASSERT_TRUE(Runtime::Current()->GetJavaVM()->
- LoadNativeLibrary(env_, "", class_loader_, /* is_shared_namespace */ false,
- nullptr, nullptr, &reason))
+ LoadNativeLibrary(env_, "", class_loader_, nullptr, &reason))
<< reason;
jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
@@ -236,8 +235,7 @@
std::string reason;
ASSERT_TRUE(Runtime::Current()->GetJavaVM()->
- LoadNativeLibrary(env_, "", class_loader_, /* is_shared_namespace */ false,
- nullptr, nullptr, &reason))
+ LoadNativeLibrary(env_, "", class_loader_, nullptr, &reason))
<< reason;
jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42);
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index a7a1c0f..f2929bc 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -533,6 +533,8 @@
first_index_bounds_check_map_(
std::less<int>(),
graph->GetArena()->Adapter(kArenaAllocBoundsCheckElimination)),
+ dynamic_bce_standby_(
+ graph->GetArena()->Adapter(kArenaAllocBoundsCheckElimination)),
early_exit_loop_(
std::less<uint32_t>(),
graph->GetArena()->Adapter(kArenaAllocBoundsCheckElimination)),
@@ -553,6 +555,13 @@
}
void Finish() {
+ // Retry dynamic bce candidates on standby that are still in the graph.
+ for (HBoundsCheck* bounds_check : dynamic_bce_standby_) {
+ if (bounds_check->IsInBlock()) {
+ TryDynamicBCE(bounds_check);
+ }
+ }
+
// Preserve SSA structure which may have been broken by adding one or more
// new taken-test structures (see TransformLoopForDeoptimizationIfNeeded()).
InsertPhiNodes();
@@ -561,6 +570,7 @@
early_exit_loop_.clear();
taken_test_loop_.clear();
finite_loop_.clear();
+ dynamic_bce_standby_.clear();
}
private:
@@ -1301,7 +1311,7 @@
if (DynamicBCESeemsProfitable(loop, instruction->GetBlock()) &&
induction_range_.CanGenerateCode(
instruction, index, &needs_finite_test, &needs_taken_test) &&
- CanHandleInfiniteLoop(loop, index, needs_finite_test) &&
+ CanHandleInfiniteLoop(loop, instruction, index, needs_finite_test) &&
CanHandleLength(loop, length, needs_taken_test)) { // do this test last (may code gen)
HInstruction* lower = nullptr;
HInstruction* upper = nullptr;
@@ -1433,7 +1443,7 @@
* ensure the loop is finite.
*/
bool CanHandleInfiniteLoop(
- HLoopInformation* loop, HInstruction* index, bool needs_infinite_test) {
+ HLoopInformation* loop, HBoundsCheck* check, HInstruction* index, bool needs_infinite_test) {
if (needs_infinite_test) {
// If we already forced the loop to be finite, allow directly.
const uint32_t loop_id = loop->GetHeader()->GetBlockId();
@@ -1455,6 +1465,9 @@
}
}
}
+ // If bounds check made it this far, it is worthwhile to check later if
+ // the loop was forced finite by another candidate.
+ dynamic_bce_standby_.push_back(check);
return false;
}
return true;
@@ -1676,6 +1689,9 @@
// in a block that checks an index against that HArrayLength.
ArenaSafeMap<int, HBoundsCheck*> first_index_bounds_check_map_;
+ // Stand by list for dynamic bce.
+ ArenaVector<HBoundsCheck*> dynamic_bce_standby_;
+
// Early-exit loop bookkeeping.
ArenaSafeMap<uint32_t, bool> early_exit_loop_;
@@ -1711,21 +1727,18 @@
// that value dominated by that instruction fits in that range. Range of that
// value can be narrowed further down in the dominator tree.
BCEVisitor visitor(graph_, side_effects_, induction_analysis_);
- HBasicBlock* last_visited_block = nullptr;
for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
HBasicBlock* current = it.Current();
- if (current == last_visited_block) {
- // We may insert blocks into the reverse post order list when processing
- // a loop header. Don't process it again.
- DCHECK(current->IsLoopHeader());
- continue;
- }
if (visitor.IsAddedBlock(current)) {
// Skip added blocks. Their effects are already taken care of.
continue;
}
visitor.VisitBasicBlock(current);
- last_visited_block = current;
+ // Skip forward to the current block in case new basic blocks were inserted
+ // (which always appear earlier in reverse post order) to avoid visiting the
+ // same basic block twice.
+ for ( ; !it.Done() && it.Current() != current; it.Advance()) {
+ }
}
// Perform cleanup.
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index d550095..3e3719e 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -562,31 +562,16 @@
graph_->reverse_post_order_[++index] = otherwise;
graph_->reverse_post_order_[++index] = merge;
- // Set the loop information of the newly created blocks.
- HLoopInformation* loop_info = cursor_block->GetLoopInformation();
- if (loop_info != nullptr) {
- then->SetLoopInformation(cursor_block->GetLoopInformation());
- merge->SetLoopInformation(cursor_block->GetLoopInformation());
- otherwise->SetLoopInformation(cursor_block->GetLoopInformation());
- for (HLoopInformationOutwardIterator loop_it(*cursor_block);
- !loop_it.Done();
- loop_it.Advance()) {
- loop_it.Current()->Add(then);
- loop_it.Current()->Add(merge);
- loop_it.Current()->Add(otherwise);
- }
- // In case the original invoke location was a back edge, we need to update
- // the loop to now have the merge block as a back edge.
- if (loop_info->IsBackEdge(*original_invoke_block)) {
- loop_info->RemoveBackEdge(original_invoke_block);
- loop_info->AddBackEdge(merge);
- }
- }
- // Set the try/catch information of the newly created blocks.
- then->SetTryCatchInformation(cursor_block->GetTryCatchInformation());
- merge->SetTryCatchInformation(cursor_block->GetTryCatchInformation());
- otherwise->SetTryCatchInformation(cursor_block->GetTryCatchInformation());
+ graph_->UpdateLoopAndTryInformationOfNewBlock(
+ then, original_invoke_block, /* replace_if_back_edge */ false);
+ graph_->UpdateLoopAndTryInformationOfNewBlock(
+ otherwise, original_invoke_block, /* replace_if_back_edge */ false);
+
+ // In case the original invoke location was a back edge, we need to update
+ // the loop to now have the merge block as a back edge.
+ graph_->UpdateLoopAndTryInformationOfNewBlock(
+ merge, original_invoke_block, /* replace_if_back_edge */ true);
}
bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction,
@@ -603,6 +588,10 @@
DCHECK(resolved_method != nullptr);
ArtMethod* actual_method = nullptr;
+ size_t method_index = invoke_instruction->IsInvokeVirtual()
+ ? invoke_instruction->AsInvokeVirtual()->GetVTableIndex()
+ : invoke_instruction->AsInvokeInterface()->GetImtIndex();
+
// Check whether we are actually calling the same method among
// the different types seen.
for (size_t i = 0; i < InlineCache::kIndividualCacheSize; ++i) {
@@ -611,13 +600,18 @@
}
ArtMethod* new_method = nullptr;
if (invoke_instruction->IsInvokeInterface()) {
- new_method = ic.GetTypeAt(i)->FindVirtualMethodForInterface(
- resolved_method, pointer_size);
+ new_method = ic.GetTypeAt(i)->GetEmbeddedImTableEntry(
+ method_index % mirror::Class::kImtSize, pointer_size);
+ if (new_method->IsRuntimeMethod()) {
+ // Bail out as soon as we see a conflict trampoline in one of the target's
+ // interface table.
+ return false;
+ }
} else {
DCHECK(invoke_instruction->IsInvokeVirtual());
- new_method = ic.GetTypeAt(i)->FindVirtualMethodForVirtual(
- resolved_method, pointer_size);
+ new_method = ic.GetTypeAt(i)->GetEmbeddedVTableEntry(method_index, pointer_size);
}
+ DCHECK(new_method != nullptr);
if (actual_method == nullptr) {
actual_method = new_method;
} else if (actual_method != new_method) {
@@ -641,10 +635,6 @@
HInstanceFieldGet* receiver_class = BuildGetReceiverClass(
class_linker, receiver, invoke_instruction->GetDexPc());
- size_t method_offset = invoke_instruction->IsInvokeVirtual()
- ? actual_method->GetVtableIndex()
- : invoke_instruction->AsInvokeInterface()->GetImtIndex();
-
Primitive::Type type = Is64BitInstructionSet(graph_->GetInstructionSet())
? Primitive::kPrimLong
: Primitive::kPrimInt;
@@ -653,7 +643,7 @@
type,
invoke_instruction->IsInvokeVirtual() ? HClassTableGet::TableKind::kVTable
: HClassTableGet::TableKind::kIMTable,
- method_offset,
+ method_index,
invoke_instruction->GetDexPc());
HConstant* constant;
@@ -1020,6 +1010,8 @@
// at runtime, we change this call as if it was a virtual call.
invoke_type = kVirtual;
}
+
+ const int32_t caller_instruction_counter = graph_->GetCurrentInstructionId();
HGraph* callee_graph = new (graph_->GetArena()) HGraph(
graph_->GetArena(),
callee_dex_file,
@@ -1029,7 +1021,7 @@
invoke_type,
graph_->IsDebuggable(),
/* osr */ false,
- graph_->GetCurrentInstructionId());
+ caller_instruction_counter);
callee_graph->SetArtMethod(resolved_method);
OptimizingCompilerStats inline_stats;
@@ -1229,7 +1221,16 @@
}
number_of_inlined_instructions_ += number_of_instructions;
+ DCHECK_EQ(caller_instruction_counter, graph_->GetCurrentInstructionId())
+ << "No instructions can be added to the outer graph while inner graph is being built";
+
+ const int32_t callee_instruction_counter = callee_graph->GetCurrentInstructionId();
+ graph_->SetCurrentInstructionId(callee_instruction_counter);
*return_replacement = callee_graph->InlineInto(graph_, invoke_instruction);
+
+ DCHECK_EQ(callee_instruction_counter, callee_graph->GetCurrentInstructionId())
+ << "No instructions can be added to the inner graph during inlining into the outer graph";
+
return true;
}
diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h
index 2ab50bb..0cec5cc 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -193,6 +193,46 @@
#undef INTRISIC_OPTIMIZATION
+//
+// Macros for use in the intrinsics code generators.
+//
+
+// Defines an unimplemented intrinsic: that is, a method call that is recognized as an
+// intrinsic to exploit e.g. no side-effects or exceptions, but otherwise not handled
+// by this architecture-specific intrinsics code generator. Eventually it is implemented
+// as a true method call.
+#define UNIMPLEMENTED_INTRINSIC(Arch, Name) \
+void IntrinsicLocationsBuilder ## Arch::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
+} \
+void IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
+}
+
+// Defines a list of unreached intrinsics: that is, method calls that are recognized as
+// an intrinsic, and then always converted into HIR instructions before they reach any
+// architecture-specific intrinsics code generator.
+#define UNREACHABLE_INTRINSIC(Arch, Name) \
+void IntrinsicLocationsBuilder ## Arch::Visit ## Name(HInvoke* invoke) { \
+ LOG(FATAL) << "Unreachable: intrinsic " << invoke->GetIntrinsic() \
+ << " should have been converted to HIR"; \
+} \
+void IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke) { \
+ LOG(FATAL) << "Unreachable: intrinsic " << invoke->GetIntrinsic() \
+ << " should have been converted to HIR"; \
+}
+#define UNREACHABLE_INTRINSICS(Arch) \
+UNREACHABLE_INTRINSIC(Arch, FloatFloatToIntBits) \
+UNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) \
+UNREACHABLE_INTRINSIC(Arch, FloatIsNaN) \
+UNREACHABLE_INTRINSIC(Arch, DoubleIsNaN) \
+UNREACHABLE_INTRINSIC(Arch, IntegerRotateLeft) \
+UNREACHABLE_INTRINSIC(Arch, LongRotateLeft) \
+UNREACHABLE_INTRINSIC(Arch, IntegerRotateRight) \
+UNREACHABLE_INTRINSIC(Arch, LongRotateRight) \
+UNREACHABLE_INTRINSIC(Arch, IntegerCompare) \
+UNREACHABLE_INTRINSIC(Arch, LongCompare) \
+UNREACHABLE_INTRINSIC(Arch, IntegerSignum) \
+UNREACHABLE_INTRINSIC(Arch, LongSignum)
+
} // namespace art
#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_H_
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index 4ce919e..69c9708 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -1151,6 +1151,7 @@
__ LoadFromOffset(kLoadWord, LR, TR,
QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pIndexOf).Int32Value());
+ CheckEntrypointTypes<kQuickIndexOf, int32_t, void*, uint32_t, uint32_t>();
__ blx(LR);
if (slow_path != nullptr) {
@@ -1242,6 +1243,12 @@
void IntrinsicCodeGeneratorARM::VisitStringNewStringFromChars(HInvoke* invoke) {
ArmAssembler* assembler = GetAssembler();
+ // No need to emit code checking whether `locations->InAt(2)` is a null
+ // pointer, as callers of the native method
+ //
+ // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)
+ //
+ // all include a null check on `data` before calling that method.
__ LoadFromOffset(
kLoadWord, LR, TR, QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pAllocStringFromChars).Int32Value());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
@@ -1972,54 +1979,30 @@
__ Bind(&done);
}
-// Unimplemented intrinsics.
+UNIMPLEMENTED_INTRINSIC(ARM, IntegerBitCount)
+UNIMPLEMENTED_INTRINSIC(ARM, LongBitCount)
+UNIMPLEMENTED_INTRINSIC(ARM, MathMinDoubleDouble)
+UNIMPLEMENTED_INTRINSIC(ARM, MathMinFloatFloat)
+UNIMPLEMENTED_INTRINSIC(ARM, MathMaxDoubleDouble)
+UNIMPLEMENTED_INTRINSIC(ARM, MathMaxFloatFloat)
+UNIMPLEMENTED_INTRINSIC(ARM, MathMinLongLong)
+UNIMPLEMENTED_INTRINSIC(ARM, MathMaxLongLong)
+UNIMPLEMENTED_INTRINSIC(ARM, MathCeil) // Could be done by changing rounding mode, maybe?
+UNIMPLEMENTED_INTRINSIC(ARM, MathFloor) // Could be done by changing rounding mode, maybe?
+UNIMPLEMENTED_INTRINSIC(ARM, MathRint)
+UNIMPLEMENTED_INTRINSIC(ARM, MathRoundDouble) // Could be done by changing rounding mode, maybe?
+UNIMPLEMENTED_INTRINSIC(ARM, MathRoundFloat) // Could be done by changing rounding mode, maybe?
+UNIMPLEMENTED_INTRINSIC(ARM, UnsafeCASLong) // High register pressure.
+UNIMPLEMENTED_INTRINSIC(ARM, SystemArrayCopyChar)
+UNIMPLEMENTED_INTRINSIC(ARM, ReferenceGetReferent)
+UNIMPLEMENTED_INTRINSIC(ARM, FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(ARM, DoubleIsInfinite)
+UNIMPLEMENTED_INTRINSIC(ARM, IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(ARM, LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(ARM, IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(ARM, LongLowestOneBit)
-#define UNIMPLEMENTED_INTRINSIC(Name) \
-void IntrinsicLocationsBuilderARM::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-} \
-void IntrinsicCodeGeneratorARM::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-}
-
-UNIMPLEMENTED_INTRINSIC(IntegerBitCount)
-UNIMPLEMENTED_INTRINSIC(LongBitCount)
-UNIMPLEMENTED_INTRINSIC(MathMinDoubleDouble)
-UNIMPLEMENTED_INTRINSIC(MathMinFloatFloat)
-UNIMPLEMENTED_INTRINSIC(MathMaxDoubleDouble)
-UNIMPLEMENTED_INTRINSIC(MathMaxFloatFloat)
-UNIMPLEMENTED_INTRINSIC(MathMinLongLong)
-UNIMPLEMENTED_INTRINSIC(MathMaxLongLong)
-UNIMPLEMENTED_INTRINSIC(MathCeil) // Could be done by changing rounding mode, maybe?
-UNIMPLEMENTED_INTRINSIC(MathFloor) // Could be done by changing rounding mode, maybe?
-UNIMPLEMENTED_INTRINSIC(MathRint)
-UNIMPLEMENTED_INTRINSIC(MathRoundDouble) // Could be done by changing rounding mode, maybe?
-UNIMPLEMENTED_INTRINSIC(MathRoundFloat) // Could be done by changing rounding mode, maybe?
-UNIMPLEMENTED_INTRINSIC(UnsafeCASLong) // High register pressure.
-UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
-
-UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
-UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
-
-UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
-
-// Handled as HIR instructions.
-UNIMPLEMENTED_INTRINSIC(FloatFloatToIntBits)
-UNIMPLEMENTED_INTRINSIC(DoubleDoubleToLongBits)
-UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
-UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
-UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
-UNIMPLEMENTED_INTRINSIC(LongRotateRight)
-UNIMPLEMENTED_INTRINSIC(IntegerCompare)
-UNIMPLEMENTED_INTRINSIC(LongCompare)
-UNIMPLEMENTED_INTRINSIC(IntegerSignum)
-UNIMPLEMENTED_INTRINSIC(LongSignum)
-
-#undef UNIMPLEMENTED_INTRINSIC
+UNREACHABLE_INTRINSICS(ARM)
#undef __
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 4be1695..934b427 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -46,6 +46,7 @@
using helpers::SRegisterFrom;
using helpers::WRegisterFrom;
using helpers::XRegisterFrom;
+using helpers::InputRegisterAt;
namespace {
@@ -367,6 +368,40 @@
GenReverse(invoke->GetLocations(), Primitive::kPrimLong, GetVIXLAssembler());
}
+static void GenBitCount(HInvoke* instr, bool is_long, vixl::MacroAssembler* masm) {
+ DCHECK(instr->GetType() == Primitive::kPrimInt);
+ DCHECK((is_long && instr->InputAt(0)->GetType() == Primitive::kPrimLong) ||
+ (!is_long && instr->InputAt(0)->GetType() == Primitive::kPrimInt));
+
+ Location out = instr->GetLocations()->Out();
+ UseScratchRegisterScope temps(masm);
+
+ Register src = InputRegisterAt(instr, 0);
+ Register dst = is_long ? XRegisterFrom(out) : WRegisterFrom(out);
+ FPRegister fpr = is_long ? temps.AcquireD() : temps.AcquireS();
+
+ __ Fmov(fpr, src);
+ __ Cnt(fpr.V8B(), fpr.V8B());
+ __ Addv(fpr.B(), fpr.V8B());
+ __ Fmov(dst, fpr);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitLongBitCount(HInvoke* invoke) {
+ CreateIntToIntLocations(arena_, invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitLongBitCount(HInvoke* invoke) {
+ GenBitCount(invoke, /* is_long */ true, GetVIXLAssembler());
+}
+
+void IntrinsicLocationsBuilderARM64::VisitIntegerBitCount(HInvoke* invoke) {
+ CreateIntToIntLocations(arena_, invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitIntegerBitCount(HInvoke* invoke) {
+ GenBitCount(invoke, /* is_long */ false, GetVIXLAssembler());
+}
+
static void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) {
LocationSummary* locations = new (arena) LocationSummary(invoke,
LocationSummary::kNoCall,
@@ -1301,6 +1336,7 @@
}
__ Ldr(lr, MemOperand(tr, QUICK_ENTRYPOINT_OFFSET(kArm64WordSize, pIndexOf).Int32Value()));
+ CheckEntrypointTypes<kQuickIndexOf, int32_t, void*, uint32_t, uint32_t>();
__ Blr(lr);
if (slow_path != nullptr) {
@@ -1392,6 +1428,12 @@
void IntrinsicCodeGeneratorARM64::VisitStringNewStringFromChars(HInvoke* invoke) {
vixl::MacroAssembler* masm = GetVIXLAssembler();
+ // No need to emit code checking whether `locations->InAt(2)` is a null
+ // pointer, as callers of the native method
+ //
+ // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)
+ //
+ // all include a null check on `data` before calling that method.
__ Ldr(lr,
MemOperand(tr, QUICK_ENTRYPOINT_OFFSET(kArm64WordSize, pAllocStringFromChars).Int32Value()));
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
@@ -1665,43 +1707,253 @@
__ Bind(&done);
}
-// Unimplemented intrinsics.
+// Mirrors ARRAYCOPY_SHORT_CHAR_ARRAY_THRESHOLD in libcore, so we can choose to use the native
+// implementation there for longer copy lengths.
+static constexpr int32_t kSystemArrayCopyThreshold = 32;
-#define UNIMPLEMENTED_INTRINSIC(Name) \
-void IntrinsicLocationsBuilderARM64::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-} \
-void IntrinsicCodeGeneratorARM64::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
+static void SetSystemArrayCopyLocationRequires(LocationSummary* locations,
+ uint32_t at,
+ HInstruction* input) {
+ HIntConstant* const_input = input->AsIntConstant();
+ if (const_input != nullptr && !vixl::Assembler::IsImmAddSub(const_input->GetValue())) {
+ locations->SetInAt(at, Location::RequiresRegister());
+ } else {
+ locations->SetInAt(at, Location::RegisterOrConstant(input));
+ }
}
-UNIMPLEMENTED_INTRINSIC(IntegerBitCount)
-UNIMPLEMENTED_INTRINSIC(LongBitCount)
-UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(SystemArrayCopy)
-UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
+void IntrinsicLocationsBuilderARM64::VisitSystemArrayCopyChar(HInvoke* invoke) {
+ // Check to see if we have known failures that will cause us to have to bail out
+ // to the runtime, and just generate the runtime call directly.
+ HIntConstant* src_pos = invoke->InputAt(1)->AsIntConstant();
+ HIntConstant* dst_pos = invoke->InputAt(3)->AsIntConstant();
-UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
-UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
+ // The positions must be non-negative.
+ if ((src_pos != nullptr && src_pos->GetValue() < 0) ||
+ (dst_pos != nullptr && dst_pos->GetValue() < 0)) {
+ // We will have to fail anyways.
+ return;
+ }
-UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
+ // The length must be >= 0 and not so long that we would (currently) prefer libcore's
+ // native implementation.
+ HIntConstant* length = invoke->InputAt(4)->AsIntConstant();
+ if (length != nullptr) {
+ int32_t len = length->GetValue();
+ if (len < 0 || len > kSystemArrayCopyThreshold) {
+ // Just call as normal.
+ return;
+ }
+ }
-// Handled as HIR instructions.
-UNIMPLEMENTED_INTRINSIC(FloatFloatToIntBits)
-UNIMPLEMENTED_INTRINSIC(DoubleDoubleToLongBits)
-UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
-UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
-UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
-UNIMPLEMENTED_INTRINSIC(LongRotateRight)
-UNIMPLEMENTED_INTRINSIC(IntegerCompare)
-UNIMPLEMENTED_INTRINSIC(LongCompare)
-UNIMPLEMENTED_INTRINSIC(IntegerSignum)
-UNIMPLEMENTED_INTRINSIC(LongSignum)
+ ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetArena();
+ LocationSummary* locations = new (allocator) LocationSummary(invoke,
+ LocationSummary::kCallOnSlowPath,
+ kIntrinsified);
+ // arraycopy(char[] src, int src_pos, char[] dst, int dst_pos, int length).
+ locations->SetInAt(0, Location::RequiresRegister());
+ SetSystemArrayCopyLocationRequires(locations, 1, invoke->InputAt(1));
+ locations->SetInAt(2, Location::RequiresRegister());
+ SetSystemArrayCopyLocationRequires(locations, 3, invoke->InputAt(3));
+ SetSystemArrayCopyLocationRequires(locations, 4, invoke->InputAt(4));
-#undef UNIMPLEMENTED_INTRINSIC
+ locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister());
+}
+
+static void CheckSystemArrayCopyPosition(vixl::MacroAssembler* masm,
+ const Location& pos,
+ const Register& input,
+ const Location& length,
+ SlowPathCodeARM64* slow_path,
+ const Register& input_len,
+ const Register& temp,
+ bool length_is_input_length = false) {
+ const int32_t length_offset = mirror::Array::LengthOffset().Int32Value();
+ if (pos.IsConstant()) {
+ int32_t pos_const = pos.GetConstant()->AsIntConstant()->GetValue();
+ if (pos_const == 0) {
+ if (!length_is_input_length) {
+ // Check that length(input) >= length.
+ __ Ldr(temp, MemOperand(input, length_offset));
+ __ Cmp(temp, OperandFrom(length, Primitive::kPrimInt));
+ __ B(slow_path->GetEntryLabel(), lt);
+ }
+ } else {
+ // Check that length(input) >= pos.
+ __ Ldr(input_len, MemOperand(input, length_offset));
+ __ Subs(temp, input_len, pos_const);
+ __ B(slow_path->GetEntryLabel(), lt);
+
+ // Check that (length(input) - pos) >= length.
+ __ Cmp(temp, OperandFrom(length, Primitive::kPrimInt));
+ __ B(slow_path->GetEntryLabel(), lt);
+ }
+ } else if (length_is_input_length) {
+ // The only way the copy can succeed is if pos is zero.
+ __ Cbnz(WRegisterFrom(pos), slow_path->GetEntryLabel());
+ } else {
+ // Check that pos >= 0.
+ Register pos_reg = WRegisterFrom(pos);
+ __ Tbnz(pos_reg, pos_reg.size() - 1, slow_path->GetEntryLabel());
+
+ // Check that pos <= length(input) && (length(input) - pos) >= length.
+ __ Ldr(temp, MemOperand(input, length_offset));
+ __ Subs(temp, temp, pos_reg);
+ // Ccmp if length(input) >= pos, else definitely bail to slow path (N!=V == lt).
+ __ Ccmp(temp, OperandFrom(length, Primitive::kPrimInt), NFlag, ge);
+ __ B(slow_path->GetEntryLabel(), lt);
+ }
+}
+
+// Compute base source address, base destination address, and end source address
+// for System.arraycopy* intrinsics.
+static void GenSystemArrayCopyAddresses(vixl::MacroAssembler* masm,
+ Primitive::Type type,
+ const Register& src,
+ const Location& src_pos,
+ const Register& dst,
+ const Location& dst_pos,
+ const Location& copy_length,
+ const Register& src_base,
+ const Register& dst_base,
+ const Register& src_end) {
+ DCHECK(type == Primitive::kPrimNot || type == Primitive::kPrimChar)
+ << "Unexpected element type: "
+ << type;
+ const int32_t char_size = Primitive::ComponentSize(type);
+ const int32_t char_size_shift = Primitive::ComponentSizeShift(type);
+
+ uint32_t offset = mirror::Array::DataOffset(char_size).Uint32Value();
+ if (src_pos.IsConstant()) {
+ int32_t constant = src_pos.GetConstant()->AsIntConstant()->GetValue();
+ __ Add(src_base, src, char_size * constant + offset);
+ } else {
+ __ Add(src_base, src, offset);
+ __ Add(src_base,
+ src_base,
+ Operand(XRegisterFrom(src_pos), LSL, char_size_shift));
+ }
+
+ if (dst_pos.IsConstant()) {
+ int32_t constant = dst_pos.GetConstant()->AsIntConstant()->GetValue();
+ __ Add(dst_base, dst, char_size * constant + offset);
+ } else {
+ __ Add(dst_base, dst, offset);
+ __ Add(dst_base,
+ dst_base,
+ Operand(XRegisterFrom(dst_pos), LSL, char_size_shift));
+ }
+
+ if (copy_length.IsConstant()) {
+ int32_t constant = copy_length.GetConstant()->AsIntConstant()->GetValue();
+ __ Add(src_end, src_base, char_size * constant);
+ } else {
+ __ Add(src_end,
+ src_base,
+ Operand(XRegisterFrom(copy_length), LSL, char_size_shift));
+ }
+}
+
+void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopyChar(HInvoke* invoke) {
+ vixl::MacroAssembler* masm = GetVIXLAssembler();
+ LocationSummary* locations = invoke->GetLocations();
+ Register src = XRegisterFrom(locations->InAt(0));
+ Location src_pos = locations->InAt(1);
+ Register dst = XRegisterFrom(locations->InAt(2));
+ Location dst_pos = locations->InAt(3);
+ Location length = locations->InAt(4);
+
+ SlowPathCodeARM64* slow_path = new (GetAllocator()) IntrinsicSlowPathARM64(invoke);
+ codegen_->AddSlowPath(slow_path);
+
+ // If source and destination are the same, take the slow path. Overlapping copy regions must be
+ // copied in reverse and we can't know in all cases if it's needed.
+ __ Cmp(src, dst);
+ __ B(slow_path->GetEntryLabel(), eq);
+
+ // Bail out if the source is null.
+ __ Cbz(src, slow_path->GetEntryLabel());
+
+ // Bail out if the destination is null.
+ __ Cbz(dst, slow_path->GetEntryLabel());
+
+ if (!length.IsConstant()) {
+ // If the length is negative, bail out.
+ __ Tbnz(WRegisterFrom(length), kWRegSize - 1, slow_path->GetEntryLabel());
+ // If the length > 32 then (currently) prefer libcore's native implementation.
+ __ Cmp(WRegisterFrom(length), kSystemArrayCopyThreshold);
+ __ B(slow_path->GetEntryLabel(), gt);
+ } else {
+ // We have already checked in the LocationsBuilder for the constant case.
+ DCHECK_GE(length.GetConstant()->AsIntConstant()->GetValue(), 0);
+ DCHECK_LE(length.GetConstant()->AsIntConstant()->GetValue(), 32);
+ }
+
+ Register src_curr_addr = WRegisterFrom(locations->GetTemp(0));
+ Register dst_curr_addr = WRegisterFrom(locations->GetTemp(1));
+ Register src_stop_addr = WRegisterFrom(locations->GetTemp(2));
+
+ CheckSystemArrayCopyPosition(masm,
+ src_pos,
+ src,
+ length,
+ slow_path,
+ src_curr_addr,
+ dst_curr_addr,
+ false);
+
+ CheckSystemArrayCopyPosition(masm,
+ dst_pos,
+ dst,
+ length,
+ slow_path,
+ src_curr_addr,
+ dst_curr_addr,
+ false);
+
+ src_curr_addr = src_curr_addr.X();
+ dst_curr_addr = dst_curr_addr.X();
+ src_stop_addr = src_stop_addr.X();
+
+ GenSystemArrayCopyAddresses(masm,
+ Primitive::kPrimChar,
+ src,
+ src_pos,
+ dst,
+ dst_pos,
+ length,
+ src_curr_addr,
+ dst_curr_addr,
+ src_stop_addr);
+
+ // Iterate over the arrays and do a raw copy of the chars.
+ const int32_t char_size = Primitive::ComponentSize(Primitive::kPrimChar);
+ UseScratchRegisterScope temps(masm);
+ Register tmp = temps.AcquireW();
+ vixl::Label loop, done;
+ __ Bind(&loop);
+ __ Cmp(src_curr_addr, src_stop_addr);
+ __ B(&done, eq);
+ __ Ldrh(tmp, MemOperand(src_curr_addr, char_size, vixl::PostIndex));
+ __ Strh(tmp, MemOperand(dst_curr_addr, char_size, vixl::PostIndex));
+ __ B(&loop);
+ __ Bind(&done);
+
+ __ Bind(slow_path->GetExitLabel());
+}
+
+UNIMPLEMENTED_INTRINSIC(ARM64, SystemArrayCopy)
+UNIMPLEMENTED_INTRINSIC(ARM64, ReferenceGetReferent)
+UNIMPLEMENTED_INTRINSIC(ARM64, FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(ARM64, DoubleIsInfinite)
+UNIMPLEMENTED_INTRINSIC(ARM64, IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(ARM64, LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(ARM64, IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(ARM64, LongLowestOneBit)
+
+UNREACHABLE_INTRINSICS(ARM64)
#undef __
diff --git a/compiler/optimizing/intrinsics_list.h b/compiler/optimizing/intrinsics_list.h
index e1aea92..b8933e1 100644
--- a/compiler/optimizing/intrinsics_list.h
+++ b/compiler/optimizing/intrinsics_list.h
@@ -19,7 +19,7 @@
// All intrinsics supported by the optimizing compiler. Format is name, then whether it is expected
// to be a HInvokeStaticOrDirect node (compared to HInvokeVirtual), then whether it requires an
-// environment.
+// environment, may have side effects, or may throw exceptions.
#define INTRINSICS_LIST(V) \
V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index a737d81..710df0a 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -490,7 +490,6 @@
static void GenNumberOfTrailingZeroes(LocationSummary* locations,
bool is64bit,
bool isR6,
- bool isR2OrNewer,
MipsAssembler* assembler) {
Register out = locations->Out().AsRegister<Register>();
Register in_lo;
@@ -503,7 +502,7 @@
// If in_lo is zero then count the number of trailing zeroes in in_hi;
// otherwise count the number of trailing zeroes in in_lo.
- // AT = in_lo ? in_lo : in_hi;
+ // out = in_lo ? in_lo : in_hi;
if (isR6) {
__ Seleqz(out, in_hi, in_lo);
__ Selnez(TMP, in_lo, in_lo);
@@ -522,50 +521,26 @@
in_lo = in;
}
- // We don't have an instruction to count the number of trailing zeroes.
- // Start by flipping the bits end-for-end so we can count the number of
- // leading zeroes instead.
- if (isR2OrNewer) {
+ if (isR6) {
+ // We don't have an instruction to count the number of trailing zeroes.
+ // Start by flipping the bits end-for-end so we can count the number of
+ // leading zeroes instead.
__ Rotr(out, in, 16);
__ Wsbh(out, out);
- } else {
- // MIPS32r1
- // __ Rotr(out, in, 16);
- __ Sll(TMP, in, 16);
- __ Srl(out, in, 16);
- __ Or(out, out, TMP);
- // __ Wsbh(out, out);
- __ LoadConst32(AT, 0x00FF00FF);
- __ And(TMP, out, AT);
- __ Sll(TMP, TMP, 8);
- __ Srl(out, out, 8);
- __ And(out, out, AT);
- __ Or(out, out, TMP);
- }
-
- if (isR6) {
__ Bitswap(out, out);
__ ClzR6(out, out);
} else {
- __ LoadConst32(AT, 0x0F0F0F0F);
- __ And(TMP, out, AT);
- __ Sll(TMP, TMP, 4);
- __ Srl(out, out, 4);
- __ And(out, out, AT);
- __ Or(out, TMP, out);
- __ LoadConst32(AT, 0x33333333);
- __ And(TMP, out, AT);
- __ Sll(TMP, TMP, 2);
- __ Srl(out, out, 2);
- __ And(out, out, AT);
- __ Or(out, TMP, out);
- __ LoadConst32(AT, 0x55555555);
- __ And(TMP, out, AT);
- __ Sll(TMP, TMP, 1);
- __ Srl(out, out, 1);
- __ And(out, out, AT);
- __ Or(out, TMP, out);
+ // Convert trailing zeroes to trailing ones, and bits to their left
+ // to zeroes.
+ __ Addiu(TMP, in, -1);
+ __ Xor(out, TMP, in);
+ __ And(out, out, TMP);
+ // Count number of leading zeroes.
__ ClzR2(out, out);
+ // Subtract number of leading zeroes from 32 to get number of trailing ones.
+ // Remember that the trailing ones were formerly trailing zeroes.
+ __ LoadConst32(TMP, 32);
+ __ Subu(out, TMP, out);
}
if (is64bit) {
@@ -587,11 +562,7 @@
}
void IntrinsicCodeGeneratorMIPS::VisitIntegerNumberOfTrailingZeros(HInvoke* invoke) {
- GenNumberOfTrailingZeroes(invoke->GetLocations(),
- /* is64bit */ false,
- IsR6(),
- IsR2OrNewer(),
- GetAssembler());
+ GenNumberOfTrailingZeroes(invoke->GetLocations(), /* is64bit */ false, IsR6(), GetAssembler());
}
// int java.lang.Long.numberOfTrailingZeros(long i)
@@ -600,207 +571,7 @@
}
void IntrinsicCodeGeneratorMIPS::VisitLongNumberOfTrailingZeros(HInvoke* invoke) {
- GenNumberOfTrailingZeroes(invoke->GetLocations(),
- /* is64bit */ true,
- IsR6(),
- IsR2OrNewer(),
- GetAssembler());
-}
-
-enum RotationDirection {
- kRotateRight,
- kRotateLeft,
-};
-
-static void GenRotate(HInvoke* invoke,
- Primitive::Type type,
- bool isR2OrNewer,
- RotationDirection direction,
- MipsAssembler* assembler) {
- DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
-
- LocationSummary* locations = invoke->GetLocations();
- if (invoke->InputAt(1)->IsIntConstant()) {
- int32_t shift = static_cast<int32_t>(invoke->InputAt(1)->AsIntConstant()->GetValue());
- if (type == Primitive::kPrimInt) {
- Register in = locations->InAt(0).AsRegister<Register>();
- Register out = locations->Out().AsRegister<Register>();
-
- shift &= 0x1f;
- if (direction == kRotateLeft) {
- shift = (32 - shift) & 0x1F;
- }
-
- if (isR2OrNewer) {
- if ((shift != 0) || (out != in)) {
- __ Rotr(out, in, shift);
- }
- } else {
- if (shift == 0) {
- if (out != in) {
- __ Move(out, in);
- }
- } else {
- __ Srl(AT, in, shift);
- __ Sll(out, in, 32 - shift);
- __ Or(out, out, AT);
- }
- }
- } else { // Primitive::kPrimLong
- Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>();
- Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>();
- Register out_lo = locations->Out().AsRegisterPairLow<Register>();
- Register out_hi = locations->Out().AsRegisterPairHigh<Register>();
-
- shift &= 0x3f;
- if (direction == kRotateLeft) {
- shift = (64 - shift) & 0x3F;
- }
-
- if (shift == 0) {
- __ Move(out_lo, in_lo);
- __ Move(out_hi, in_hi);
- } else if (shift == 32) {
- __ Move(out_lo, in_hi);
- __ Move(out_hi, in_lo);
- } else if (shift < 32) {
- __ Srl(AT, in_lo, shift);
- __ Sll(out_lo, in_hi, 32 - shift);
- __ Or(out_lo, out_lo, AT);
- __ Srl(AT, in_hi, shift);
- __ Sll(out_hi, in_lo, 32 - shift);
- __ Or(out_hi, out_hi, AT);
- } else {
- __ Sll(AT, in_lo, 64 - shift);
- __ Srl(out_lo, in_hi, shift - 32);
- __ Or(out_lo, out_lo, AT);
- __ Sll(AT, in_hi, 64 - shift);
- __ Srl(out_hi, in_lo, shift - 32);
- __ Or(out_hi, out_hi, AT);
- }
- }
- } else { // !invoke->InputAt(1)->IsIntConstant()
- Register shamt = locations->InAt(1).AsRegister<Register>();
- if (type == Primitive::kPrimInt) {
- Register in = locations->InAt(0).AsRegister<Register>();
- Register out = locations->Out().AsRegister<Register>();
-
- if (isR2OrNewer) {
- if (direction == kRotateRight) {
- __ Rotrv(out, in, shamt);
- } else {
- // negu tmp, shamt
- __ Subu(TMP, ZERO, shamt);
- __ Rotrv(out, in, TMP);
- }
- } else {
- if (direction == kRotateRight) {
- __ Srlv(AT, in, shamt);
- __ Subu(TMP, ZERO, shamt);
- __ Sllv(out, in, TMP);
- __ Or(out, out, AT);
- } else {
- __ Sllv(AT, in, shamt);
- __ Subu(TMP, ZERO, shamt);
- __ Srlv(out, in, TMP);
- __ Or(out, out, AT);
- }
- }
- } else { // Primitive::kPrimLong
- Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>();
- Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>();
- Register out_lo = locations->Out().AsRegisterPairLow<Register>();
- Register out_hi = locations->Out().AsRegisterPairHigh<Register>();
-
- MipsLabel done;
-
- if (direction == kRotateRight) {
- __ Nor(TMP, ZERO, shamt);
- __ Srlv(AT, in_lo, shamt);
- __ Sll(out_lo, in_hi, 1);
- __ Sllv(out_lo, out_lo, TMP);
- __ Or(out_lo, out_lo, AT);
- __ Srlv(AT, in_hi, shamt);
- __ Sll(out_hi, in_lo, 1);
- __ Sllv(out_hi, out_hi, TMP);
- __ Or(out_hi, out_hi, AT);
- } else {
- __ Nor(TMP, ZERO, shamt);
- __ Sllv(AT, in_lo, shamt);
- __ Srl(out_lo, in_hi, 1);
- __ Srlv(out_lo, out_lo, TMP);
- __ Or(out_lo, out_lo, AT);
- __ Sllv(AT, in_hi, shamt);
- __ Srl(out_hi, in_lo, 1);
- __ Srlv(out_hi, out_hi, TMP);
- __ Or(out_hi, out_hi, AT);
- }
-
- __ Andi(TMP, shamt, 32);
- __ Beqz(TMP, &done);
- __ Move(TMP, out_hi);
- __ Move(out_hi, out_lo);
- __ Move(out_lo, TMP);
-
- __ Bind(&done);
- }
- }
-}
-
-// int java.lang.Integer.rotateRight(int i, int distance)
-void IntrinsicLocationsBuilderMIPS::VisitIntegerRotateRight(HInvoke* invoke) {
- LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kNoCall,
- kIntrinsified);
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(invoke->InputAt(1)));
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
-}
-
-void IntrinsicCodeGeneratorMIPS::VisitIntegerRotateRight(HInvoke* invoke) {
- GenRotate(invoke, Primitive::kPrimInt, IsR2OrNewer(), kRotateRight, GetAssembler());
-}
-
-// long java.lang.Long.rotateRight(long i, int distance)
-void IntrinsicLocationsBuilderMIPS::VisitLongRotateRight(HInvoke* invoke) {
- LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kNoCall,
- kIntrinsified);
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(invoke->InputAt(1)));
- locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
-}
-
-void IntrinsicCodeGeneratorMIPS::VisitLongRotateRight(HInvoke* invoke) {
- GenRotate(invoke, Primitive::kPrimLong, IsR2OrNewer(), kRotateRight, GetAssembler());
-}
-
-// int java.lang.Integer.rotateLeft(int i, int distance)
-void IntrinsicLocationsBuilderMIPS::VisitIntegerRotateLeft(HInvoke* invoke) {
- LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kNoCall,
- kIntrinsified);
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(invoke->InputAt(1)));
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
-}
-
-void IntrinsicCodeGeneratorMIPS::VisitIntegerRotateLeft(HInvoke* invoke) {
- GenRotate(invoke, Primitive::kPrimInt, IsR2OrNewer(), kRotateLeft, GetAssembler());
-}
-
-// long java.lang.Long.rotateLeft(long i, int distance)
-void IntrinsicLocationsBuilderMIPS::VisitLongRotateLeft(HInvoke* invoke) {
- LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kNoCall,
- kIntrinsified);
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(invoke->InputAt(1)));
- locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
-}
-
-void IntrinsicCodeGeneratorMIPS::VisitLongRotateLeft(HInvoke* invoke) {
- GenRotate(invoke, Primitive::kPrimLong, IsR2OrNewer(), kRotateLeft, GetAssembler());
+ GenNumberOfTrailingZeroes(invoke->GetLocations(), /* is64bit */ true, IsR6(), GetAssembler());
}
// int java.lang.Integer.reverse(int)
@@ -839,6 +610,142 @@
locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
}
+static void GenBitCount(LocationSummary* locations,
+ Primitive::Type type,
+ bool isR6,
+ MipsAssembler* assembler) {
+ DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
+
+ Register out = locations->Out().AsRegister<Register>();
+
+ // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
+ //
+ // A generalization of the best bit counting method to integers of
+ // bit-widths up to 128 (parameterized by type T) is this:
+ //
+ // v = v - ((v >> 1) & (T)~(T)0/3); // temp
+ // v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3); // temp
+ // v = (v + (v >> 4)) & (T)~(T)0/255*15; // temp
+ // c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * BITS_PER_BYTE; // count
+ //
+ // For comparison, for 32-bit quantities, this algorithm can be executed
+ // using 20 MIPS instructions (the calls to LoadConst32() generate two
+ // machine instructions each for the values being used in this algorithm).
+ // A(n unrolled) loop-based algorithm required 25 instructions.
+ //
+ // For 64-bit quantities, this algorithm gets executed twice, (once
+ // for in_lo, and again for in_hi), but saves a few instructions
+ // because the mask values only have to be loaded once. Using this
+ // algorithm the count for a 64-bit operand can be performed in 33
+ // instructions compared to a loop-based algorithm which required 47
+ // instructions.
+
+ if (type == Primitive::kPrimInt) {
+ Register in = locations->InAt(0).AsRegister<Register>();
+
+ __ Srl(TMP, in, 1);
+ __ LoadConst32(AT, 0x55555555);
+ __ And(TMP, TMP, AT);
+ __ Subu(TMP, in, TMP);
+ __ LoadConst32(AT, 0x33333333);
+ __ And(out, TMP, AT);
+ __ Srl(TMP, TMP, 2);
+ __ And(TMP, TMP, AT);
+ __ Addu(TMP, out, TMP);
+ __ Srl(out, TMP, 4);
+ __ Addu(out, out, TMP);
+ __ LoadConst32(AT, 0x0F0F0F0F);
+ __ And(out, out, AT);
+ __ LoadConst32(TMP, 0x01010101);
+ if (isR6) {
+ __ MulR6(out, out, TMP);
+ } else {
+ __ MulR2(out, out, TMP);
+ }
+ __ Srl(out, out, 24);
+ } else if (type == Primitive::kPrimLong) {
+ Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>();
+ Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>();
+ Register tmp_hi = locations->GetTemp(0).AsRegister<Register>();
+ Register out_hi = locations->GetTemp(1).AsRegister<Register>();
+ Register tmp_lo = TMP;
+ Register out_lo = out;
+
+ __ Srl(tmp_lo, in_lo, 1);
+ __ Srl(tmp_hi, in_hi, 1);
+
+ __ LoadConst32(AT, 0x55555555);
+
+ __ And(tmp_lo, tmp_lo, AT);
+ __ Subu(tmp_lo, in_lo, tmp_lo);
+
+ __ And(tmp_hi, tmp_hi, AT);
+ __ Subu(tmp_hi, in_hi, tmp_hi);
+
+ __ LoadConst32(AT, 0x33333333);
+
+ __ And(out_lo, tmp_lo, AT);
+ __ Srl(tmp_lo, tmp_lo, 2);
+ __ And(tmp_lo, tmp_lo, AT);
+ __ Addu(tmp_lo, out_lo, tmp_lo);
+ __ Srl(out_lo, tmp_lo, 4);
+ __ Addu(out_lo, out_lo, tmp_lo);
+
+ __ And(out_hi, tmp_hi, AT);
+ __ Srl(tmp_hi, tmp_hi, 2);
+ __ And(tmp_hi, tmp_hi, AT);
+ __ Addu(tmp_hi, out_hi, tmp_hi);
+ __ Srl(out_hi, tmp_hi, 4);
+ __ Addu(out_hi, out_hi, tmp_hi);
+
+ __ LoadConst32(AT, 0x0F0F0F0F);
+
+ __ And(out_lo, out_lo, AT);
+ __ And(out_hi, out_hi, AT);
+
+ __ LoadConst32(AT, 0x01010101);
+
+ if (isR6) {
+ __ MulR6(out_lo, out_lo, AT);
+
+ __ MulR6(out_hi, out_hi, AT);
+ } else {
+ __ MulR2(out_lo, out_lo, AT);
+
+ __ MulR2(out_hi, out_hi, AT);
+ }
+
+ __ Srl(out_lo, out_lo, 24);
+ __ Srl(out_hi, out_hi, 24);
+
+ __ Addu(out, out_hi, out_lo);
+ }
+}
+
+// int java.lang.Integer.bitCount(int)
+void IntrinsicLocationsBuilderMIPS::VisitIntegerBitCount(HInvoke* invoke) {
+ CreateIntToIntLocations(arena_, invoke);
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitIntegerBitCount(HInvoke* invoke) {
+ GenBitCount(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler());
+}
+
+// int java.lang.Long.bitCount(int)
+void IntrinsicLocationsBuilderMIPS::VisitLongBitCount(HInvoke* invoke) {
+ LocationSummary* locations = new (arena_) LocationSummary(invoke,
+ LocationSummary::kNoCall,
+ kIntrinsified);
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetOut(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister());
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitLongBitCount(HInvoke* invoke) {
+ GenBitCount(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler());
+}
+
static void MathAbsFP(LocationSummary* locations, bool is64bit, MipsAssembler* assembler) {
FRegister in = locations->InAt(0).AsFpuRegister<FRegister>();
FRegister out = locations->Out().AsFpuRegister<FRegister>();
@@ -1698,88 +1605,234 @@
__ Bind(&end);
}
-// Unimplemented intrinsics.
+static void GenIsInfinite(LocationSummary* locations,
+ const Primitive::Type type,
+ const bool isR6,
+ MipsAssembler* assembler) {
+ FRegister in = locations->InAt(0).AsFpuRegister<FRegister>();
+ Register out = locations->Out().AsRegister<Register>();
-#define UNIMPLEMENTED_INTRINSIC(Name) \
-void IntrinsicLocationsBuilderMIPS::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-} \
-void IntrinsicCodeGeneratorMIPS::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
+ DCHECK(type == Primitive::kPrimFloat || type == Primitive::kPrimDouble);
+
+ if (isR6) {
+ if (type == Primitive::kPrimDouble) {
+ __ ClassD(FTMP, in);
+ } else {
+ __ ClassS(FTMP, in);
+ }
+ __ Mfc1(out, FTMP);
+ __ Andi(out, out, kPositiveInfinity | kNegativeInfinity);
+ __ Sltu(out, ZERO, out);
+ } else {
+ // If one, or more, of the exponent bits is zero, then the number can't be infinite.
+ if (type == Primitive::kPrimDouble) {
+ __ MoveFromFpuHigh(TMP, in);
+ __ LoadConst32(AT, 0x7FF00000);
+ } else {
+ __ Mfc1(TMP, in);
+ __ LoadConst32(AT, 0x7F800000);
+ }
+ __ Xor(TMP, TMP, AT);
+
+ __ Sll(TMP, TMP, 1);
+
+ if (type == Primitive::kPrimDouble) {
+ __ Mfc1(AT, in);
+ __ Or(TMP, TMP, AT);
+ }
+ // If any of the significand bits are one, then the number is not infinite.
+ __ Sltiu(out, TMP, 1);
+ }
}
-UNIMPLEMENTED_INTRINSIC(IntegerBitCount)
-UNIMPLEMENTED_INTRINSIC(LongBitCount)
+// boolean java.lang.Float.isInfinite(float)
+void IntrinsicLocationsBuilderMIPS::VisitFloatIsInfinite(HInvoke* invoke) {
+ CreateFPToIntLocations(arena_, invoke);
+}
-UNIMPLEMENTED_INTRINSIC(MathCeil)
-UNIMPLEMENTED_INTRINSIC(MathFloor)
-UNIMPLEMENTED_INTRINSIC(MathRint)
-UNIMPLEMENTED_INTRINSIC(MathRoundDouble)
-UNIMPLEMENTED_INTRINSIC(MathRoundFloat)
-UNIMPLEMENTED_INTRINSIC(ThreadCurrentThread)
-UNIMPLEMENTED_INTRINSIC(UnsafeGet)
-UNIMPLEMENTED_INTRINSIC(UnsafeGetVolatile)
-UNIMPLEMENTED_INTRINSIC(UnsafeGetLong)
-UNIMPLEMENTED_INTRINSIC(UnsafeGetLongVolatile)
-UNIMPLEMENTED_INTRINSIC(UnsafeGetObject)
-UNIMPLEMENTED_INTRINSIC(UnsafeGetObjectVolatile)
-UNIMPLEMENTED_INTRINSIC(UnsafePut)
-UNIMPLEMENTED_INTRINSIC(UnsafePutOrdered)
-UNIMPLEMENTED_INTRINSIC(UnsafePutVolatile)
-UNIMPLEMENTED_INTRINSIC(UnsafePutObject)
-UNIMPLEMENTED_INTRINSIC(UnsafePutObjectOrdered)
-UNIMPLEMENTED_INTRINSIC(UnsafePutObjectVolatile)
-UNIMPLEMENTED_INTRINSIC(UnsafePutLong)
-UNIMPLEMENTED_INTRINSIC(UnsafePutLongOrdered)
-UNIMPLEMENTED_INTRINSIC(UnsafePutLongVolatile)
-UNIMPLEMENTED_INTRINSIC(UnsafeCASInt)
-UNIMPLEMENTED_INTRINSIC(UnsafeCASLong)
-UNIMPLEMENTED_INTRINSIC(UnsafeCASObject)
-UNIMPLEMENTED_INTRINSIC(StringCompareTo)
-UNIMPLEMENTED_INTRINSIC(StringIndexOf)
-UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
-UNIMPLEMENTED_INTRINSIC(StringNewStringFromBytes)
-UNIMPLEMENTED_INTRINSIC(StringNewStringFromChars)
-UNIMPLEMENTED_INTRINSIC(StringNewStringFromString)
+void IntrinsicCodeGeneratorMIPS::VisitFloatIsInfinite(HInvoke* invoke) {
+ GenIsInfinite(invoke->GetLocations(), Primitive::kPrimFloat, IsR6(), GetAssembler());
+}
-UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
-UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck)
-UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(SystemArrayCopy)
+// boolean java.lang.Double.isInfinite(double)
+void IntrinsicLocationsBuilderMIPS::VisitDoubleIsInfinite(HInvoke* invoke) {
+ CreateFPToIntLocations(arena_, invoke);
+}
-UNIMPLEMENTED_INTRINSIC(MathCos)
-UNIMPLEMENTED_INTRINSIC(MathSin)
-UNIMPLEMENTED_INTRINSIC(MathAcos)
-UNIMPLEMENTED_INTRINSIC(MathAsin)
-UNIMPLEMENTED_INTRINSIC(MathAtan)
-UNIMPLEMENTED_INTRINSIC(MathAtan2)
-UNIMPLEMENTED_INTRINSIC(MathCbrt)
-UNIMPLEMENTED_INTRINSIC(MathCosh)
-UNIMPLEMENTED_INTRINSIC(MathExp)
-UNIMPLEMENTED_INTRINSIC(MathExpm1)
-UNIMPLEMENTED_INTRINSIC(MathHypot)
-UNIMPLEMENTED_INTRINSIC(MathLog)
-UNIMPLEMENTED_INTRINSIC(MathLog10)
-UNIMPLEMENTED_INTRINSIC(MathNextAfter)
-UNIMPLEMENTED_INTRINSIC(MathSinh)
-UNIMPLEMENTED_INTRINSIC(MathTan)
-UNIMPLEMENTED_INTRINSIC(MathTanh)
+void IntrinsicCodeGeneratorMIPS::VisitDoubleIsInfinite(HInvoke* invoke) {
+ GenIsInfinite(invoke->GetLocations(), Primitive::kPrimDouble, IsR6(), GetAssembler());
+}
-UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
-UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
+static void GenHighestOneBit(LocationSummary* locations,
+ const Primitive::Type type,
+ bool isR6,
+ MipsAssembler* assembler) {
+ DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
-UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
+ if (type == Primitive::kPrimLong) {
+ Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>();
+ Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>();
+ Register out_lo = locations->Out().AsRegisterPairLow<Register>();
+ Register out_hi = locations->Out().AsRegisterPairHigh<Register>();
-// Handled as HIR instructions.
-UNIMPLEMENTED_INTRINSIC(FloatFloatToIntBits)
-UNIMPLEMENTED_INTRINSIC(DoubleDoubleToLongBits)
-UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
-UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
-UNIMPLEMENTED_INTRINSIC(IntegerCompare)
-UNIMPLEMENTED_INTRINSIC(LongCompare)
-UNIMPLEMENTED_INTRINSIC(IntegerSignum)
-UNIMPLEMENTED_INTRINSIC(LongSignum)
+ if (isR6) {
+ __ ClzR6(TMP, in_hi);
+ } else {
+ __ ClzR2(TMP, in_hi);
+ }
+ __ LoadConst32(AT, 0x80000000);
+ __ Srlv(out_hi, AT, TMP);
+ __ And(out_hi, out_hi, in_hi);
+ if (isR6) {
+ __ ClzR6(TMP, in_lo);
+ } else {
+ __ ClzR2(TMP, in_lo);
+ }
+ __ Srlv(out_lo, AT, TMP);
+ __ And(out_lo, out_lo, in_lo);
+ if (isR6) {
+ __ Seleqz(out_lo, out_lo, out_hi);
+ } else {
+ __ Movn(out_lo, ZERO, out_hi);
+ }
+ } else {
+ Register in = locations->InAt(0).AsRegister<Register>();
+ Register out = locations->Out().AsRegister<Register>();
+
+ if (isR6) {
+ __ ClzR6(TMP, in);
+ } else {
+ __ ClzR2(TMP, in);
+ }
+ __ LoadConst32(AT, 0x80000000);
+ __ Srlv(AT, AT, TMP); // Srlv shifts in the range of [0;31] bits (lower 5 bits of arg).
+ __ And(out, AT, in); // So this is required for 0 (=shift by 32).
+ }
+}
+
+// int java.lang.Integer.highestOneBit(int)
+void IntrinsicLocationsBuilderMIPS::VisitIntegerHighestOneBit(HInvoke* invoke) {
+ CreateIntToIntLocations(arena_, invoke);
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitIntegerHighestOneBit(HInvoke* invoke) {
+ GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler());
+}
+
+// long java.lang.Long.highestOneBit(long)
+void IntrinsicLocationsBuilderMIPS::VisitLongHighestOneBit(HInvoke* invoke) {
+ CreateIntToIntLocations(arena_, invoke, Location::kOutputOverlap);
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitLongHighestOneBit(HInvoke* invoke) {
+ GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler());
+}
+
+static void GenLowestOneBit(LocationSummary* locations,
+ const Primitive::Type type,
+ bool isR6,
+ MipsAssembler* assembler) {
+ DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
+
+ if (type == Primitive::kPrimLong) {
+ Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>();
+ Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>();
+ Register out_lo = locations->Out().AsRegisterPairLow<Register>();
+ Register out_hi = locations->Out().AsRegisterPairHigh<Register>();
+
+ __ Subu(TMP, ZERO, in_lo);
+ __ And(out_lo, TMP, in_lo);
+ __ Subu(TMP, ZERO, in_hi);
+ __ And(out_hi, TMP, in_hi);
+ if (isR6) {
+ __ Seleqz(out_hi, out_hi, out_lo);
+ } else {
+ __ Movn(out_hi, ZERO, out_lo);
+ }
+ } else {
+ Register in = locations->InAt(0).AsRegister<Register>();
+ Register out = locations->Out().AsRegister<Register>();
+
+ __ Subu(TMP, ZERO, in);
+ __ And(out, TMP, in);
+ }
+}
+
+// int java.lang.Integer.lowestOneBit(int)
+void IntrinsicLocationsBuilderMIPS::VisitIntegerLowestOneBit(HInvoke* invoke) {
+ CreateIntToIntLocations(arena_, invoke);
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitIntegerLowestOneBit(HInvoke* invoke) {
+ GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler());
+}
+
+// long java.lang.Long.lowestOneBit(long)
+void IntrinsicLocationsBuilderMIPS::VisitLongLowestOneBit(HInvoke* invoke) {
+ CreateIntToIntLocations(arena_, invoke);
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitLongLowestOneBit(HInvoke* invoke) {
+ GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler());
+}
+
+// Unimplemented intrinsics.
+
+UNIMPLEMENTED_INTRINSIC(MIPS, MathCeil)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathFloor)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathRint)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathRoundDouble)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathRoundFloat)
+UNIMPLEMENTED_INTRINSIC(MIPS, ThreadCurrentThread)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGet)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetVolatile)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetLong)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetLongVolatile)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetObject)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeGetObjectVolatile)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafePut)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafePutOrdered)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafePutVolatile)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafePutObject)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafePutObjectOrdered)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafePutObjectVolatile)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafePutLong)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafePutLongOrdered)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafePutLongVolatile)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeCASInt)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeCASLong)
+UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeCASObject)
+UNIMPLEMENTED_INTRINSIC(MIPS, StringCompareTo)
+UNIMPLEMENTED_INTRINSIC(MIPS, StringIndexOf)
+UNIMPLEMENTED_INTRINSIC(MIPS, StringIndexOfAfter)
+UNIMPLEMENTED_INTRINSIC(MIPS, StringNewStringFromBytes)
+UNIMPLEMENTED_INTRINSIC(MIPS, StringNewStringFromChars)
+UNIMPLEMENTED_INTRINSIC(MIPS, StringNewStringFromString)
+
+UNIMPLEMENTED_INTRINSIC(MIPS, ReferenceGetReferent)
+UNIMPLEMENTED_INTRINSIC(MIPS, StringGetCharsNoCheck)
+UNIMPLEMENTED_INTRINSIC(MIPS, SystemArrayCopyChar)
+UNIMPLEMENTED_INTRINSIC(MIPS, SystemArrayCopy)
+
+UNIMPLEMENTED_INTRINSIC(MIPS, MathCos)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathSin)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathAcos)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathAsin)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathAtan)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathAtan2)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathCbrt)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathCosh)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathExp)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathExpm1)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathHypot)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathLog)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathLog10)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathNextAfter)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathSinh)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathTan)
+UNIMPLEMENTED_INTRINSIC(MIPS, MathTanh)
+
+UNREACHABLE_INTRINSICS(MIPS)
#undef UNIMPLEMENTED_INTRINSIC
diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc
index ca2652b..45611f0 100644
--- a/compiler/optimizing/intrinsics_mips64.cc
+++ b/compiler/optimizing/intrinsics_mips64.cc
@@ -340,130 +340,6 @@
GenNumberOfTrailingZeroes(invoke->GetLocations(), /* is64bit */ true, GetAssembler());
}
-static void GenRotateRight(HInvoke* invoke,
- Primitive::Type type,
- Mips64Assembler* assembler) {
- DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
-
- LocationSummary* locations = invoke->GetLocations();
- GpuRegister in = locations->InAt(0).AsRegister<GpuRegister>();
- GpuRegister out = locations->Out().AsRegister<GpuRegister>();
-
- if (invoke->InputAt(1)->IsIntConstant()) {
- uint32_t shift = static_cast<uint32_t>(invoke->InputAt(1)->AsIntConstant()->GetValue());
- if (type == Primitive::kPrimInt) {
- shift &= 0x1f;
- __ Rotr(out, in, shift);
- } else {
- shift &= 0x3f;
- if (shift < 32) {
- __ Drotr(out, in, shift);
- } else {
- shift &= 0x1f;
- __ Drotr32(out, in, shift);
- }
- }
- } else {
- GpuRegister shamt = locations->InAt(1).AsRegister<GpuRegister>();
- if (type == Primitive::kPrimInt) {
- __ Rotrv(out, in, shamt);
- } else {
- __ Drotrv(out, in, shamt);
- }
- }
-}
-
-// int java.lang.Integer.rotateRight(int i, int distance)
-void IntrinsicLocationsBuilderMIPS64::VisitIntegerRotateRight(HInvoke* invoke) {
- LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kNoCall,
- kIntrinsified);
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(invoke->InputAt(1)));
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
-}
-
-void IntrinsicCodeGeneratorMIPS64::VisitIntegerRotateRight(HInvoke* invoke) {
- GenRotateRight(invoke, Primitive::kPrimInt, GetAssembler());
-}
-
-// long java.lang.Long.rotateRight(long i, int distance)
-void IntrinsicLocationsBuilderMIPS64::VisitLongRotateRight(HInvoke* invoke) {
- LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kNoCall,
- kIntrinsified);
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(invoke->InputAt(1)));
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
-}
-
-void IntrinsicCodeGeneratorMIPS64::VisitLongRotateRight(HInvoke* invoke) {
- GenRotateRight(invoke, Primitive::kPrimLong, GetAssembler());
-}
-
-static void GenRotateLeft(HInvoke* invoke,
- Primitive::Type type,
- Mips64Assembler* assembler) {
- DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
-
- LocationSummary* locations = invoke->GetLocations();
- GpuRegister in = locations->InAt(0).AsRegister<GpuRegister>();
- GpuRegister out = locations->Out().AsRegister<GpuRegister>();
-
- if (invoke->InputAt(1)->IsIntConstant()) {
- int32_t shift = -static_cast<int32_t>(invoke->InputAt(1)->AsIntConstant()->GetValue());
- if (type == Primitive::kPrimInt) {
- shift &= 0x1f;
- __ Rotr(out, in, shift);
- } else {
- shift &= 0x3f;
- if (shift < 32) {
- __ Drotr(out, in, shift);
- } else {
- shift &= 0x1f;
- __ Drotr32(out, in, shift);
- }
- }
- } else {
- GpuRegister shamt = locations->InAt(1).AsRegister<GpuRegister>();
- if (type == Primitive::kPrimInt) {
- __ Subu(TMP, ZERO, shamt);
- __ Rotrv(out, in, TMP);
- } else {
- __ Dsubu(TMP, ZERO, shamt);
- __ Drotrv(out, in, TMP);
- }
- }
-}
-
-// int java.lang.Integer.rotateLeft(int i, int distance)
-void IntrinsicLocationsBuilderMIPS64::VisitIntegerRotateLeft(HInvoke* invoke) {
- LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kNoCall,
- kIntrinsified);
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(invoke->InputAt(1)));
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
-}
-
-void IntrinsicCodeGeneratorMIPS64::VisitIntegerRotateLeft(HInvoke* invoke) {
- GenRotateLeft(invoke, Primitive::kPrimInt, GetAssembler());
-}
-
-// long java.lang.Long.rotateLeft(long i, int distance)
-void IntrinsicLocationsBuilderMIPS64::VisitLongRotateLeft(HInvoke* invoke) {
- LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kNoCall,
- kIntrinsified);
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(invoke->InputAt(1)));
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
-}
-
-void IntrinsicCodeGeneratorMIPS64::VisitLongRotateLeft(HInvoke* invoke) {
- GenRotateLeft(invoke, Primitive::kPrimLong, GetAssembler());
-}
-
static void GenReverse(LocationSummary* locations,
Primitive::Type type,
Mips64Assembler* assembler) {
@@ -1636,6 +1512,7 @@
TMP,
TR,
QUICK_ENTRYPOINT_OFFSET(kMips64DoublewordSize, pIndexOf).Int32Value());
+ CheckEntrypointTypes<kQuickIndexOf, int32_t, void*, uint32_t, uint32_t>();
__ Jalr(TMP);
__ Nop();
@@ -1685,7 +1562,7 @@
invoke, GetAssembler(), codegen_, GetAllocator(), /* start_at_zero */ false);
}
-// java.lang.String.String(byte[] bytes)
+// java.lang.StringFactory.newStringFromBytes(byte[] data, int high, int offset, int byteCount)
void IntrinsicLocationsBuilderMIPS64::VisitStringNewStringFromBytes(HInvoke* invoke) {
LocationSummary* locations = new (arena_) LocationSummary(invoke,
LocationSummary::kCall,
@@ -1719,7 +1596,7 @@
__ Bind(slow_path->GetExitLabel());
}
-// java.lang.String.String(char[] value)
+// java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)
void IntrinsicLocationsBuilderMIPS64::VisitStringNewStringFromChars(HInvoke* invoke) {
LocationSummary* locations = new (arena_) LocationSummary(invoke,
LocationSummary::kCall,
@@ -1735,6 +1612,12 @@
void IntrinsicCodeGeneratorMIPS64::VisitStringNewStringFromChars(HInvoke* invoke) {
Mips64Assembler* assembler = GetAssembler();
+ // No need to emit code checking whether `locations->InAt(2)` is a null
+ // pointer, as callers of the native method
+ //
+ // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)
+ //
+ // all include a null check on `data` before calling that method.
__ LoadFromOffset(kLoadDoubleword,
TMP,
TR,
@@ -1778,62 +1661,44 @@
__ Bind(slow_path->GetExitLabel());
}
-// Unimplemented intrinsics.
+UNIMPLEMENTED_INTRINSIC(MIPS64, IntegerBitCount)
+UNIMPLEMENTED_INTRINSIC(MIPS64, LongBitCount)
-#define UNIMPLEMENTED_INTRINSIC(Name) \
-void IntrinsicLocationsBuilderMIPS64::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-} \
-void IntrinsicCodeGeneratorMIPS64::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-}
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathRoundDouble)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathRoundFloat)
-UNIMPLEMENTED_INTRINSIC(IntegerBitCount)
-UNIMPLEMENTED_INTRINSIC(LongBitCount)
+UNIMPLEMENTED_INTRINSIC(MIPS64, ReferenceGetReferent)
+UNIMPLEMENTED_INTRINSIC(MIPS64, StringGetCharsNoCheck)
+UNIMPLEMENTED_INTRINSIC(MIPS64, SystemArrayCopyChar)
+UNIMPLEMENTED_INTRINSIC(MIPS64, SystemArrayCopy)
-UNIMPLEMENTED_INTRINSIC(MathRoundDouble)
-UNIMPLEMENTED_INTRINSIC(MathRoundFloat)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathCos)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathSin)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathAcos)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathAsin)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathAtan)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathAtan2)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathCbrt)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathCosh)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathExp)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathExpm1)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathHypot)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathLog)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathLog10)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathNextAfter)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathSinh)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathTan)
+UNIMPLEMENTED_INTRINSIC(MIPS64, MathTanh)
-UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
-UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck)
-UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(SystemArrayCopy)
+UNIMPLEMENTED_INTRINSIC(MIPS64, FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(MIPS64, DoubleIsInfinite)
-UNIMPLEMENTED_INTRINSIC(MathCos)
-UNIMPLEMENTED_INTRINSIC(MathSin)
-UNIMPLEMENTED_INTRINSIC(MathAcos)
-UNIMPLEMENTED_INTRINSIC(MathAsin)
-UNIMPLEMENTED_INTRINSIC(MathAtan)
-UNIMPLEMENTED_INTRINSIC(MathAtan2)
-UNIMPLEMENTED_INTRINSIC(MathCbrt)
-UNIMPLEMENTED_INTRINSIC(MathCosh)
-UNIMPLEMENTED_INTRINSIC(MathExp)
-UNIMPLEMENTED_INTRINSIC(MathExpm1)
-UNIMPLEMENTED_INTRINSIC(MathHypot)
-UNIMPLEMENTED_INTRINSIC(MathLog)
-UNIMPLEMENTED_INTRINSIC(MathLog10)
-UNIMPLEMENTED_INTRINSIC(MathNextAfter)
-UNIMPLEMENTED_INTRINSIC(MathSinh)
-UNIMPLEMENTED_INTRINSIC(MathTan)
-UNIMPLEMENTED_INTRINSIC(MathTanh)
+UNIMPLEMENTED_INTRINSIC(MIPS64, IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(MIPS64, LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(MIPS64, IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(MIPS64, LongLowestOneBit)
-UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
-UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
-
-UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
-
-// Handled as HIR instructions.
-UNIMPLEMENTED_INTRINSIC(FloatFloatToIntBits)
-UNIMPLEMENTED_INTRINSIC(DoubleDoubleToLongBits)
-UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
-UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
-UNIMPLEMENTED_INTRINSIC(IntegerCompare)
-UNIMPLEMENTED_INTRINSIC(LongCompare)
-UNIMPLEMENTED_INTRINSIC(IntegerSignum)
-UNIMPLEMENTED_INTRINSIC(LongSignum)
-
-#undef UNIMPLEMENTED_INTRINSIC
+UNREACHABLE_INTRINSICS(MIPS64)
#undef __
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 0df4553..9a2dc41 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -1564,6 +1564,12 @@
void IntrinsicCodeGeneratorX86::VisitStringNewStringFromChars(HInvoke* invoke) {
X86Assembler* assembler = GetAssembler();
+ // No need to emit code checking whether `locations->InAt(2)` is a null
+ // pointer, as callers of the native method
+ //
+ // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)
+ //
+ // all include a null check on `data` before calling that method.
__ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocStringFromChars)));
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
@@ -2621,41 +2627,17 @@
GenTrailingZeros(GetAssembler(), codegen_, invoke, /* is_long */ true);
}
-// Unimplemented intrinsics.
+UNIMPLEMENTED_INTRINSIC(X86, MathRoundDouble)
+UNIMPLEMENTED_INTRINSIC(X86, ReferenceGetReferent)
+UNIMPLEMENTED_INTRINSIC(X86, SystemArrayCopy)
+UNIMPLEMENTED_INTRINSIC(X86, FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(X86, DoubleIsInfinite)
+UNIMPLEMENTED_INTRINSIC(X86, IntegerHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(X86, LongHighestOneBit)
+UNIMPLEMENTED_INTRINSIC(X86, IntegerLowestOneBit)
+UNIMPLEMENTED_INTRINSIC(X86, LongLowestOneBit)
-#define UNIMPLEMENTED_INTRINSIC(Name) \
-void IntrinsicLocationsBuilderX86::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-} \
-void IntrinsicCodeGeneratorX86::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-}
-
-UNIMPLEMENTED_INTRINSIC(MathRoundDouble)
-UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
-UNIMPLEMENTED_INTRINSIC(SystemArrayCopy)
-
-UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
-UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
-
-UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongHighestOneBit)
-UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit)
-UNIMPLEMENTED_INTRINSIC(LongLowestOneBit)
-
-// Handled as HIR instructions.
-UNIMPLEMENTED_INTRINSIC(FloatFloatToIntBits)
-UNIMPLEMENTED_INTRINSIC(DoubleDoubleToLongBits)
-UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
-UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
-UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
-UNIMPLEMENTED_INTRINSIC(LongRotateRight)
-UNIMPLEMENTED_INTRINSIC(IntegerCompare)
-UNIMPLEMENTED_INTRINSIC(LongCompare)
-UNIMPLEMENTED_INTRINSIC(IntegerSignum)
-UNIMPLEMENTED_INTRINSIC(LongSignum)
-
-#undef UNIMPLEMENTED_INTRINSIC
+UNREACHABLE_INTRINSICS(X86)
#undef __
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 2a9e684..75204b4 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -1659,6 +1659,12 @@
void IntrinsicCodeGeneratorX86_64::VisitStringNewStringFromChars(HInvoke* invoke) {
X86_64Assembler* assembler = GetAssembler();
+ // No need to emit code checking whether `locations->InAt(2)` is a null
+ // pointer, as callers of the native method
+ //
+ // java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)
+ //
+ // all include a null check on `data` before calling that method.
__ gs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pAllocStringFromChars),
/* no_rip */ true));
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
@@ -2705,34 +2711,11 @@
GenTrailingZeros(GetAssembler(), codegen_, invoke, /* is_long */ true);
}
-// Unimplemented intrinsics.
+UNIMPLEMENTED_INTRINSIC(X86_64, ReferenceGetReferent)
+UNIMPLEMENTED_INTRINSIC(X86_64, FloatIsInfinite)
+UNIMPLEMENTED_INTRINSIC(X86_64, DoubleIsInfinite)
-#define UNIMPLEMENTED_INTRINSIC(Name) \
-void IntrinsicLocationsBuilderX86_64::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-} \
-void IntrinsicCodeGeneratorX86_64::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
-}
-
-UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
-
-UNIMPLEMENTED_INTRINSIC(FloatIsInfinite)
-UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite)
-
-// Handled as HIR instructions.
-UNIMPLEMENTED_INTRINSIC(FloatFloatToIntBits)
-UNIMPLEMENTED_INTRINSIC(DoubleDoubleToLongBits)
-UNIMPLEMENTED_INTRINSIC(FloatIsNaN)
-UNIMPLEMENTED_INTRINSIC(DoubleIsNaN)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
-UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
-UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
-UNIMPLEMENTED_INTRINSIC(LongRotateRight)
-UNIMPLEMENTED_INTRINSIC(IntegerCompare)
-UNIMPLEMENTED_INTRINSIC(LongCompare)
-UNIMPLEMENTED_INTRINSIC(IntegerSignum)
-UNIMPLEMENTED_INTRINSIC(LongSignum)
-
-#undef UNIMPLEMENTED_INTRINSIC
+UNREACHABLE_INTRINSICS(X86_64)
#undef __
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 27a5b97..77ded29 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -127,6 +127,9 @@
// Remove the block from the list of blocks, so that further analyses
// never see it.
blocks_[i] = nullptr;
+ if (block->IsExitBlock()) {
+ SetExitBlock(nullptr);
+ }
}
}
}
@@ -1870,13 +1873,49 @@
DCHECK(block->GetPhis().IsEmpty());
if (block->IsExitBlock()) {
- exit_block_ = nullptr;
+ SetExitBlock(nullptr);
}
RemoveElement(reverse_post_order_, block);
blocks_[block->GetBlockId()] = nullptr;
}
+void HGraph::UpdateLoopAndTryInformationOfNewBlock(HBasicBlock* block,
+ HBasicBlock* reference,
+ bool replace_if_back_edge) {
+ if (block->IsLoopHeader()) {
+ // Clear the information of which blocks are contained in that loop. Since the
+ // information is stored as a bit vector based on block ids, we have to update
+ // it, as those block ids were specific to the callee graph and we are now adding
+ // these blocks to the caller graph.
+ block->GetLoopInformation()->ClearAllBlocks();
+ }
+
+ // If not already in a loop, update the loop information.
+ if (!block->IsInLoop()) {
+ block->SetLoopInformation(reference->GetLoopInformation());
+ }
+
+ // If the block is in a loop, update all its outward loops.
+ HLoopInformation* loop_info = block->GetLoopInformation();
+ if (loop_info != nullptr) {
+ for (HLoopInformationOutwardIterator loop_it(*block);
+ !loop_it.Done();
+ loop_it.Advance()) {
+ loop_it.Current()->Add(block);
+ }
+ if (replace_if_back_edge && loop_info->IsBackEdge(*reference)) {
+ loop_info->ReplaceBackEdge(reference, block);
+ }
+ }
+
+ // Copy TryCatchInformation if `reference` is a try block, not if it is a catch block.
+ TryCatchInformation* try_catch_info = reference->IsTryBlock()
+ ? reference->GetTryCatchInformation()
+ : nullptr;
+ block->SetTryCatchInformation(try_catch_info);
+}
+
HInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) {
DCHECK(HasExitBlock()) << "Unimplemented scenario";
// Update the environments in this graph to have the invoke's environment
@@ -1940,34 +1979,6 @@
at->MergeWithInlined(first);
exit_block_->ReplaceWith(to);
- // Update all predecessors of the exit block (now the `to` block)
- // to not `HReturn` but `HGoto` instead.
- bool returns_void = to->GetPredecessors()[0]->GetLastInstruction()->IsReturnVoid();
- if (to->GetPredecessors().size() == 1) {
- HBasicBlock* predecessor = to->GetPredecessors()[0];
- HInstruction* last = predecessor->GetLastInstruction();
- if (!returns_void) {
- return_value = last->InputAt(0);
- }
- predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
- predecessor->RemoveInstruction(last);
- } else {
- if (!returns_void) {
- // There will be multiple returns.
- return_value = new (allocator) HPhi(
- allocator, kNoRegNumber, 0, HPhi::ToPhiType(invoke->GetType()), to->GetDexPc());
- to->AddPhi(return_value->AsPhi());
- }
- for (HBasicBlock* predecessor : to->GetPredecessors()) {
- HInstruction* last = predecessor->GetLastInstruction();
- if (!returns_void) {
- return_value->AsPhi()->AddInput(last->InputAt(0));
- }
- predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
- predecessor->RemoveInstruction(last);
- }
- }
-
// Update the meta information surrounding blocks:
// (1) the graph they are now in,
// (2) the reverse post order of that graph,
@@ -1991,10 +2002,6 @@
size_t index_of_at = IndexOfElement(outer_graph->reverse_post_order_, at);
MakeRoomFor(&outer_graph->reverse_post_order_, blocks_added, index_of_at);
- HLoopInformation* loop_info = at->GetLoopInformation();
- // Copy TryCatchInformation if `at` is a try block, not if it is a catch block.
- TryCatchInformation* try_catch_info = at->IsTryBlock() ? at->GetTryCatchInformation() : nullptr;
-
// Do a reverse post order of the blocks in the callee and do (1), (2), (3)
// and (4) to the blocks that apply.
for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
@@ -2005,23 +2012,7 @@
current->SetGraph(outer_graph);
outer_graph->AddBlock(current);
outer_graph->reverse_post_order_[++index_of_at] = current;
- if (!current->IsInLoop()) {
- current->SetLoopInformation(loop_info);
- } else if (current->IsLoopHeader()) {
- // Clear the information of which blocks are contained in that loop. Since the
- // information is stored as a bit vector based on block ids, we have to update
- // it, as those block ids were specific to the callee graph and we are now adding
- // these blocks to the caller graph.
- current->GetLoopInformation()->ClearAllBlocks();
- }
- if (current->IsInLoop()) {
- for (HLoopInformationOutwardIterator loop_it(*current);
- !loop_it.Done();
- loop_it.Advance()) {
- loop_it.Current()->Add(current);
- }
- }
- current->SetTryCatchInformation(try_catch_info);
+ UpdateLoopAndTryInformationOfNewBlock(current, at, /* replace_if_back_edge */ false);
}
}
@@ -2029,26 +2020,40 @@
to->SetGraph(outer_graph);
outer_graph->AddBlock(to);
outer_graph->reverse_post_order_[++index_of_at] = to;
- if (loop_info != nullptr) {
- if (!to->IsInLoop()) {
- to->SetLoopInformation(loop_info);
+ // Only `to` can become a back edge, as the inlined blocks
+ // are predecessors of `to`.
+ UpdateLoopAndTryInformationOfNewBlock(to, at, /* replace_if_back_edge */ true);
+
+ // Update all predecessors of the exit block (now the `to` block)
+ // to not `HReturn` but `HGoto` instead.
+ bool returns_void = to->GetPredecessors()[0]->GetLastInstruction()->IsReturnVoid();
+ if (to->GetPredecessors().size() == 1) {
+ HBasicBlock* predecessor = to->GetPredecessors()[0];
+ HInstruction* last = predecessor->GetLastInstruction();
+ if (!returns_void) {
+ return_value = last->InputAt(0);
}
- for (HLoopInformationOutwardIterator loop_it(*at); !loop_it.Done(); loop_it.Advance()) {
- loop_it.Current()->Add(to);
+ predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
+ predecessor->RemoveInstruction(last);
+ } else {
+ if (!returns_void) {
+ // There will be multiple returns.
+ return_value = new (allocator) HPhi(
+ allocator, kNoRegNumber, 0, HPhi::ToPhiType(invoke->GetType()), to->GetDexPc());
+ to->AddPhi(return_value->AsPhi());
}
- if (loop_info->IsBackEdge(*at)) {
- // Only `to` can become a back edge, as the inlined blocks
- // are predecessors of `to`.
- loop_info->ReplaceBackEdge(at, to);
+ for (HBasicBlock* predecessor : to->GetPredecessors()) {
+ HInstruction* last = predecessor->GetLastInstruction();
+ if (!returns_void) {
+ DCHECK(last->IsReturn());
+ return_value->AsPhi()->AddInput(last->InputAt(0));
+ }
+ predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
+ predecessor->RemoveInstruction(last);
}
}
- to->SetTryCatchInformation(try_catch_info);
}
- // Update the next instruction id of the outer graph, so that instructions
- // added later get bigger ids than those in the inner graph.
- outer_graph->SetCurrentInstructionId(GetNextInstructionId());
-
// Walk over the entry block and:
// - Move constants from the entry block to the outer_graph's entry block,
// - Replace HParameterValue instructions with their real value.
@@ -2157,32 +2162,17 @@
reverse_post_order_[index_of_header++] = false_block;
reverse_post_order_[index_of_header++] = new_pre_header;
- // Fix loop information.
- HLoopInformation* loop_info = old_pre_header->GetLoopInformation();
- if (loop_info != nullptr) {
- if_block->SetLoopInformation(loop_info);
- true_block->SetLoopInformation(loop_info);
- false_block->SetLoopInformation(loop_info);
- new_pre_header->SetLoopInformation(loop_info);
- // Add blocks to all enveloping loops.
- for (HLoopInformationOutwardIterator loop_it(*old_pre_header);
- !loop_it.Done();
- loop_it.Advance()) {
- loop_it.Current()->Add(if_block);
- loop_it.Current()->Add(true_block);
- loop_it.Current()->Add(false_block);
- loop_it.Current()->Add(new_pre_header);
- }
- }
-
- // Fix try/catch information.
- TryCatchInformation* try_catch_info = old_pre_header->IsTryBlock()
- ? old_pre_header->GetTryCatchInformation()
- : nullptr;
- if_block->SetTryCatchInformation(try_catch_info);
- true_block->SetTryCatchInformation(try_catch_info);
- false_block->SetTryCatchInformation(try_catch_info);
- new_pre_header->SetTryCatchInformation(try_catch_info);
+ // The pre_header can never be a back edge of a loop.
+ DCHECK((old_pre_header->GetLoopInformation() == nullptr) ||
+ !old_pre_header->GetLoopInformation()->IsBackEdge(*old_pre_header));
+ UpdateLoopAndTryInformationOfNewBlock(
+ if_block, old_pre_header, /* replace_if_back_edge */ false);
+ UpdateLoopAndTryInformationOfNewBlock(
+ true_block, old_pre_header, /* replace_if_back_edge */ false);
+ UpdateLoopAndTryInformationOfNewBlock(
+ false_block, old_pre_header, /* replace_if_back_edge */ false);
+ UpdateLoopAndTryInformationOfNewBlock(
+ new_pre_header, old_pre_header, /* replace_if_back_edge */ false);
}
static void CheckAgainstUpperBound(ReferenceTypeInfo rti, ReferenceTypeInfo upper_bound_rti)
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 9eddfc7..b684cc6 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -353,6 +353,13 @@
// and removing the invoke instruction.
HInstruction* InlineInto(HGraph* outer_graph, HInvoke* invoke);
+ // Update the loop and try membership of `block`, which was spawned from `reference`.
+ // In case `reference` is a back edge, `replace_if_back_edge` notifies whether `block`
+ // should be the new back edge.
+ void UpdateLoopAndTryInformationOfNewBlock(HBasicBlock* block,
+ HBasicBlock* reference,
+ bool replace_if_back_edge);
+
// Need to add a couple of blocks to test if the loop body is entered and
// put deoptimization instructions, etc.
void TransformLoopHeaderForBCE(HBasicBlock* header);
@@ -380,6 +387,7 @@
}
void SetCurrentInstructionId(int32_t id) {
+ DCHECK_GE(id, current_instruction_id_);
current_instruction_id_ = id;
}
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 5a9f258..c1b4d24 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -483,7 +483,11 @@
static void AllocateRegisters(HGraph* graph,
CodeGenerator* codegen,
PassObserver* pass_observer) {
- PrepareForRegisterAllocation(graph).Run();
+ {
+ PassScope scope(PrepareForRegisterAllocation::kPrepareForRegisterAllocationPassName,
+ pass_observer);
+ PrepareForRegisterAllocation(graph).Run();
+ }
SsaLivenessAnalysis liveness(graph, codegen);
{
PassScope scope(SsaLivenessAnalysis::kLivenessPassName, pass_observer);
@@ -861,7 +865,7 @@
const uint32_t access_flags = method->GetAccessFlags();
const InvokeType invoke_type = method->GetInvokeType();
- ArenaAllocator arena(Runtime::Current()->GetArenaPool());
+ ArenaAllocator arena(Runtime::Current()->GetJitArenaPool());
CodeVectorAllocator code_allocator(&arena);
std::unique_ptr<CodeGenerator> codegen;
{
diff --git a/compiler/optimizing/prepare_for_register_allocation.h b/compiler/optimizing/prepare_for_register_allocation.h
index c8b8b0dc..c90724c 100644
--- a/compiler/optimizing/prepare_for_register_allocation.h
+++ b/compiler/optimizing/prepare_for_register_allocation.h
@@ -32,6 +32,9 @@
void Run();
+ static constexpr const char* kPrepareForRegisterAllocationPassName =
+ "prepare_for_register_allocation";
+
private:
void VisitNullCheck(HNullCheck* check) OVERRIDE;
void VisitDivZeroCheck(HDivZeroCheck* check) OVERRIDE;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index d9a2f30..f25d748 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -698,6 +698,12 @@
Usage("Can't have both --image and (--app-image-fd or --app-image-file)");
}
+ if (IsBootImage()) {
+ // We need the boot image to always be debuggable.
+ // TODO: Remove this once we better deal with full frame deoptimization.
+ compiler_options_->debuggable_ = true;
+ }
+
if (oat_filenames_.empty() && oat_fd_ == -1) {
Usage("Output must be supplied with either --oat-file or --oat-fd");
}
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index e30b968..c187536 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -361,6 +361,7 @@
const char* method_filter,
bool list_classes,
bool list_methods,
+ bool dump_header_only,
const char* export_dex_location,
uint32_t addr2instr)
: dump_raw_mapping_table_(dump_raw_mapping_table),
@@ -373,6 +374,7 @@
method_filter_(method_filter),
list_classes_(list_classes),
list_methods_(list_methods),
+ dump_header_only_(dump_header_only),
export_dex_location_(export_dex_location),
addr2instr_(addr2instr),
class_loader_(nullptr) {}
@@ -387,6 +389,7 @@
const char* const method_filter_;
const bool list_classes_;
const bool list_methods_;
+ const bool dump_header_only_;
const char* const export_dex_location_;
uint32_t addr2instr_;
Handle<mirror::ClassLoader>* class_loader_;
@@ -514,21 +517,24 @@
os << StringPrintf("0x%08x\n\n", resolved_addr2instr_);
}
- for (size_t i = 0; i < oat_dex_files_.size(); i++) {
- const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
- CHECK(oat_dex_file != nullptr);
+ if (!options_.dump_header_only_) {
+ for (size_t i = 0; i < oat_dex_files_.size(); i++) {
+ const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
+ CHECK(oat_dex_file != nullptr);
- // If file export selected skip file analysis
- if (options_.export_dex_location_) {
- if (!ExportDexFile(os, *oat_dex_file)) {
- success = false;
- }
- } else {
- if (!DumpOatDexFile(os, *oat_dex_file)) {
- success = false;
+ // If file export selected skip file analysis
+ if (options_.export_dex_location_) {
+ if (!ExportDexFile(os, *oat_dex_file)) {
+ success = false;
+ }
+ } else {
+ if (!DumpOatDexFile(os, *oat_dex_file)) {
+ success = false;
+ }
}
}
}
+
os << std::flush;
return success;
}
@@ -2572,6 +2578,8 @@
dump_code_info_stack_maps_ = true;
} else if (option == "--no-disassemble") {
disassemble_code_ = false;
+ } else if (option =="--header-only") {
+ dump_header_only_ = true;
} else if (option.starts_with("--symbolize=")) {
oat_filename_ = option.substr(strlen("--symbolize=")).data();
symbolize_ = true;
@@ -2655,6 +2663,9 @@
" --no-disassemble may be used to disable disassembly.\n"
" Example: --no-disassemble\n"
"\n"
+ " --header-only may be used to print only the oat header.\n"
+ " Example: --header-only\n"
+ "\n"
" --list-classes may be used to list target file classes (can be used with filters).\n"
" Example: --list-classes\n"
" Example: --list-classes --class-filter=com.example.foo\n"
@@ -2697,6 +2708,7 @@
bool symbolize_ = false;
bool list_classes_ = false;
bool list_methods_ = false;
+ bool dump_header_only_ = false;
uint32_t addr2instr_ = 0;
const char* export_dex_location_ = nullptr;
};
@@ -2719,6 +2731,7 @@
args_->method_filter_,
args_->list_classes_,
args_->list_methods_,
+ args_->dump_header_only_,
args_->export_dex_location_,
args_->addr2instr_));
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 947de8a..500fa14 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -292,7 +292,8 @@
# Note that the fault_handler_x86.cc is not a mistake. This file is
# shared between the x86 and x86_64 architectures.
LIBART_SRC_FILES_x86_64 := \
- interpreter/mterp/mterp_stub.cc \
+ interpreter/mterp/mterp.cc \
+ interpreter/mterp/out/mterp_x86_64.S \
arch/x86_64/context_x86_64.cc \
arch/x86_64/entrypoints_init_x86_64.cc \
arch/x86_64/jni_entrypoints_x86_64.S \
@@ -306,7 +307,8 @@
$(LIBART_SRC_FILES_x86_64) \
LIBART_TARGET_SRC_FILES_mips := \
- interpreter/mterp/mterp_stub.cc \
+ interpreter/mterp/mterp.cc \
+ interpreter/mterp/out/mterp_mips.S \
arch/mips/context_mips.cc \
arch/mips/entrypoints_init_mips.cc \
arch/mips/jni_entrypoints_mips.S \
@@ -316,7 +318,8 @@
arch/mips/fault_handler_mips.cc
LIBART_TARGET_SRC_FILES_mips64 := \
- interpreter/mterp/mterp_stub.cc \
+ interpreter/mterp/mterp.cc \
+ interpreter/mterp/out/mterp_mips64.S \
arch/mips64/context_mips64.cc \
arch/mips64/entrypoints_init_mips64.cc \
arch/mips64/jni_entrypoints_mips64.S \
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index ebe89bb..12d6d8f 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -463,12 +463,6 @@
interface_method->VisitRoots(visitor, pointer_size);
}
visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
- if (!IsNative()) {
- ProfilingInfo* profiling_info = GetProfilingInfo(pointer_size);
- if (profiling_info != nullptr) {
- profiling_info->VisitRoots(visitor);
- }
- }
}
}
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index cd38e16..a60f31e 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -411,7 +411,12 @@
DCHECK(method_header->Contains(pc));
return method_header;
} else {
- DCHECK(!code_cache->ContainsPc(reinterpret_cast<const void*>(pc))) << std::hex << pc;
+ DCHECK(!code_cache->ContainsPc(reinterpret_cast<const void*>(pc)))
+ << PrettyMethod(this)
+ << ", pc=" << std::hex << pc
+ << ", entry_point=" << std::hex << reinterpret_cast<uintptr_t>(existing_entry_point)
+ << ", copy=" << std::boolalpha << IsCopied()
+ << ", proxy=" << std::boolalpha << IsProxyMethod();
}
}
diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc
index a4b38ea..44af3f7 100644
--- a/runtime/base/arena_allocator.cc
+++ b/runtime/base/arena_allocator.cc
@@ -183,10 +183,10 @@
free(reinterpret_cast<void*>(memory_));
}
-MemMapArena::MemMapArena(size_t size, bool low_4gb) {
+MemMapArena::MemMapArena(size_t size, bool low_4gb, const char* name) {
std::string error_msg;
map_.reset(MemMap::MapAnonymous(
- "LinearAlloc", nullptr, size, PROT_READ | PROT_WRITE, low_4gb, false, &error_msg));
+ name, nullptr, size, PROT_READ | PROT_WRITE, low_4gb, false, &error_msg));
CHECK(map_.get() != nullptr) << error_msg;
memory_ = map_->Begin();
size_ = map_->Size();
@@ -210,9 +210,12 @@
}
}
-ArenaPool::ArenaPool(bool use_malloc, bool low_4gb)
- : use_malloc_(use_malloc), lock_("Arena pool lock", kArenaPoolLock), free_arenas_(nullptr),
- low_4gb_(low_4gb) {
+ArenaPool::ArenaPool(bool use_malloc, bool low_4gb, const char* name)
+ : use_malloc_(use_malloc),
+ lock_("Arena pool lock", kArenaPoolLock),
+ free_arenas_(nullptr),
+ low_4gb_(low_4gb),
+ name_(name) {
if (low_4gb) {
CHECK(!use_malloc) << "low4gb must use map implementation";
}
@@ -250,7 +253,7 @@
}
if (ret == nullptr) {
ret = use_malloc_ ? static_cast<Arena*>(new MallocArena(size)) :
- new MemMapArena(size, low_4gb_);
+ new MemMapArena(size, low_4gb_, name_);
}
ret->Reset();
return ret;
diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h
index 8a96571..728f897 100644
--- a/runtime/base/arena_allocator.h
+++ b/runtime/base/arena_allocator.h
@@ -261,7 +261,7 @@
class MemMapArena FINAL : public Arena {
public:
- MemMapArena(size_t size, bool low_4gb);
+ MemMapArena(size_t size, bool low_4gb, const char* name);
virtual ~MemMapArena();
void Release() OVERRIDE;
@@ -271,7 +271,9 @@
class ArenaPool {
public:
- explicit ArenaPool(bool use_malloc = true, bool low_4gb = false);
+ ArenaPool(bool use_malloc = true,
+ bool low_4gb = false,
+ const char* name = "LinearAlloc");
~ArenaPool();
Arena* AllocArena(size_t size) REQUIRES(!lock_);
void FreeArenaChain(Arena* first) REQUIRES(!lock_);
@@ -287,6 +289,7 @@
mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
Arena* free_arenas_ GUARDED_BY(lock_);
const bool low_4gb_;
+ const char* name_;
DISALLOW_COPY_AND_ASSIGN(ArenaPool);
};
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b5e6532..5f26b5d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2855,8 +2855,9 @@
WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
LinearAlloc* allocator = class_loader->GetAllocator();
if (allocator == nullptr) {
- allocator = Runtime::Current()->CreateLinearAlloc();
- class_loader->SetAllocator(allocator);
+ RegisterClassLoader(class_loader);
+ allocator = class_loader->GetAllocator();
+ CHECK(allocator != nullptr);
}
return allocator;
}
@@ -4817,24 +4818,31 @@
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(new_class);
}
+void ClassLinker::RegisterClassLoader(mirror::ClassLoader* class_loader) {
+ CHECK(class_loader->GetAllocator() == nullptr);
+ CHECK(class_loader->GetClassTable() == nullptr);
+ Thread* const self = Thread::Current();
+ ClassLoaderData data;
+ data.weak_root = self->GetJniEnv()->vm->AddWeakGlobalRef(self, class_loader);
+ // Create and set the class table.
+ data.class_table = new ClassTable;
+ class_loader->SetClassTable(data.class_table);
+ // Create and set the linear allocator.
+ data.allocator = Runtime::Current()->CreateLinearAlloc();
+ class_loader->SetAllocator(data.allocator);
+ // Add to the list so that we know to free the data later.
+ class_loaders_.push_back(data);
+}
+
ClassTable* ClassLinker::InsertClassTableForClassLoader(mirror::ClassLoader* class_loader) {
if (class_loader == nullptr) {
return &boot_class_table_;
}
ClassTable* class_table = class_loader->GetClassTable();
if (class_table == nullptr) {
- class_table = new ClassTable;
- Thread* const self = Thread::Current();
- ClassLoaderData data;
- data.weak_root = self->GetJniEnv()->vm->AddWeakGlobalRef(self, class_loader);
- data.class_table = class_table;
- // Don't already have a class table, add it to the class loader.
- CHECK(class_loader->GetClassTable() == nullptr);
- class_loader->SetClassTable(data.class_table);
- // Should have been set when we registered the dex file.
- data.allocator = class_loader->GetAllocator();
- CHECK(data.allocator != nullptr);
- class_loaders_.push_back(data);
+ RegisterClassLoader(class_loader);
+ class_table = class_loader->GetClassTable();
+ DCHECK(class_table != nullptr);
}
return class_table;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 729617d..0a75b27 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -576,12 +576,12 @@
// Unlike GetOrCreateAllocatorForClassLoader, GetAllocatorForClassLoader asserts that the
// allocator for this class loader is already created.
- static LinearAlloc* GetAllocatorForClassLoader(mirror::ClassLoader* class_loader)
+ LinearAlloc* GetAllocatorForClassLoader(mirror::ClassLoader* class_loader)
SHARED_REQUIRES(Locks::mutator_lock_);
// Return the linear alloc for a class loader if it is already allocated, otherwise allocate and
// set it. TODO: Consider using a lock other than classlinker_classes_lock_.
- static LinearAlloc* GetOrCreateAllocatorForClassLoader(mirror::ClassLoader* class_loader)
+ LinearAlloc* GetOrCreateAllocatorForClassLoader(mirror::ClassLoader* class_loader)
REQUIRES(!Locks::classlinker_classes_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
@@ -980,9 +980,16 @@
mirror::Class* LookupClassFromBootImage(const char* descriptor)
SHARED_REQUIRES(Locks::mutator_lock_);
+ // Register a class loader and create its class table and allocator. Should not be called if
+ // these are already created.
+ void RegisterClassLoader(mirror::ClassLoader* class_loader)
+ SHARED_REQUIRES(Locks::mutator_lock_)
+ REQUIRES(Locks::classlinker_classes_lock_);
+
// Returns null if not found.
ClassTable* ClassTableForClassLoader(mirror::ClassLoader* class_loader)
SHARED_REQUIRES(Locks::mutator_lock_, Locks::classlinker_classes_lock_);
+
// Insert a new class table if not found.
ClassTable* InsertClassTableForClassLoader(mirror::ClassLoader* class_loader)
SHARED_REQUIRES(Locks::mutator_lock_)
diff --git a/runtime/entrypoints/quick/quick_default_externs.h b/runtime/entrypoints/quick/quick_default_externs.h
index fbf028d..4e01d80 100644
--- a/runtime/entrypoints/quick/quick_default_externs.h
+++ b/runtime/entrypoints/quick/quick_default_externs.h
@@ -93,7 +93,7 @@
extern "C" uint64_t art_quick_ushr_long(uint64_t, uint32_t);
// Intrinsic entrypoints.
-extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
+extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t);
extern "C" int32_t art_quick_string_compareto(void*, void*);
extern "C" void* art_quick_memcpy(void*, const void*, size_t);
diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h
index faa4747..79d1c13 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_list.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_list.h
@@ -119,7 +119,7 @@
V(ShrLong, uint64_t, uint64_t, uint32_t) \
V(UshrLong, uint64_t, uint64_t, uint32_t) \
\
- V(IndexOf, int32_t, void*, uint32_t, uint32_t, uint32_t) \
+ V(IndexOf, int32_t, void*, uint32_t, uint32_t) \
V(StringCompareTo, int32_t, void*, void*) \
V(Memcpy, void*, void*, const void*, size_t) \
\
diff --git a/runtime/gc/allocation_record.cc b/runtime/gc/allocation_record.cc
index 4de5388..4672483 100644
--- a/runtime/gc/allocation_record.cc
+++ b/runtime/gc/allocation_record.cc
@@ -245,6 +245,9 @@
heap->SetAllocTrackingEnabled(true);
}
} else {
+ // Delete outside of the critical section to avoid possible lock violations like the runtime
+ // shutdown lock.
+ std::unique_ptr<AllocRecordObjectMap> map;
{
MutexLock mu(self, *Locks::alloc_tracker_lock_);
if (!heap->IsAllocTrackingEnabled()) {
@@ -252,7 +255,7 @@
}
heap->SetAllocTrackingEnabled(false);
LOG(INFO) << "Disabling alloc tracker";
- heap->SetAllocationRecords(nullptr);
+ map = heap->ReleaseAllocationRecords();
}
// If an allocation comes in before we uninstrument, we will safely drop it on the floor.
Runtime::Current()->GetInstrumentation()->UninstrumentQuickAllocEntryPoints();
diff --git a/runtime/gc/collector/immune_spaces.cc b/runtime/gc/collector/immune_spaces.cc
index 26da4ca..1e5f283 100644
--- a/runtime/gc/collector/immune_spaces.cc
+++ b/runtime/gc/collector/immune_spaces.cc
@@ -16,6 +16,9 @@
#include "immune_spaces.h"
+#include <vector>
+#include <tuple>
+
#include "gc/space/space-inl.h"
#include "mirror/object.h"
#include "oat_file.h"
@@ -32,11 +35,12 @@
void ImmuneSpaces::CreateLargestImmuneRegion() {
uintptr_t best_begin = 0u;
uintptr_t best_end = 0u;
+ uintptr_t best_heap_size = 0u;
uintptr_t cur_begin = 0u;
uintptr_t cur_end = 0u;
- // TODO: If the last space is an image space, we may include its oat file in the immune region.
- // This could potentially hide heap corruption bugs if there is invalid pointers that point into
- // the boot oat code
+ uintptr_t cur_heap_size = 0u;
+ using Interval = std::tuple</*start*/uintptr_t, /*end*/uintptr_t, /*is_heap*/bool>;
+ std::vector<Interval> intervals;
for (space::ContinuousSpace* space : GetSpaces()) {
uintptr_t space_begin = reinterpret_cast<uintptr_t>(space->Begin());
uintptr_t space_end = reinterpret_cast<uintptr_t>(space->Limit());
@@ -50,29 +54,47 @@
// creation, the actual oat file could be somewhere else.
const OatFile* const image_oat_file = image_space->GetOatFile();
if (image_oat_file != nullptr) {
- uintptr_t oat_begin = reinterpret_cast<uintptr_t>(image_oat_file->Begin());
- uintptr_t oat_end = reinterpret_cast<uintptr_t>(image_oat_file->End());
- if (space_end == oat_begin) {
- DCHECK_GE(oat_end, oat_begin);
- space_end = oat_end;
- }
+ intervals.push_back(Interval(reinterpret_cast<uintptr_t>(image_oat_file->Begin()),
+ reinterpret_cast<uintptr_t>(image_oat_file->End()),
+ /*image*/false));
}
}
- if (cur_begin == 0u) {
- cur_begin = space_begin;
- cur_end = space_end;
- } else if (cur_end == space_begin) {
- // Extend current region.
- cur_end = space_end;
- } else {
- // Reset.
- cur_begin = 0;
- cur_end = 0;
+ intervals.push_back(Interval(space_begin, space_end, /*is_heap*/true));
+ }
+ std::sort(intervals.begin(), intervals.end());
+ // Intervals are already sorted by begin, if a new interval begins at the end of the current
+ // region then we append, otherwise we restart the current interval. To prevent starting an
+ // interval on an oat file, ignore oat files that are not extending an existing interval.
+ // If the total number of image bytes in the current interval is larger than the current best
+ // one, then we set the best one to be the current one.
+ for (const Interval& interval : intervals) {
+ const uintptr_t begin = std::get<0>(interval);
+ const uintptr_t end = std::get<1>(interval);
+ const bool is_heap = std::get<2>(interval);
+ VLOG(collector) << "Interval " << reinterpret_cast<const void*>(begin) << "-"
+ << reinterpret_cast<const void*>(end) << " is_heap=" << is_heap;
+ DCHECK_GE(end, begin);
+ DCHECK_GE(begin, cur_end);
+ // New interval is not at the end of the current one, start a new interval if we are a heap
+ // interval. Otherwise continue since we never start a new region with non image intervals.
+ if (begin != cur_end) {
+ if (!is_heap) {
+ continue;
+ }
+ // Not extending, reset the region.
+ cur_begin = begin;
+ cur_heap_size = 0;
}
- if (cur_end - cur_begin > best_end - best_begin) {
- // Improvement, update the best range.
- best_begin = cur_begin;
- best_end = cur_end;
+ cur_end = end;
+ if (is_heap) {
+ // Only update if the total number of image bytes is greater than the current best one.
+ // We don't want to count the oat file bytes since these contain no java objects.
+ cur_heap_size += end - begin;
+ if (cur_heap_size > best_heap_size) {
+ best_begin = cur_begin;
+ best_end = cur_end;
+ best_heap_size = cur_heap_size;
+ }
}
}
largest_immune_region_.SetBegin(reinterpret_cast<mirror::Object*>(best_begin));
diff --git a/runtime/gc/collector/immune_spaces_test.cc b/runtime/gc/collector/immune_spaces_test.cc
index 56838f5..cf93ec6 100644
--- a/runtime/gc/collector/immune_spaces_test.cc
+++ b/runtime/gc/collector/immune_spaces_test.cc
@@ -28,7 +28,136 @@
namespace gc {
namespace collector {
-class ImmuneSpacesTest : public CommonRuntimeTest {};
+class DummyOatFile : public OatFile {
+ public:
+ DummyOatFile(uint8_t* begin, uint8_t* end) : OatFile("Location", /*is_executable*/ false) {
+ begin_ = begin;
+ end_ = end;
+ }
+};
+
+class DummyImageSpace : public space::ImageSpace {
+ public:
+ DummyImageSpace(MemMap* map,
+ accounting::ContinuousSpaceBitmap* live_bitmap,
+ std::unique_ptr<DummyOatFile>&& oat_file,
+ std::unique_ptr<MemMap>&& oat_map)
+ : ImageSpace("DummyImageSpace",
+ /*image_location*/"",
+ map,
+ live_bitmap,
+ map->End()),
+ oat_map_(std::move(oat_map)) {
+ oat_file_ = std::move(oat_file);
+ oat_file_non_owned_ = oat_file_.get();
+ }
+
+ private:
+ std::unique_ptr<MemMap> oat_map_;
+};
+
+class ImmuneSpacesTest : public CommonRuntimeTest {
+ static constexpr size_t kMaxBitmaps = 10;
+
+ public:
+ ImmuneSpacesTest() {}
+
+ void ReserveBitmaps() {
+ // Create a bunch of dummy bitmaps since these are required to create image spaces. The bitmaps
+ // do not need to cover the image spaces though.
+ for (size_t i = 0; i < kMaxBitmaps; ++i) {
+ std::unique_ptr<accounting::ContinuousSpaceBitmap> bitmap(
+ accounting::ContinuousSpaceBitmap::Create("bitmap",
+ reinterpret_cast<uint8_t*>(kPageSize),
+ kPageSize));
+ CHECK(bitmap != nullptr);
+ live_bitmaps_.push_back(std::move(bitmap));
+ }
+ }
+
+ // Create an image space, the oat file is optional.
+ DummyImageSpace* CreateImageSpace(uint8_t* image_begin,
+ size_t image_size,
+ uint8_t* oat_begin,
+ size_t oat_size) {
+ std::string error_str;
+ std::unique_ptr<MemMap> map(MemMap::MapAnonymous("DummyImageSpace",
+ image_begin,
+ image_size,
+ PROT_READ | PROT_WRITE,
+ /*low_4gb*/true,
+ /*reuse*/false,
+ &error_str));
+ if (map == nullptr) {
+ LOG(ERROR) << error_str;
+ return nullptr;
+ }
+ CHECK(!live_bitmaps_.empty());
+ std::unique_ptr<accounting::ContinuousSpaceBitmap> live_bitmap(std::move(live_bitmaps_.back()));
+ live_bitmaps_.pop_back();
+ std::unique_ptr<MemMap> oat_map(MemMap::MapAnonymous("OatMap",
+ oat_begin,
+ oat_size,
+ PROT_READ | PROT_WRITE,
+ /*low_4gb*/true,
+ /*reuse*/false,
+ &error_str));
+ if (oat_map == nullptr) {
+ LOG(ERROR) << error_str;
+ return nullptr;
+ }
+ std::unique_ptr<DummyOatFile> oat_file(new DummyOatFile(oat_map->Begin(), oat_map->End()));
+ // Create image header.
+ ImageSection sections[ImageHeader::kSectionCount];
+ new (map->Begin()) ImageHeader(
+ /*image_begin*/PointerToLowMemUInt32(map->Begin()),
+ /*image_size*/map->Size(),
+ sections,
+ /*image_roots*/PointerToLowMemUInt32(map->Begin()) + 1,
+ /*oat_checksum*/0u,
+ // The oat file data in the header is always right after the image space.
+ /*oat_file_begin*/PointerToLowMemUInt32(oat_begin),
+ /*oat_data_begin*/PointerToLowMemUInt32(oat_begin),
+ /*oat_data_end*/PointerToLowMemUInt32(oat_begin + oat_size),
+ /*oat_file_end*/PointerToLowMemUInt32(oat_begin + oat_size),
+ /*boot_image_begin*/0u,
+ /*boot_image_size*/0u,
+ /*boot_oat_begin*/0u,
+ /*boot_oat_size*/0u,
+ /*pointer_size*/sizeof(void*),
+ /*compile_pic*/false,
+ /*is_pic*/false,
+ ImageHeader::kStorageModeUncompressed,
+ /*storage_size*/0u);
+ return new DummyImageSpace(map.release(),
+ live_bitmap.release(),
+ std::move(oat_file),
+ std::move(oat_map));
+ }
+
+ // Does not reserve the memory, the caller needs to be sure no other threads will map at the
+ // returned address.
+ static uint8_t* GetContinuousMemoryRegion(size_t size) {
+ std::string error_str;
+ std::unique_ptr<MemMap> map(MemMap::MapAnonymous("reserve",
+ nullptr,
+ size,
+ PROT_READ | PROT_WRITE,
+ /*low_4gb*/true,
+ /*reuse*/false,
+ &error_str));
+ if (map == nullptr) {
+ LOG(ERROR) << "Failed to allocate memory region " << error_str;
+ return nullptr;
+ }
+ return map->Begin();
+ }
+
+ private:
+ // Bitmap pool for pre-allocated dummy bitmaps. We need to pre-allocate them since we don't want
+ // them to randomly get placed somewhere where we want an image space.
+ std::vector<std::unique_ptr<accounting::ContinuousSpaceBitmap>> live_bitmaps_;
+};
class DummySpace : public space::ContinuousSpace {
public:
@@ -72,94 +201,41 @@
EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().End()), b.Limit());
}
-class DummyOatFile : public OatFile {
- public:
- DummyOatFile(uint8_t* begin, uint8_t* end) : OatFile("Location", /*is_executable*/ false) {
- begin_ = begin;
- end_ = end;
- }
-};
-
-class DummyImageSpace : public space::ImageSpace {
- public:
- DummyImageSpace(MemMap* map,
- accounting::ContinuousSpaceBitmap* live_bitmap,
- std::unique_ptr<DummyOatFile>&& oat_file)
- : ImageSpace("DummyImageSpace",
- /*image_location*/"",
- map,
- live_bitmap,
- map->End()) {
- oat_file_ = std::move(oat_file);
- oat_file_non_owned_ = oat_file_.get();
- }
-
- // Size is the size of the image space, oat offset is where the oat file is located
- // after the end of image space. oat_size is the size of the oat file.
- static DummyImageSpace* Create(size_t size, size_t oat_offset, size_t oat_size) {
- std::string error_str;
- std::unique_ptr<MemMap> map(MemMap::MapAnonymous("DummyImageSpace",
- nullptr,
- size,
- PROT_READ | PROT_WRITE,
- /*low_4gb*/true,
- /*reuse*/false,
- &error_str));
- if (map == nullptr) {
- LOG(ERROR) << error_str;
- return nullptr;
- }
- std::unique_ptr<accounting::ContinuousSpaceBitmap> live_bitmap(
- accounting::ContinuousSpaceBitmap::Create("bitmap", map->Begin(), map->Size()));
- if (live_bitmap == nullptr) {
- return nullptr;
- }
- // The actual mapped oat file may not be directly after the image for the app image case.
- std::unique_ptr<DummyOatFile> oat_file(new DummyOatFile(map->End() + oat_offset,
- map->End() + oat_offset + oat_size));
- // Create image header.
- ImageSection sections[ImageHeader::kSectionCount];
- new (map->Begin()) ImageHeader(
- /*image_begin*/PointerToLowMemUInt32(map->Begin()),
- /*image_size*/map->Size(),
- sections,
- /*image_roots*/PointerToLowMemUInt32(map->Begin()) + 1,
- /*oat_checksum*/0u,
- // The oat file data in the header is always right after the image space.
- /*oat_file_begin*/PointerToLowMemUInt32(map->End()),
- /*oat_data_begin*/PointerToLowMemUInt32(map->End()),
- /*oat_data_end*/PointerToLowMemUInt32(map->End() + oat_size),
- /*oat_file_end*/PointerToLowMemUInt32(map->End() + oat_size),
- /*boot_image_begin*/0u,
- /*boot_image_size*/0u,
- /*boot_oat_begin*/0u,
- /*boot_oat_size*/0u,
- /*pointer_size*/sizeof(void*),
- /*compile_pic*/false,
- /*is_pic*/false,
- ImageHeader::kStorageModeUncompressed,
- /*storage_size*/0u);
- return new DummyImageSpace(map.release(), live_bitmap.release(), std::move(oat_file));
- }
-};
-
+// Tests [image][oat][space] producing a single large immune region.
TEST_F(ImmuneSpacesTest, AppendAfterImage) {
+ ReserveBitmaps();
ImmuneSpaces spaces;
- constexpr size_t image_size = 123 * kPageSize;
- constexpr size_t image_oat_size = 321 * kPageSize;
- std::unique_ptr<DummyImageSpace> image_space(DummyImageSpace::Create(image_size,
- 0,
- image_oat_size));
+ constexpr size_t kImageSize = 123 * kPageSize;
+ constexpr size_t kImageOatSize = 321 * kPageSize;
+ constexpr size_t kOtherSpaceSize= 100 * kPageSize;
+
+ uint8_t* memory = GetContinuousMemoryRegion(kImageSize + kImageOatSize + kOtherSpaceSize);
+
+ std::unique_ptr<DummyImageSpace> image_space(CreateImageSpace(memory,
+ kImageSize,
+ memory + kImageSize,
+ kImageOatSize));
ASSERT_TRUE(image_space != nullptr);
const ImageHeader& image_header = image_space->GetImageHeader();
- EXPECT_EQ(image_header.GetImageSize(), image_size);
+ DummySpace space(image_header.GetOatFileEnd(), image_header.GetOatFileEnd() + kOtherSpaceSize);
+
+ EXPECT_EQ(image_header.GetImageSize(), kImageSize);
EXPECT_EQ(static_cast<size_t>(image_header.GetOatFileEnd() - image_header.GetOatFileBegin()),
- image_oat_size);
- DummySpace space(image_header.GetOatFileEnd(), image_header.GetOatFileEnd() + 813 * kPageSize);
- EXPECT_NE(image_space->Limit(), space.Begin());
+ kImageOatSize);
+ EXPECT_EQ(image_space->GetOatFile()->Size(), kImageOatSize);
+ // Check that we do not include the oat if there is no space after.
{
WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
spaces.AddSpace(image_space.get());
+ }
+ EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().Begin()),
+ image_space->Begin());
+ EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().End()),
+ image_space->Limit());
+ // Add another space and ensure it gets appended.
+ EXPECT_NE(image_space->Limit(), space.Begin());
+ {
+ WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
spaces.AddSpace(&space);
}
EXPECT_TRUE(spaces.ContainsSpace(image_space.get()));
@@ -170,18 +246,122 @@
EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().Begin()),
image_space->Begin());
EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().End()), space.Limit());
- // Check that appending with a gap between the map does not include the oat file.
- image_space.reset(DummyImageSpace::Create(image_size, kPageSize, image_oat_size));
- spaces.Reset();
+}
+
+// Test [image1][image2][image1 oat][image2 oat][image3] producing a single large immune region.
+TEST_F(ImmuneSpacesTest, MultiImage) {
+ ReserveBitmaps();
+ // Image 2 needs to be smaller or else it may be chosen for immune region.
+ constexpr size_t kImage1Size = kPageSize * 17;
+ constexpr size_t kImage2Size = kPageSize * 13;
+ constexpr size_t kImage3Size = kPageSize * 3;
+ constexpr size_t kImage1OatSize = kPageSize * 5;
+ constexpr size_t kImage2OatSize = kPageSize * 8;
+ constexpr size_t kImage3OatSize = kPageSize;
+ constexpr size_t kImageBytes = kImage1Size + kImage2Size + kImage3Size;
+ constexpr size_t kMemorySize = kImageBytes + kImage1OatSize + kImage2OatSize + kImage3OatSize;
+ uint8_t* memory = GetContinuousMemoryRegion(kMemorySize);
+ uint8_t* space1_begin = memory;
+ memory += kImage1Size;
+ uint8_t* space2_begin = memory;
+ memory += kImage2Size;
+ uint8_t* space1_oat_begin = memory;
+ memory += kImage1OatSize;
+ uint8_t* space2_oat_begin = memory;
+ memory += kImage2OatSize;
+ uint8_t* space3_begin = memory;
+
+ std::unique_ptr<DummyImageSpace> space1(CreateImageSpace(space1_begin,
+ kImage1Size,
+ space1_oat_begin,
+ kImage1OatSize));
+ ASSERT_TRUE(space1 != nullptr);
+
+
+ std::unique_ptr<DummyImageSpace> space2(CreateImageSpace(space2_begin,
+ kImage2Size,
+ space2_oat_begin,
+ kImage2OatSize));
+ ASSERT_TRUE(space2 != nullptr);
+
+ // Finally put a 3rd image space.
+ std::unique_ptr<DummyImageSpace> space3(CreateImageSpace(space3_begin,
+ kImage3Size,
+ space3_begin + kImage3Size,
+ kImage3OatSize));
+ ASSERT_TRUE(space3 != nullptr);
+
+ // Check that we do not include the oat if there is no space after.
+ ImmuneSpaces spaces;
{
WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
- spaces.AddSpace(image_space.get());
+ LOG(INFO) << "Adding space1 " << reinterpret_cast<const void*>(space1->Begin());
+ spaces.AddSpace(space1.get());
+ LOG(INFO) << "Adding space2 " << reinterpret_cast<const void*>(space2->Begin());
+ spaces.AddSpace(space2.get());
+ }
+ // There are no more heap bytes, the immune region should only be the first 2 image spaces and
+ // should exclude the image oat files.
+ EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().Begin()),
+ space1->Begin());
+ EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().End()),
+ space2->Limit());
+
+ // Add another space after the oat files, now it should contain the entire memory region.
+ {
+ WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
+ LOG(INFO) << "Adding space3 " << reinterpret_cast<const void*>(space3->Begin());
+ spaces.AddSpace(space3.get());
}
EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().Begin()),
- image_space->Begin());
- // Size should be equal, we should not add the oat file since it is not adjacent to the image
- // space.
- EXPECT_EQ(spaces.GetLargestImmuneRegion().Size(), image_size);
+ space1->Begin());
+ EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().End()),
+ space3->Limit());
+
+ // Add a smaller non-adjacent space and ensure it does not become part of the immune region.
+ // Image size is kImageBytes - kPageSize
+ // Oat size is kPageSize.
+ // Guard pages to ensure it is not adjacent to an existing immune region.
+ // Layout: [guard page][image][oat][guard page]
+ constexpr size_t kGuardSize = kPageSize;
+ constexpr size_t kImage4Size = kImageBytes - kPageSize;
+ constexpr size_t kImage4OatSize = kPageSize;
+ uint8_t* memory2 = GetContinuousMemoryRegion(kImage4Size + kImage4OatSize + kGuardSize * 2);
+ std::unique_ptr<DummyImageSpace> space4(CreateImageSpace(memory2 + kGuardSize,
+ kImage4Size,
+ memory2 + kGuardSize + kImage4Size,
+ kImage4OatSize));
+ ASSERT_TRUE(space4 != nullptr);
+ {
+ WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
+ LOG(INFO) << "Adding space4 " << reinterpret_cast<const void*>(space4->Begin());
+ spaces.AddSpace(space4.get());
+ }
+ EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().Begin()),
+ space1->Begin());
+ EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().End()),
+ space3->Limit());
+
+ // Add a larger non-adjacent space and ensure it becomes the new largest immune region.
+ // Image size is kImageBytes + kPageSize
+ // Oat size is kPageSize.
+ // Guard pages to ensure it is not adjacent to an existing immune region.
+ // Layout: [guard page][image][oat][guard page]
+ constexpr size_t kImage5Size = kImageBytes + kPageSize;
+ constexpr size_t kImage5OatSize = kPageSize;
+ uint8_t* memory3 = GetContinuousMemoryRegion(kImage5Size + kImage5OatSize + kGuardSize * 2);
+ std::unique_ptr<DummyImageSpace> space5(CreateImageSpace(memory3 + kGuardSize,
+ kImage5Size,
+ memory3 + kGuardSize + kImage5Size,
+ kImage5OatSize));
+ ASSERT_TRUE(space5 != nullptr);
+ {
+ WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
+ LOG(INFO) << "Adding space5 " << reinterpret_cast<const void*>(space5->Begin());
+ spaces.AddSpace(space5.get());
+ }
+ EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().Begin()), space5->Begin());
+ EXPECT_EQ(reinterpret_cast<uint8_t*>(spaces.GetLargestImmuneRegion().End()), space5->Limit());
}
} // namespace collector
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index f437830..d7023d8 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -109,16 +109,25 @@
obj = TryToAllocate<kInstrumented, false>(self, allocator, byte_count, &bytes_allocated,
&usable_size, &bytes_tl_bulk_allocated);
if (UNLIKELY(obj == nullptr)) {
- bool is_current_allocator = allocator == GetCurrentAllocator();
- obj = AllocateInternalWithGc(self, allocator, byte_count, &bytes_allocated, &usable_size,
+ // AllocateInternalWithGc can cause thread suspension, if someone instruments the entrypoints
+ // or changes the allocator in a suspend point here, we need to retry the allocation.
+ obj = AllocateInternalWithGc(self,
+ allocator,
+ kInstrumented,
+ byte_count,
+ &bytes_allocated,
+ &usable_size,
&bytes_tl_bulk_allocated, &klass);
if (obj == nullptr) {
- bool after_is_current_allocator = allocator == GetCurrentAllocator();
- // If there is a pending exception, fail the allocation right away since the next one
- // could cause OOM and abort the runtime.
- if (!self->IsExceptionPending() && is_current_allocator && !after_is_current_allocator) {
- // If the allocator changed, we need to restart the allocation.
- return AllocObject<kInstrumented>(self, klass, byte_count, pre_fence_visitor);
+ // The only way that we can get a null return if there is no pending exception is if the
+ // allocator or instrumentation changed.
+ if (!self->IsExceptionPending()) {
+ // AllocObject will pick up the new allocator type, and instrumented as true is the safe
+ // default.
+ return AllocObject</*kInstrumented*/true>(self,
+ klass,
+ byte_count,
+ pre_fence_visitor);
}
return nullptr;
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 4bee462..bebff0f 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1650,8 +1650,15 @@
return nullptr;
}
+static inline bool EntrypointsInstrumented() SHARED_REQUIRES(Locks::mutator_lock_) {
+ instrumentation::Instrumentation* const instrumentation =
+ Runtime::Current()->GetInstrumentation();
+ return instrumentation != nullptr && instrumentation->AllocEntrypointsInstrumented();
+}
+
mirror::Object* Heap::AllocateInternalWithGc(Thread* self,
AllocatorType allocator,
+ bool instrumented,
size_t alloc_size,
size_t* bytes_allocated,
size_t* usable_size,
@@ -1667,12 +1674,13 @@
// The allocation failed. If the GC is running, block until it completes, and then retry the
// allocation.
collector::GcType last_gc = WaitForGcToComplete(kGcCauseForAlloc, self);
+ // If we were the default allocator but the allocator changed while we were suspended,
+ // abort the allocation.
+ if ((was_default_allocator && allocator != GetCurrentAllocator()) ||
+ (!instrumented && EntrypointsInstrumented())) {
+ return nullptr;
+ }
if (last_gc != collector::kGcTypeNone) {
- // If we were the default allocator but the allocator changed while we were suspended,
- // abort the allocation.
- if (was_default_allocator && allocator != GetCurrentAllocator()) {
- return nullptr;
- }
// A GC was in progress and we blocked, retry allocation now that memory has been freed.
mirror::Object* ptr = TryToAllocate<true, false>(self, allocator, alloc_size, bytes_allocated,
usable_size, bytes_tl_bulk_allocated);
@@ -1684,7 +1692,8 @@
collector::GcType tried_type = next_gc_type_;
const bool gc_ran =
CollectGarbageInternal(tried_type, kGcCauseForAlloc, false) != collector::kGcTypeNone;
- if (was_default_allocator && allocator != GetCurrentAllocator()) {
+ if ((was_default_allocator && allocator != GetCurrentAllocator()) ||
+ (!instrumented && EntrypointsInstrumented())) {
return nullptr;
}
if (gc_ran) {
@@ -1703,7 +1712,8 @@
// Attempt to run the collector, if we succeed, re-try the allocation.
const bool plan_gc_ran =
CollectGarbageInternal(gc_type, kGcCauseForAlloc, false) != collector::kGcTypeNone;
- if (was_default_allocator && allocator != GetCurrentAllocator()) {
+ if ((was_default_allocator && allocator != GetCurrentAllocator()) ||
+ (!instrumented && EntrypointsInstrumented())) {
return nullptr;
}
if (plan_gc_ran) {
@@ -1732,7 +1742,8 @@
// We don't need a WaitForGcToComplete here either.
DCHECK(!gc_plan_.empty());
CollectGarbageInternal(gc_plan_.back(), kGcCauseForAlloc, true);
- if (was_default_allocator && allocator != GetCurrentAllocator()) {
+ if ((was_default_allocator && allocator != GetCurrentAllocator()) ||
+ (!instrumented && EntrypointsInstrumented())) {
return nullptr;
}
ptr = TryToAllocate<true, true>(self, allocator, alloc_size, bytes_allocated, usable_size,
@@ -1748,6 +1759,11 @@
min_interval_homogeneous_space_compaction_by_oom_) {
last_time_homogeneous_space_compaction_by_oom_ = current_time;
HomogeneousSpaceCompactResult result = PerformHomogeneousSpaceCompact();
+ // Thread suspension could have occurred.
+ if ((was_default_allocator && allocator != GetCurrentAllocator()) ||
+ (!instrumented && EntrypointsInstrumented())) {
+ return nullptr;
+ }
switch (result) {
case HomogeneousSpaceCompactResult::kSuccess:
// If the allocation succeeded, we delayed an oom.
@@ -1788,6 +1804,11 @@
// If we aren't out of memory then the OOM was probably from the non moving space being
// full. Attempt to disable compaction and turn the main space into a non moving space.
DisableMovingGc();
+ // Thread suspension could have occurred.
+ if ((was_default_allocator && allocator != GetCurrentAllocator()) ||
+ (!instrumented && EntrypointsInstrumented())) {
+ return nullptr;
+ }
// If we are still a moving GC then something must have caused the transition to fail.
if (IsMovingGc(collector_type_)) {
MutexLock mu(self, *gc_complete_lock_);
@@ -3926,6 +3947,10 @@
allocation_records_.reset(records);
}
+std::unique_ptr<AllocRecordObjectMap> Heap::ReleaseAllocationRecords() {
+ return std::move(allocation_records_);
+}
+
void Heap::VisitAllocationRecords(RootVisitor* visitor) const {
if (IsAllocTrackingEnabled()) {
MutexLock mu(Thread::Current(), *Locks::alloc_tracker_lock_);
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 6edb548..889069d 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -766,6 +766,10 @@
return allocation_records_.get();
}
+ // Release ownership of the allocation records.
+ std::unique_ptr<AllocRecordObjectMap> ReleaseAllocationRecords()
+ REQUIRES(Locks::alloc_tracker_lock_);
+
void SetAllocationRecords(AllocRecordObjectMap* records)
REQUIRES(Locks::alloc_tracker_lock_);
@@ -865,6 +869,7 @@
// an initial allocation attempt failed.
mirror::Object* AllocateInternalWithGc(Thread* self,
AllocatorType allocator,
+ bool instrumented,
size_t num_bytes,
size_t* bytes_allocated,
size_t* usable_size,
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 2e4be6b..b3cdb41 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -419,6 +419,12 @@
size_t inlined_frames_before_frame)
SHARED_REQUIRES(Locks::mutator_lock_);
+ // Does not hold lock, used to check if someone changed from not instrumented to instrumented
+ // during a GC suspend point.
+ bool AllocEntrypointsInstrumented() const SHARED_REQUIRES(Locks::mutator_lock_) {
+ return quick_alloc_entry_points_instrumentation_counter_ > 0;
+ }
+
private:
InstrumentationLevel GetCurrentInstrumentationLevel() const;
@@ -572,9 +578,7 @@
InterpreterHandlerTable interpreter_handler_table_ GUARDED_BY(Locks::mutator_lock_);
// Greater than 0 if quick alloc entry points instrumented.
- size_t quick_alloc_entry_points_instrumentation_counter_
- GUARDED_BY(Locks::instrument_entrypoints_lock_);
-
+ size_t quick_alloc_entry_points_instrumentation_counter_;
friend class InstrumentationTest; // For GetCurrentInstrumentationLevel and ConfigureStubs.
DISALLOW_COPY_AND_ASSIGN(Instrumentation);
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index a595d33..baf4afe 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -240,20 +240,10 @@
return os;
}
-#if !defined(__clang__)
-#if (defined(__arm__) || defined(__i386__) || defined(__aarch64__))
-// TODO: remove when all targets implemented.
static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind;
-#else
-static constexpr InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind;
-#endif
-#else
+
+#if defined(__clang__)
// Clang 3.4 fails to build the goto interpreter implementation.
-#if (defined(__arm__) || defined(__i386__) || defined(__aarch64__))
-static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind;
-#else
-static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImplKind;
-#endif
template<bool do_access_check, bool transaction_active>
JValue ExecuteGotoImpl(Thread*, const DexFile::CodeItem*, ShadowFrame&, JValue) {
LOG(FATAL) << "UNREACHABLE";
@@ -295,9 +285,7 @@
}
jit::Jit* jit = Runtime::Current()->GetJit();
- if (UNLIKELY(jit != nullptr &&
- jit->JitAtFirstUse() &&
- jit->GetCodeCache()->ContainsMethod(method))) {
+ if (jit != nullptr && jit->CanInvokeCompiledCode(method)) {
JValue result;
// Pop the shadow frame before calling into compiled code.
@@ -327,12 +315,8 @@
while (true) {
// Mterp does not support all instrumentation/debugging.
if (MterpShouldSwitchInterpreters()) {
-#if !defined(__clang__)
- return ExecuteGotoImpl<false, false>(self, code_item, shadow_frame, result_register);
-#else
return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register,
false);
-#endif
}
bool returned = ExecuteMterpImpl(self, code_item, &shadow_frame, &result_register);
if (returned) {
diff --git a/runtime/interpreter/mterp/arm/op_cmpg_double.S b/runtime/interpreter/mterp/arm/op_cmpg_double.S
index 4b05c44..602a4b1 100644
--- a/runtime/interpreter/mterp/arm/op_cmpg_double.S
+++ b/runtime/interpreter/mterp/arm/op_cmpg_double.S
@@ -23,7 +23,7 @@
VREG_INDEX_TO_ADDR r3, r3 @ r3<- &vCC
fldd d0, [r2] @ d0<- vBB
fldd d1, [r3] @ d1<- vCC
- fcmped d0, d1 @ compare (vBB, vCC)
+ vcmpe.f64 d0, d1 @ compare (vBB, vCC)
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
mov r0, #1 @ r0<- 1 (default)
GET_INST_OPCODE ip @ extract opcode from rINST
diff --git a/runtime/interpreter/mterp/arm/op_cmpg_float.S b/runtime/interpreter/mterp/arm/op_cmpg_float.S
index d5d2df2..965091f 100644
--- a/runtime/interpreter/mterp/arm/op_cmpg_float.S
+++ b/runtime/interpreter/mterp/arm/op_cmpg_float.S
@@ -23,7 +23,7 @@
VREG_INDEX_TO_ADDR r3, r3 @ r3<- &vCC
flds s0, [r2] @ s0<- vBB
flds s1, [r3] @ s1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ vcmpe.f32 s0, s1 @ compare (vBB, vCC)
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
mov r0, #1 @ r0<- 1 (default)
GET_INST_OPCODE ip @ extract opcode from rINST
diff --git a/runtime/interpreter/mterp/arm/op_cmpl_double.S b/runtime/interpreter/mterp/arm/op_cmpl_double.S
index 6ee53b3..8a5e509 100644
--- a/runtime/interpreter/mterp/arm/op_cmpl_double.S
+++ b/runtime/interpreter/mterp/arm/op_cmpl_double.S
@@ -23,7 +23,7 @@
VREG_INDEX_TO_ADDR r3, r3 @ r3<- &vCC
fldd d0, [r2] @ d0<- vBB
fldd d1, [r3] @ d1<- vCC
- fcmped d0, d1 @ compare (vBB, vCC)
+ vcmpe.f64 d0, d1 @ compare (vBB, vCC)
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
mvn r0, #0 @ r0<- -1 (default)
GET_INST_OPCODE ip @ extract opcode from rINST
diff --git a/runtime/interpreter/mterp/arm/op_cmpl_float.S b/runtime/interpreter/mterp/arm/op_cmpl_float.S
index 64535b6..9df0c2c 100644
--- a/runtime/interpreter/mterp/arm/op_cmpl_float.S
+++ b/runtime/interpreter/mterp/arm/op_cmpl_float.S
@@ -23,7 +23,7 @@
VREG_INDEX_TO_ADDR r3, r3 @ r3<- &vCC
flds s0, [r2] @ s0<- vBB
flds s1, [r3] @ s1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ vcmpe.f32 s0, s1 @ compare (vBB, vCC)
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
mvn r0, #0 @ r0<- -1 (default)
GET_INST_OPCODE ip @ extract opcode from rINST
diff --git a/runtime/interpreter/mterp/arm/op_double_to_float.S b/runtime/interpreter/mterp/arm/op_double_to_float.S
index e327000..98fdfbc 100644
--- a/runtime/interpreter/mterp/arm/op_double_to_float.S
+++ b/runtime/interpreter/mterp/arm/op_double_to_float.S
@@ -1 +1 @@
-%include "arm/funopNarrower.S" {"instr":"fcvtsd s0, d0"}
+%include "arm/funopNarrower.S" {"instr":"vcvt.f32.f64 s0, d0"}
diff --git a/runtime/interpreter/mterp/arm/op_float_to_double.S b/runtime/interpreter/mterp/arm/op_float_to_double.S
index fb1892b..b1e12bd 100644
--- a/runtime/interpreter/mterp/arm/op_float_to_double.S
+++ b/runtime/interpreter/mterp/arm/op_float_to_double.S
@@ -1 +1 @@
-%include "arm/funopWider.S" {"instr":"fcvtds d0, s0"}
+%include "arm/funopWider.S" {"instr":"vcvt.f64.f32 d0, s0"}
diff --git a/runtime/interpreter/mterp/arm/op_float_to_long.S b/runtime/interpreter/mterp/arm/op_float_to_long.S
index 24416d3..5c8680f 100644
--- a/runtime/interpreter/mterp/arm/op_float_to_long.S
+++ b/runtime/interpreter/mterp/arm/op_float_to_long.S
@@ -17,7 +17,7 @@
cmp r0, #0 @ nonzero == yes
mvnne r0, #0 @ return maxlong (7fffffff)
mvnne r1, #0x80000000
- ldmnefd sp!, {r4, pc}
+ popne {r4, pc}
mov r0, r4 @ recover arg
mov r1, #0xdf000000 @ (float)minlong
@@ -25,14 +25,14 @@
cmp r0, #0 @ nonzero == yes
movne r0, #0 @ return minlong (80000000)
movne r1, #0x80000000
- ldmnefd sp!, {r4, pc}
+ popne {r4, pc}
mov r0, r4 @ recover arg
mov r1, r4
bl __aeabi_fcmpeq @ is arg == self?
cmp r0, #0 @ zero == no
moveq r1, #0 @ return zero for NaN
- ldmeqfd sp!, {r4, pc}
+ popeq {r4, pc}
mov r0, r4 @ recover arg
bl __aeabi_f2lz @ convert float to long
diff --git a/runtime/interpreter/mterp/config_mips b/runtime/interpreter/mterp/config_mips
index d1221f7..c6292c3 100644
--- a/runtime/interpreter/mterp/config_mips
+++ b/runtime/interpreter/mterp/config_mips
@@ -1,4 +1,4 @@
-# Copyright (C) 2015 The Android Open Source Project
+# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
# limitations under the License.
#
-# Configuration for MIPS_32
+# Configuration for MIPS_32 targets.
#
handler-style computed-goto
@@ -33,265 +33,265 @@
# opcode list; argument to op-start is default directory
op-start mips
- # (override example:) op OP_SUB_FLOAT_2ADDR arm-vfp
- # (fallback example:) op OP_SUB_FLOAT_2ADDR FALLBACK
+ # (override example:) op op_sub_float_2addr arm-vfp
+ # (fallback example:) op op_sub_float_2addr FALLBACK
- op op_nop FALLBACK
- op op_move FALLBACK
- op op_move_from16 FALLBACK
- op op_move_16 FALLBACK
- op op_move_wide FALLBACK
- op op_move_wide_from16 FALLBACK
- op op_move_wide_16 FALLBACK
- op op_move_object FALLBACK
- op op_move_object_from16 FALLBACK
- op op_move_object_16 FALLBACK
- op op_move_result FALLBACK
- op op_move_result_wide FALLBACK
- op op_move_result_object FALLBACK
- op op_move_exception FALLBACK
- op op_return_void FALLBACK
- op op_return FALLBACK
- op op_return_wide FALLBACK
- op op_return_object FALLBACK
- op op_const_4 FALLBACK
- op op_const_16 FALLBACK
- op op_const FALLBACK
- op op_const_high16 FALLBACK
- op op_const_wide_16 FALLBACK
- op op_const_wide_32 FALLBACK
- op op_const_wide FALLBACK
- op op_const_wide_high16 FALLBACK
- op op_const_string FALLBACK
- op op_const_string_jumbo FALLBACK
- op op_const_class FALLBACK
- op op_monitor_enter FALLBACK
- op op_monitor_exit FALLBACK
- op op_check_cast FALLBACK
- op op_instance_of FALLBACK
- op op_array_length FALLBACK
- op op_new_instance FALLBACK
- op op_new_array FALLBACK
- op op_filled_new_array FALLBACK
- op op_filled_new_array_range FALLBACK
- op op_fill_array_data FALLBACK
- op op_throw FALLBACK
- op op_goto FALLBACK
- op op_goto_16 FALLBACK
- op op_goto_32 FALLBACK
- op op_packed_switch FALLBACK
- op op_sparse_switch FALLBACK
- op op_cmpl_float FALLBACK
- op op_cmpg_float FALLBACK
- op op_cmpl_double FALLBACK
- op op_cmpg_double FALLBACK
- op op_cmp_long FALLBACK
- op op_if_eq FALLBACK
- op op_if_ne FALLBACK
- op op_if_lt FALLBACK
- op op_if_ge FALLBACK
- op op_if_gt FALLBACK
- op op_if_le FALLBACK
- op op_if_eqz FALLBACK
- op op_if_nez FALLBACK
- op op_if_ltz FALLBACK
- op op_if_gez FALLBACK
- op op_if_gtz FALLBACK
- op op_if_lez FALLBACK
- op_unused_3e FALLBACK
- op_unused_3f FALLBACK
- op_unused_40 FALLBACK
- op_unused_41 FALLBACK
- op_unused_42 FALLBACK
- op_unused_43 FALLBACK
- op op_aget FALLBACK
- op op_aget_wide FALLBACK
- op op_aget_object FALLBACK
- op op_aget_boolean FALLBACK
- op op_aget_byte FALLBACK
- op op_aget_char FALLBACK
- op op_aget_short FALLBACK
- op op_aput FALLBACK
- op op_aput_wide FALLBACK
- op op_aput_object FALLBACK
- op op_aput_boolean FALLBACK
- op op_aput_byte FALLBACK
- op op_aput_char FALLBACK
- op op_aput_short FALLBACK
- op op_iget FALLBACK
- op op_iget_wide FALLBACK
- op op_iget_object FALLBACK
- op op_iget_boolean FALLBACK
- op op_iget_byte FALLBACK
- op op_iget_char FALLBACK
- op op_iget_short FALLBACK
- op op_iput FALLBACK
- op op_iput_wide FALLBACK
- op op_iput_object FALLBACK
- op op_iput_boolean FALLBACK
- op op_iput_byte FALLBACK
- op op_iput_char FALLBACK
- op op_iput_short FALLBACK
- op op_sget FALLBACK
- op op_sget_wide FALLBACK
- op op_sget_object FALLBACK
- op op_sget_boolean FALLBACK
- op op_sget_byte FALLBACK
- op op_sget_char FALLBACK
- op op_sget_short FALLBACK
- op op_sput FALLBACK
- op op_sput_wide FALLBACK
- op op_sput_object FALLBACK
- op op_sput_boolean FALLBACK
- op op_sput_byte FALLBACK
- op op_sput_char FALLBACK
- op op_sput_short FALLBACK
- op op_invoke_virtual FALLBACK
- op op_invoke_super FALLBACK
- op op_invoke_direct FALLBACK
- op op_invoke_static FALLBACK
- op op_invoke_interface FALLBACK
- op op_return_void_no_barrier FALLBACK
- op op_invoke_virtual_range FALLBACK
- op op_invoke_super_range FALLBACK
- op op_invoke_direct_range FALLBACK
- op op_invoke_static_range FALLBACK
- op op_invoke_interface_range FALLBACK
- op_unused_79 FALLBACK
- op_unused_7a FALLBACK
- op op_neg_int FALLBACK
- op op_not_int FALLBACK
- op op_neg_long FALLBACK
- op op_not_long FALLBACK
- op op_neg_float FALLBACK
- op op_neg_double FALLBACK
- op op_int_to_long FALLBACK
- op op_int_to_float FALLBACK
- op op_int_to_double FALLBACK
- op op_long_to_int FALLBACK
- op op_long_to_float FALLBACK
- op op_long_to_double FALLBACK
- op op_float_to_int FALLBACK
- op op_float_to_long FALLBACK
- op op_float_to_double FALLBACK
- op op_double_to_int FALLBACK
- op op_double_to_long FALLBACK
- op op_double_to_float FALLBACK
- op op_int_to_byte FALLBACK
- op op_int_to_char FALLBACK
- op op_int_to_short FALLBACK
- op op_add_int FALLBACK
- op op_sub_int FALLBACK
- op op_mul_int FALLBACK
- op op_div_int FALLBACK
- op op_rem_int FALLBACK
- op op_and_int FALLBACK
- op op_or_int FALLBACK
- op op_xor_int FALLBACK
- op op_shl_int FALLBACK
- op op_shr_int FALLBACK
- op op_ushr_int FALLBACK
- op op_add_long FALLBACK
- op op_sub_long FALLBACK
- op op_mul_long FALLBACK
- op op_div_long FALLBACK
- op op_rem_long FALLBACK
- op op_and_long FALLBACK
- op op_or_long FALLBACK
- op op_xor_long FALLBACK
- op op_shl_long FALLBACK
- op op_shr_long FALLBACK
- op op_ushr_long FALLBACK
- op op_add_float FALLBACK
- op op_sub_float FALLBACK
- op op_mul_float FALLBACK
- op op_div_float FALLBACK
- op op_rem_float FALLBACK
- op op_add_double FALLBACK
- op op_sub_double FALLBACK
- op op_mul_double FALLBACK
- op op_div_double FALLBACK
- op op_rem_double FALLBACK
- op op_add_int_2addr FALLBACK
- op op_sub_int_2addr FALLBACK
- op op_mul_int_2addr FALLBACK
- op op_div_int_2addr FALLBACK
- op op_rem_int_2addr FALLBACK
- op op_and_int_2addr FALLBACK
- op op_or_int_2addr FALLBACK
- op op_xor_int_2addr FALLBACK
- op op_shl_int_2addr FALLBACK
- op op_shr_int_2addr FALLBACK
- op op_ushr_int_2addr FALLBACK
- op op_add_long_2addr FALLBACK
- op op_sub_long_2addr FALLBACK
- op op_mul_long_2addr FALLBACK
- op op_div_long_2addr FALLBACK
- op op_rem_long_2addr FALLBACK
- op op_and_long_2addr FALLBACK
- op op_or_long_2addr FALLBACK
- op op_xor_long_2addr FALLBACK
- op op_shl_long_2addr FALLBACK
- op op_shr_long_2addr FALLBACK
- op op_ushr_long_2addr FALLBACK
- op op_add_float_2addr FALLBACK
- op op_sub_float_2addr FALLBACK
- op op_mul_float_2addr FALLBACK
- op op_div_float_2addr FALLBACK
- op op_rem_float_2addr FALLBACK
- op op_add_double_2addr FALLBACK
- op op_sub_double_2addr FALLBACK
- op op_mul_double_2addr FALLBACK
- op op_div_double_2addr FALLBACK
- op op_rem_double_2addr FALLBACK
- op op_add_int_lit16 FALLBACK
- op op_rsub_int FALLBACK
- op op_mul_int_lit16 FALLBACK
- op op_div_int_lit16 FALLBACK
- op op_rem_int_lit16 FALLBACK
- op op_and_int_lit16 FALLBACK
- op op_or_int_lit16 FALLBACK
- op op_xor_int_lit16 FALLBACK
- op op_add_int_lit8 FALLBACK
- op op_rsub_int_lit8 FALLBACK
- op op_mul_int_lit8 FALLBACK
- op op_div_int_lit8 FALLBACK
- op op_rem_int_lit8 FALLBACK
- op op_and_int_lit8 FALLBACK
- op op_or_int_lit8 FALLBACK
- op op_xor_int_lit8 FALLBACK
- op op_shl_int_lit8 FALLBACK
- op op_shr_int_lit8 FALLBACK
- op op_ushr_int_lit8 FALLBACK
- op op_iget_quick FALLBACK
- op op_iget_wide_quick FALLBACK
- op op_iget_object_quick FALLBACK
- op op_iput_quick FALLBACK
- op op_iput_wide_quick FALLBACK
- op op_iput_object_quick FALLBACK
- op op_invoke_virtual_quick FALLBACK
- op op_invoke_virtual_range_quick FALLBACK
- op op_iput_boolean_quick FALLBACK
- op op_iput_byte_quick FALLBACK
- op op_iput_char_quick FALLBACK
- op op_iput_short_quick FALLBACK
- op op_iget_boolean_quick FALLBACK
- op op_iget_byte_quick FALLBACK
- op op_iget_char_quick FALLBACK
- op op_iget_short_quick FALLBACK
- op_unused_f3 FALLBACK
- op_unused_f4 FALLBACK
- op_unused_f5 FALLBACK
- op_unused_f6 FALLBACK
- op_unused_f7 FALLBACK
- op_unused_f8 FALLBACK
- op_unused_f9 FALLBACK
- op_unused_fa FALLBACK
- op_unused_fb FALLBACK
- op_unused_fc FALLBACK
- op_unused_fd FALLBACK
- op_unused_fe FALLBACK
- op_unused_ff FALLBACK
+ # op op_nop FALLBACK
+ # op op_move FALLBACK
+ # op op_move_from16 FALLBACK
+ # op op_move_16 FALLBACK
+ # op op_move_wide FALLBACK
+ # op op_move_wide_from16 FALLBACK
+ # op op_move_wide_16 FALLBACK
+ # op op_move_object FALLBACK
+ # op op_move_object_from16 FALLBACK
+ # op op_move_object_16 FALLBACK
+ # op op_move_result FALLBACK
+ # op op_move_result_wide FALLBACK
+ # op op_move_result_object FALLBACK
+ # op op_move_exception FALLBACK
+ # op op_return_void FALLBACK
+ # op op_return FALLBACK
+ # op op_return_wide FALLBACK
+ # op op_return_object FALLBACK
+ # op op_const_4 FALLBACK
+ # op op_const_16 FALLBACK
+ # op op_const FALLBACK
+ # op op_const_high16 FALLBACK
+ # op op_const_wide_16 FALLBACK
+ # op op_const_wide_32 FALLBACK
+ # op op_const_wide FALLBACK
+ # op op_const_wide_high16 FALLBACK
+ # op op_const_string FALLBACK
+ # op op_const_string_jumbo FALLBACK
+ # op op_const_class FALLBACK
+ # op op_monitor_enter FALLBACK
+ # op op_monitor_exit FALLBACK
+ # op op_check_cast FALLBACK
+ # op op_instance_of FALLBACK
+ # op op_array_length FALLBACK
+ # op op_new_instance FALLBACK
+ # op op_new_array FALLBACK
+ # op op_filled_new_array FALLBACK
+ # op op_filled_new_array_range FALLBACK
+ # op op_fill_array_data FALLBACK
+ # op op_throw FALLBACK
+ # op op_goto FALLBACK
+ # op op_goto_16 FALLBACK
+ # op op_goto_32 FALLBACK
+ # op op_packed_switch FALLBACK
+ # op op_sparse_switch FALLBACK
+ # op op_cmpl_float FALLBACK
+ # op op_cmpg_float FALLBACK
+ # op op_cmpl_double FALLBACK
+ # op op_cmpg_double FALLBACK
+ # op op_cmp_long FALLBACK
+ # op op_if_eq FALLBACK
+ # op op_if_ne FALLBACK
+ # op op_if_lt FALLBACK
+ # op op_if_ge FALLBACK
+ # op op_if_gt FALLBACK
+ # op op_if_le FALLBACK
+ # op op_if_eqz FALLBACK
+ # op op_if_nez FALLBACK
+ # op op_if_ltz FALLBACK
+ # op op_if_gez FALLBACK
+ # op op_if_gtz FALLBACK
+ # op op_if_lez FALLBACK
+ # op op_unused_3e FALLBACK
+ # op op_unused_3f FALLBACK
+ # op op_unused_40 FALLBACK
+ # op op_unused_41 FALLBACK
+ # op op_unused_42 FALLBACK
+ # op op_unused_43 FALLBACK
+ # op op_aget FALLBACK
+ # op op_aget_wide FALLBACK
+ # op op_aget_object FALLBACK
+ # op op_aget_boolean FALLBACK
+ # op op_aget_byte FALLBACK
+ # op op_aget_char FALLBACK
+ # op op_aget_short FALLBACK
+ # op op_aput FALLBACK
+ # op op_aput_wide FALLBACK
+ # op op_aput_object FALLBACK
+ # op op_aput_boolean FALLBACK
+ # op op_aput_byte FALLBACK
+ # op op_aput_char FALLBACK
+ # op op_aput_short FALLBACK
+ # op op_iget FALLBACK
+ # op op_iget_wide FALLBACK
+ # op op_iget_object FALLBACK
+ # op op_iget_boolean FALLBACK
+ # op op_iget_byte FALLBACK
+ # op op_iget_char FALLBACK
+ # op op_iget_short FALLBACK
+ # op op_iput FALLBACK
+ # op op_iput_wide FALLBACK
+ # op op_iput_object FALLBACK
+ # op op_iput_boolean FALLBACK
+ # op op_iput_byte FALLBACK
+ # op op_iput_char FALLBACK
+ # op op_iput_short FALLBACK
+ # op op_sget FALLBACK
+ # op op_sget_wide FALLBACK
+ # op op_sget_object FALLBACK
+ # op op_sget_boolean FALLBACK
+ # op op_sget_byte FALLBACK
+ # op op_sget_char FALLBACK
+ # op op_sget_short FALLBACK
+ # op op_sput FALLBACK
+ # op op_sput_wide FALLBACK
+ # op op_sput_object FALLBACK
+ # op op_sput_boolean FALLBACK
+ # op op_sput_byte FALLBACK
+ # op op_sput_char FALLBACK
+ # op op_sput_short FALLBACK
+ # op op_invoke_virtual FALLBACK
+ # op op_invoke_super FALLBACK
+ # op op_invoke_direct FALLBACK
+ # op op_invoke_static FALLBACK
+ # op op_invoke_interface FALLBACK
+ # op op_return_void_no_barrier FALLBACK
+ # op op_invoke_virtual_range FALLBACK
+ # op op_invoke_super_range FALLBACK
+ # op op_invoke_direct_range FALLBACK
+ # op op_invoke_static_range FALLBACK
+ # op op_invoke_interface_range FALLBACK
+ # op op_unused_79 FALLBACK
+ # op op_unused_7a FALLBACK
+ # op op_neg_int FALLBACK
+ # op op_not_int FALLBACK
+ # op op_neg_long FALLBACK
+ # op op_not_long FALLBACK
+ # op op_neg_float FALLBACK
+ # op op_neg_double FALLBACK
+ # op op_int_to_long FALLBACK
+ # op op_int_to_float FALLBACK
+ # op op_int_to_double FALLBACK
+ # op op_long_to_int FALLBACK
+ # op op_long_to_float FALLBACK
+ # op op_long_to_double FALLBACK
+ # op op_float_to_int FALLBACK
+ # op op_float_to_long FALLBACK
+ # op op_float_to_double FALLBACK
+ # op op_double_to_int FALLBACK
+ # op op_double_to_long FALLBACK
+ # op op_double_to_float FALLBACK
+ # op op_int_to_byte FALLBACK
+ # op op_int_to_char FALLBACK
+ # op op_int_to_short FALLBACK
+ # op op_add_int FALLBACK
+ # op op_sub_int FALLBACK
+ # op op_mul_int FALLBACK
+ # op op_div_int FALLBACK
+ # op op_rem_int FALLBACK
+ # op op_and_int FALLBACK
+ # op op_or_int FALLBACK
+ # op op_xor_int FALLBACK
+ # op op_shl_int FALLBACK
+ # op op_shr_int FALLBACK
+ # op op_ushr_int FALLBACK
+ # op op_add_long FALLBACK
+ # op op_sub_long FALLBACK
+ # op op_mul_long FALLBACK
+ # op op_div_long FALLBACK
+ # op op_rem_long FALLBACK
+ # op op_and_long FALLBACK
+ # op op_or_long FALLBACK
+ # op op_xor_long FALLBACK
+ # op op_shl_long FALLBACK
+ # op op_shr_long FALLBACK
+ # op op_ushr_long FALLBACK
+ # op op_add_float FALLBACK
+ # op op_sub_float FALLBACK
+ # op op_mul_float FALLBACK
+ # op op_div_float FALLBACK
+ # op op_rem_float FALLBACK
+ # op op_add_double FALLBACK
+ # op op_sub_double FALLBACK
+ # op op_mul_double FALLBACK
+ # op op_div_double FALLBACK
+ # op op_rem_double FALLBACK
+ # op op_add_int_2addr FALLBACK
+ # op op_sub_int_2addr FALLBACK
+ # op op_mul_int_2addr FALLBACK
+ # op op_div_int_2addr FALLBACK
+ # op op_rem_int_2addr FALLBACK
+ # op op_and_int_2addr FALLBACK
+ # op op_or_int_2addr FALLBACK
+ # op op_xor_int_2addr FALLBACK
+ # op op_shl_int_2addr FALLBACK
+ # op op_shr_int_2addr FALLBACK
+ # op op_ushr_int_2addr FALLBACK
+ # op op_add_long_2addr FALLBACK
+ # op op_sub_long_2addr FALLBACK
+ # op op_mul_long_2addr FALLBACK
+ # op op_div_long_2addr FALLBACK
+ # op op_rem_long_2addr FALLBACK
+ # op op_and_long_2addr FALLBACK
+ # op op_or_long_2addr FALLBACK
+ # op op_xor_long_2addr FALLBACK
+ # op op_shl_long_2addr FALLBACK
+ # op op_shr_long_2addr FALLBACK
+ # op op_ushr_long_2addr FALLBACK
+ # op op_add_float_2addr FALLBACK
+ # op op_sub_float_2addr FALLBACK
+ # op op_mul_float_2addr FALLBACK
+ # op op_div_float_2addr FALLBACK
+ # op op_rem_float_2addr FALLBACK
+ # op op_add_double_2addr FALLBACK
+ # op op_sub_double_2addr FALLBACK
+ # op op_mul_double_2addr FALLBACK
+ # op op_div_double_2addr FALLBACK
+ # op op_rem_double_2addr FALLBACK
+ # op op_add_int_lit16 FALLBACK
+ # op op_rsub_int FALLBACK
+ # op op_mul_int_lit16 FALLBACK
+ # op op_div_int_lit16 FALLBACK
+ # op op_rem_int_lit16 FALLBACK
+ # op op_and_int_lit16 FALLBACK
+ # op op_or_int_lit16 FALLBACK
+ # op op_xor_int_lit16 FALLBACK
+ # op op_add_int_lit8 FALLBACK
+ # op op_rsub_int_lit8 FALLBACK
+ # op op_mul_int_lit8 FALLBACK
+ # op op_div_int_lit8 FALLBACK
+ # op op_rem_int_lit8 FALLBACK
+ # op op_and_int_lit8 FALLBACK
+ # op op_or_int_lit8 FALLBACK
+ # op op_xor_int_lit8 FALLBACK
+ # op op_shl_int_lit8 FALLBACK
+ # op op_shr_int_lit8 FALLBACK
+ # op op_ushr_int_lit8 FALLBACK
+ # op op_iget_quick FALLBACK
+ # op op_iget_wide_quick FALLBACK
+ # op op_iget_object_quick FALLBACK
+ # op op_iput_quick FALLBACK
+ # op op_iput_wide_quick FALLBACK
+ # op op_iput_object_quick FALLBACK
+ # op op_invoke_virtual_quick FALLBACK
+ # op op_invoke_virtual_range_quick FALLBACK
+ # op op_iput_boolean_quick FALLBACK
+ # op op_iput_byte_quick FALLBACK
+ # op op_iput_char_quick FALLBACK
+ # op op_iput_short_quick FALLBACK
+ # op op_iget_boolean_quick FALLBACK
+ # op op_iget_byte_quick FALLBACK
+ # op op_iget_char_quick FALLBACK
+ # op op_iget_short_quick FALLBACK
+ op op_invoke_lambda FALLBACK
+ # op op_unused_f4 FALLBACK
+ op op_capture_variable FALLBACK
+ op op_create_lambda FALLBACK
+ op op_liberate_variable FALLBACK
+ op op_box_lambda FALLBACK
+ op op_unbox_lambda FALLBACK
+ # op op_unused_fa FALLBACK
+ # op op_unused_fb FALLBACK
+ # op op_unused_fc FALLBACK
+ # op op_unused_fd FALLBACK
+ # op op_unused_fe FALLBACK
+ # op op_unused_ff FALLBACK
op-end
# common subroutines for asm
diff --git a/runtime/interpreter/mterp/config_mips64 b/runtime/interpreter/mterp/config_mips64
index f804ce5..c40c007 100644
--- a/runtime/interpreter/mterp/config_mips64
+++ b/runtime/interpreter/mterp/config_mips64
@@ -36,262 +36,262 @@
# (override example:) op OP_SUB_FLOAT_2ADDR arm-vfp
# (fallback example:) op OP_SUB_FLOAT_2ADDR FALLBACK
- op op_nop FALLBACK
- op op_move FALLBACK
- op op_move_from16 FALLBACK
- op op_move_16 FALLBACK
- op op_move_wide FALLBACK
- op op_move_wide_from16 FALLBACK
- op op_move_wide_16 FALLBACK
- op op_move_object FALLBACK
- op op_move_object_from16 FALLBACK
- op op_move_object_16 FALLBACK
- op op_move_result FALLBACK
- op op_move_result_wide FALLBACK
- op op_move_result_object FALLBACK
- op op_move_exception FALLBACK
- op op_return_void FALLBACK
- op op_return FALLBACK
- op op_return_wide FALLBACK
- op op_return_object FALLBACK
- op op_const_4 FALLBACK
- op op_const_16 FALLBACK
- op op_const FALLBACK
- op op_const_high16 FALLBACK
- op op_const_wide_16 FALLBACK
- op op_const_wide_32 FALLBACK
- op op_const_wide FALLBACK
- op op_const_wide_high16 FALLBACK
- op op_const_string FALLBACK
- op op_const_string_jumbo FALLBACK
- op op_const_class FALLBACK
- op op_monitor_enter FALLBACK
- op op_monitor_exit FALLBACK
- op op_check_cast FALLBACK
- op op_instance_of FALLBACK
- op op_array_length FALLBACK
- op op_new_instance FALLBACK
- op op_new_array FALLBACK
- op op_filled_new_array FALLBACK
- op op_filled_new_array_range FALLBACK
- op op_fill_array_data FALLBACK
- op op_throw FALLBACK
- op op_goto FALLBACK
- op op_goto_16 FALLBACK
- op op_goto_32 FALLBACK
- op op_packed_switch FALLBACK
- op op_sparse_switch FALLBACK
- op op_cmpl_float FALLBACK
- op op_cmpg_float FALLBACK
- op op_cmpl_double FALLBACK
- op op_cmpg_double FALLBACK
- op op_cmp_long FALLBACK
- op op_if_eq FALLBACK
- op op_if_ne FALLBACK
- op op_if_lt FALLBACK
- op op_if_ge FALLBACK
- op op_if_gt FALLBACK
- op op_if_le FALLBACK
- op op_if_eqz FALLBACK
- op op_if_nez FALLBACK
- op op_if_ltz FALLBACK
- op op_if_gez FALLBACK
- op op_if_gtz FALLBACK
- op op_if_lez FALLBACK
- op_unused_3e FALLBACK
- op_unused_3f FALLBACK
- op_unused_40 FALLBACK
- op_unused_41 FALLBACK
- op_unused_42 FALLBACK
- op_unused_43 FALLBACK
- op op_aget FALLBACK
- op op_aget_wide FALLBACK
- op op_aget_object FALLBACK
- op op_aget_boolean FALLBACK
- op op_aget_byte FALLBACK
- op op_aget_char FALLBACK
- op op_aget_short FALLBACK
- op op_aput FALLBACK
- op op_aput_wide FALLBACK
- op op_aput_object FALLBACK
- op op_aput_boolean FALLBACK
- op op_aput_byte FALLBACK
- op op_aput_char FALLBACK
- op op_aput_short FALLBACK
- op op_iget FALLBACK
- op op_iget_wide FALLBACK
- op op_iget_object FALLBACK
- op op_iget_boolean FALLBACK
- op op_iget_byte FALLBACK
- op op_iget_char FALLBACK
- op op_iget_short FALLBACK
- op op_iput FALLBACK
- op op_iput_wide FALLBACK
- op op_iput_object FALLBACK
- op op_iput_boolean FALLBACK
- op op_iput_byte FALLBACK
- op op_iput_char FALLBACK
- op op_iput_short FALLBACK
- op op_sget FALLBACK
- op op_sget_wide FALLBACK
- op op_sget_object FALLBACK
- op op_sget_boolean FALLBACK
- op op_sget_byte FALLBACK
- op op_sget_char FALLBACK
- op op_sget_short FALLBACK
- op op_sput FALLBACK
- op op_sput_wide FALLBACK
- op op_sput_object FALLBACK
- op op_sput_boolean FALLBACK
- op op_sput_byte FALLBACK
- op op_sput_char FALLBACK
- op op_sput_short FALLBACK
- op op_invoke_virtual FALLBACK
- op op_invoke_super FALLBACK
- op op_invoke_direct FALLBACK
- op op_invoke_static FALLBACK
- op op_invoke_interface FALLBACK
- op op_return_void_no_barrier FALLBACK
- op op_invoke_virtual_range FALLBACK
- op op_invoke_super_range FALLBACK
- op op_invoke_direct_range FALLBACK
- op op_invoke_static_range FALLBACK
- op op_invoke_interface_range FALLBACK
- op_unused_79 FALLBACK
- op_unused_7a FALLBACK
- op op_neg_int FALLBACK
- op op_not_int FALLBACK
- op op_neg_long FALLBACK
- op op_not_long FALLBACK
- op op_neg_float FALLBACK
- op op_neg_double FALLBACK
- op op_int_to_long FALLBACK
- op op_int_to_float FALLBACK
- op op_int_to_double FALLBACK
- op op_long_to_int FALLBACK
- op op_long_to_float FALLBACK
- op op_long_to_double FALLBACK
- op op_float_to_int FALLBACK
- op op_float_to_long FALLBACK
- op op_float_to_double FALLBACK
- op op_double_to_int FALLBACK
- op op_double_to_long FALLBACK
- op op_double_to_float FALLBACK
- op op_int_to_byte FALLBACK
- op op_int_to_char FALLBACK
- op op_int_to_short FALLBACK
- op op_add_int FALLBACK
- op op_sub_int FALLBACK
- op op_mul_int FALLBACK
- op op_div_int FALLBACK
- op op_rem_int FALLBACK
- op op_and_int FALLBACK
- op op_or_int FALLBACK
- op op_xor_int FALLBACK
- op op_shl_int FALLBACK
- op op_shr_int FALLBACK
- op op_ushr_int FALLBACK
- op op_add_long FALLBACK
- op op_sub_long FALLBACK
- op op_mul_long FALLBACK
- op op_div_long FALLBACK
- op op_rem_long FALLBACK
- op op_and_long FALLBACK
- op op_or_long FALLBACK
- op op_xor_long FALLBACK
- op op_shl_long FALLBACK
- op op_shr_long FALLBACK
- op op_ushr_long FALLBACK
- op op_add_float FALLBACK
- op op_sub_float FALLBACK
- op op_mul_float FALLBACK
- op op_div_float FALLBACK
- op op_rem_float FALLBACK
- op op_add_double FALLBACK
- op op_sub_double FALLBACK
- op op_mul_double FALLBACK
- op op_div_double FALLBACK
- op op_rem_double FALLBACK
- op op_add_int_2addr FALLBACK
- op op_sub_int_2addr FALLBACK
- op op_mul_int_2addr FALLBACK
- op op_div_int_2addr FALLBACK
- op op_rem_int_2addr FALLBACK
- op op_and_int_2addr FALLBACK
- op op_or_int_2addr FALLBACK
- op op_xor_int_2addr FALLBACK
- op op_shl_int_2addr FALLBACK
- op op_shr_int_2addr FALLBACK
- op op_ushr_int_2addr FALLBACK
- op op_add_long_2addr FALLBACK
- op op_sub_long_2addr FALLBACK
- op op_mul_long_2addr FALLBACK
- op op_div_long_2addr FALLBACK
- op op_rem_long_2addr FALLBACK
- op op_and_long_2addr FALLBACK
- op op_or_long_2addr FALLBACK
- op op_xor_long_2addr FALLBACK
- op op_shl_long_2addr FALLBACK
- op op_shr_long_2addr FALLBACK
- op op_ushr_long_2addr FALLBACK
- op op_add_float_2addr FALLBACK
- op op_sub_float_2addr FALLBACK
- op op_mul_float_2addr FALLBACK
- op op_div_float_2addr FALLBACK
- op op_rem_float_2addr FALLBACK
- op op_add_double_2addr FALLBACK
- op op_sub_double_2addr FALLBACK
- op op_mul_double_2addr FALLBACK
- op op_div_double_2addr FALLBACK
- op op_rem_double_2addr FALLBACK
- op op_add_int_lit16 FALLBACK
- op op_rsub_int FALLBACK
- op op_mul_int_lit16 FALLBACK
- op op_div_int_lit16 FALLBACK
- op op_rem_int_lit16 FALLBACK
- op op_and_int_lit16 FALLBACK
- op op_or_int_lit16 FALLBACK
- op op_xor_int_lit16 FALLBACK
- op op_add_int_lit8 FALLBACK
- op op_rsub_int_lit8 FALLBACK
- op op_mul_int_lit8 FALLBACK
- op op_div_int_lit8 FALLBACK
- op op_rem_int_lit8 FALLBACK
- op op_and_int_lit8 FALLBACK
- op op_or_int_lit8 FALLBACK
- op op_xor_int_lit8 FALLBACK
- op op_shl_int_lit8 FALLBACK
- op op_shr_int_lit8 FALLBACK
- op op_ushr_int_lit8 FALLBACK
- op op_iget_quick FALLBACK
- op op_iget_wide_quick FALLBACK
- op op_iget_object_quick FALLBACK
- op op_iput_quick FALLBACK
- op op_iput_wide_quick FALLBACK
- op op_iput_object_quick FALLBACK
- op op_invoke_virtual_quick FALLBACK
- op op_invoke_virtual_range_quick FALLBACK
- op op_iput_boolean_quick FALLBACK
- op op_iput_byte_quick FALLBACK
- op op_iput_char_quick FALLBACK
- op op_iput_short_quick FALLBACK
- op op_iget_boolean_quick FALLBACK
- op op_iget_byte_quick FALLBACK
- op op_iget_char_quick FALLBACK
- op op_iget_short_quick FALLBACK
- op_unused_f3 FALLBACK
- op_unused_f4 FALLBACK
- op_unused_f5 FALLBACK
- op_unused_f6 FALLBACK
- op_unused_f7 FALLBACK
- op_unused_f8 FALLBACK
- op_unused_f9 FALLBACK
- op_unused_fa FALLBACK
- op_unused_fb FALLBACK
- op_unused_fc FALLBACK
- op_unused_fd FALLBACK
- op_unused_fe FALLBACK
- op_unused_ff FALLBACK
+ # op op_nop FALLBACK
+ # op op_move FALLBACK
+ # op op_move_from16 FALLBACK
+ # op op_move_16 FALLBACK
+ # op op_move_wide FALLBACK
+ # op op_move_wide_from16 FALLBACK
+ # op op_move_wide_16 FALLBACK
+ # op op_move_object FALLBACK
+ # op op_move_object_from16 FALLBACK
+ # op op_move_object_16 FALLBACK
+ # op op_move_result FALLBACK
+ # op op_move_result_wide FALLBACK
+ # op op_move_result_object FALLBACK
+ # op op_move_exception FALLBACK
+ # op op_return_void FALLBACK
+ # op op_return FALLBACK
+ # op op_return_wide FALLBACK
+ # op op_return_object FALLBACK
+ # op op_const_4 FALLBACK
+ # op op_const_16 FALLBACK
+ # op op_const FALLBACK
+ # op op_const_high16 FALLBACK
+ # op op_const_wide_16 FALLBACK
+ # op op_const_wide_32 FALLBACK
+ # op op_const_wide FALLBACK
+ # op op_const_wide_high16 FALLBACK
+ # op op_const_string FALLBACK
+ # op op_const_string_jumbo FALLBACK
+ # op op_const_class FALLBACK
+ # op op_monitor_enter FALLBACK
+ # op op_monitor_exit FALLBACK
+ # op op_check_cast FALLBACK
+ # op op_instance_of FALLBACK
+ # op op_array_length FALLBACK
+ # op op_new_instance FALLBACK
+ # op op_new_array FALLBACK
+ # op op_filled_new_array FALLBACK
+ # op op_filled_new_array_range FALLBACK
+ # op op_fill_array_data FALLBACK
+ # op op_throw FALLBACK
+ # op op_goto FALLBACK
+ # op op_goto_16 FALLBACK
+ # op op_goto_32 FALLBACK
+ # op op_packed_switch FALLBACK
+ # op op_sparse_switch FALLBACK
+ # op op_cmpl_float FALLBACK
+ # op op_cmpg_float FALLBACK
+ # op op_cmpl_double FALLBACK
+ # op op_cmpg_double FALLBACK
+ # op op_cmp_long FALLBACK
+ # op op_if_eq FALLBACK
+ # op op_if_ne FALLBACK
+ # op op_if_lt FALLBACK
+ # op op_if_ge FALLBACK
+ # op op_if_gt FALLBACK
+ # op op_if_le FALLBACK
+ # op op_if_eqz FALLBACK
+ # op op_if_nez FALLBACK
+ # op op_if_ltz FALLBACK
+ # op op_if_gez FALLBACK
+ # op op_if_gtz FALLBACK
+ # op op_if_lez FALLBACK
+ # op op_unused_3e FALLBACK
+ # op op_unused_3f FALLBACK
+ # op op_unused_40 FALLBACK
+ # op op_unused_41 FALLBACK
+ # op op_unused_42 FALLBACK
+ # op op_unused_43 FALLBACK
+ # op op_aget FALLBACK
+ # op op_aget_wide FALLBACK
+ # op op_aget_object FALLBACK
+ # op op_aget_boolean FALLBACK
+ # op op_aget_byte FALLBACK
+ # op op_aget_char FALLBACK
+ # op op_aget_short FALLBACK
+ # op op_aput FALLBACK
+ # op op_aput_wide FALLBACK
+ # op op_aput_object FALLBACK
+ # op op_aput_boolean FALLBACK
+ # op op_aput_byte FALLBACK
+ # op op_aput_char FALLBACK
+ # op op_aput_short FALLBACK
+ # op op_iget FALLBACK
+ # op op_iget_wide FALLBACK
+ # op op_iget_object FALLBACK
+ # op op_iget_boolean FALLBACK
+ # op op_iget_byte FALLBACK
+ # op op_iget_char FALLBACK
+ # op op_iget_short FALLBACK
+ # op op_iput FALLBACK
+ # op op_iput_wide FALLBACK
+ # op op_iput_object FALLBACK
+ # op op_iput_boolean FALLBACK
+ # op op_iput_byte FALLBACK
+ # op op_iput_char FALLBACK
+ # op op_iput_short FALLBACK
+ # op op_sget FALLBACK
+ # op op_sget_wide FALLBACK
+ # op op_sget_object FALLBACK
+ # op op_sget_boolean FALLBACK
+ # op op_sget_byte FALLBACK
+ # op op_sget_char FALLBACK
+ # op op_sget_short FALLBACK
+ # op op_sput FALLBACK
+ # op op_sput_wide FALLBACK
+ # op op_sput_object FALLBACK
+ # op op_sput_boolean FALLBACK
+ # op op_sput_byte FALLBACK
+ # op op_sput_char FALLBACK
+ # op op_sput_short FALLBACK
+ # op op_invoke_virtual FALLBACK
+ # op op_invoke_super FALLBACK
+ # op op_invoke_direct FALLBACK
+ # op op_invoke_static FALLBACK
+ # op op_invoke_interface FALLBACK
+ # op op_return_void_no_barrier FALLBACK
+ # op op_invoke_virtual_range FALLBACK
+ # op op_invoke_super_range FALLBACK
+ # op op_invoke_direct_range FALLBACK
+ # op op_invoke_static_range FALLBACK
+ # op op_invoke_interface_range FALLBACK
+ # op op_unused_79 FALLBACK
+ # op op_unused_7a FALLBACK
+ # op op_neg_int FALLBACK
+ # op op_not_int FALLBACK
+ # op op_neg_long FALLBACK
+ # op op_not_long FALLBACK
+ # op op_neg_float FALLBACK
+ # op op_neg_double FALLBACK
+ # op op_int_to_long FALLBACK
+ # op op_int_to_float FALLBACK
+ # op op_int_to_double FALLBACK
+ # op op_long_to_int FALLBACK
+ # op op_long_to_float FALLBACK
+ # op op_long_to_double FALLBACK
+ # op op_float_to_int FALLBACK
+ # op op_float_to_long FALLBACK
+ # op op_float_to_double FALLBACK
+ # op op_double_to_int FALLBACK
+ # op op_double_to_long FALLBACK
+ # op op_double_to_float FALLBACK
+ # op op_int_to_byte FALLBACK
+ # op op_int_to_char FALLBACK
+ # op op_int_to_short FALLBACK
+ # op op_add_int FALLBACK
+ # op op_sub_int FALLBACK
+ # op op_mul_int FALLBACK
+ # op op_div_int FALLBACK
+ # op op_rem_int FALLBACK
+ # op op_and_int FALLBACK
+ # op op_or_int FALLBACK
+ # op op_xor_int FALLBACK
+ # op op_shl_int FALLBACK
+ # op op_shr_int FALLBACK
+ # op op_ushr_int FALLBACK
+ # op op_add_long FALLBACK
+ # op op_sub_long FALLBACK
+ # op op_mul_long FALLBACK
+ # op op_div_long FALLBACK
+ # op op_rem_long FALLBACK
+ # op op_and_long FALLBACK
+ # op op_or_long FALLBACK
+ # op op_xor_long FALLBACK
+ # op op_shl_long FALLBACK
+ # op op_shr_long FALLBACK
+ # op op_ushr_long FALLBACK
+ # op op_add_float FALLBACK
+ # op op_sub_float FALLBACK
+ # op op_mul_float FALLBACK
+ # op op_div_float FALLBACK
+ # op op_rem_float FALLBACK
+ # op op_add_double FALLBACK
+ # op op_sub_double FALLBACK
+ # op op_mul_double FALLBACK
+ # op op_div_double FALLBACK
+ # op op_rem_double FALLBACK
+ # op op_add_int_2addr FALLBACK
+ # op op_sub_int_2addr FALLBACK
+ # op op_mul_int_2addr FALLBACK
+ # op op_div_int_2addr FALLBACK
+ # op op_rem_int_2addr FALLBACK
+ # op op_and_int_2addr FALLBACK
+ # op op_or_int_2addr FALLBACK
+ # op op_xor_int_2addr FALLBACK
+ # op op_shl_int_2addr FALLBACK
+ # op op_shr_int_2addr FALLBACK
+ # op op_ushr_int_2addr FALLBACK
+ # op op_add_long_2addr FALLBACK
+ # op op_sub_long_2addr FALLBACK
+ # op op_mul_long_2addr FALLBACK
+ # op op_div_long_2addr FALLBACK
+ # op op_rem_long_2addr FALLBACK
+ # op op_and_long_2addr FALLBACK
+ # op op_or_long_2addr FALLBACK
+ # op op_xor_long_2addr FALLBACK
+ # op op_shl_long_2addr FALLBACK
+ # op op_shr_long_2addr FALLBACK
+ # op op_ushr_long_2addr FALLBACK
+ # op op_add_float_2addr FALLBACK
+ # op op_sub_float_2addr FALLBACK
+ # op op_mul_float_2addr FALLBACK
+ # op op_div_float_2addr FALLBACK
+ # op op_rem_float_2addr FALLBACK
+ # op op_add_double_2addr FALLBACK
+ # op op_sub_double_2addr FALLBACK
+ # op op_mul_double_2addr FALLBACK
+ # op op_div_double_2addr FALLBACK
+ # op op_rem_double_2addr FALLBACK
+ # op op_add_int_lit16 FALLBACK
+ # op op_rsub_int FALLBACK
+ # op op_mul_int_lit16 FALLBACK
+ # op op_div_int_lit16 FALLBACK
+ # op op_rem_int_lit16 FALLBACK
+ # op op_and_int_lit16 FALLBACK
+ # op op_or_int_lit16 FALLBACK
+ # op op_xor_int_lit16 FALLBACK
+ # op op_add_int_lit8 FALLBACK
+ # op op_rsub_int_lit8 FALLBACK
+ # op op_mul_int_lit8 FALLBACK
+ # op op_div_int_lit8 FALLBACK
+ # op op_rem_int_lit8 FALLBACK
+ # op op_and_int_lit8 FALLBACK
+ # op op_or_int_lit8 FALLBACK
+ # op op_xor_int_lit8 FALLBACK
+ # op op_shl_int_lit8 FALLBACK
+ # op op_shr_int_lit8 FALLBACK
+ # op op_ushr_int_lit8 FALLBACK
+ # op op_iget_quick FALLBACK
+ # op op_iget_wide_quick FALLBACK
+ # op op_iget_object_quick FALLBACK
+ # op op_iput_quick FALLBACK
+ # op op_iput_wide_quick FALLBACK
+ # op op_iput_object_quick FALLBACK
+ # op op_invoke_virtual_quick FALLBACK
+ # op op_invoke_virtual_range_quick FALLBACK
+ # op op_iput_boolean_quick FALLBACK
+ # op op_iput_byte_quick FALLBACK
+ # op op_iput_char_quick FALLBACK
+ # op op_iput_short_quick FALLBACK
+ # op op_iget_boolean_quick FALLBACK
+ # op op_iget_byte_quick FALLBACK
+ # op op_iget_char_quick FALLBACK
+ # op op_iget_short_quick FALLBACK
+ op op_invoke_lambda FALLBACK
+ # op op_unused_f4 FALLBACK
+ op op_capture_variable FALLBACK
+ op op_create_lambda FALLBACK
+ op op_liberate_variable FALLBACK
+ op op_box_lambda FALLBACK
+ op op_unbox_lambda FALLBACK
+ # op op_unused_fa FALLBACK
+ # op op_unused_fb FALLBACK
+ # op op_unused_fc FALLBACK
+ # op op_unused_fd FALLBACK
+ # op op_unused_fe FALLBACK
+ # op op_unused_ff FALLBACK
op-end
# common subroutines for asm
diff --git a/runtime/interpreter/mterp/config_x86_64 b/runtime/interpreter/mterp/config_x86_64
index a002dc2..1d7eb03 100644
--- a/runtime/interpreter/mterp/config_x86_64
+++ b/runtime/interpreter/mterp/config_x86_64
@@ -19,6 +19,10 @@
handler-style computed-goto
handler-size 128
+function-type-format FUNCTION_TYPE(%s)
+function-size-format SIZE(%s,%s)
+global-name-format SYMBOL(%s)
+
# source for alternate entry stub
asm-alt-stub x86_64/alt_stub.S
@@ -36,262 +40,262 @@
# (override example:) op OP_SUB_FLOAT_2ADDR arm-vfp
# (fallback example:) op OP_SUB_FLOAT_2ADDR FALLBACK
- op op_nop FALLBACK
- op op_move FALLBACK
- op op_move_from16 FALLBACK
- op op_move_16 FALLBACK
- op op_move_wide FALLBACK
- op op_move_wide_from16 FALLBACK
- op op_move_wide_16 FALLBACK
- op op_move_object FALLBACK
- op op_move_object_from16 FALLBACK
- op op_move_object_16 FALLBACK
- op op_move_result FALLBACK
- op op_move_result_wide FALLBACK
- op op_move_result_object FALLBACK
- op op_move_exception FALLBACK
- op op_return_void FALLBACK
- op op_return FALLBACK
- op op_return_wide FALLBACK
- op op_return_object FALLBACK
- op op_const_4 FALLBACK
- op op_const_16 FALLBACK
- op op_const FALLBACK
- op op_const_high16 FALLBACK
- op op_const_wide_16 FALLBACK
- op op_const_wide_32 FALLBACK
- op op_const_wide FALLBACK
- op op_const_wide_high16 FALLBACK
- op op_const_string FALLBACK
- op op_const_string_jumbo FALLBACK
- op op_const_class FALLBACK
- op op_monitor_enter FALLBACK
- op op_monitor_exit FALLBACK
- op op_check_cast FALLBACK
- op op_instance_of FALLBACK
- op op_array_length FALLBACK
- op op_new_instance FALLBACK
- op op_new_array FALLBACK
- op op_filled_new_array FALLBACK
- op op_filled_new_array_range FALLBACK
- op op_fill_array_data FALLBACK
- op op_throw FALLBACK
- op op_goto FALLBACK
- op op_goto_16 FALLBACK
- op op_goto_32 FALLBACK
- op op_packed_switch FALLBACK
- op op_sparse_switch FALLBACK
- op op_cmpl_float FALLBACK
- op op_cmpg_float FALLBACK
- op op_cmpl_double FALLBACK
- op op_cmpg_double FALLBACK
- op op_cmp_long FALLBACK
- op op_if_eq FALLBACK
- op op_if_ne FALLBACK
- op op_if_lt FALLBACK
- op op_if_ge FALLBACK
- op op_if_gt FALLBACK
- op op_if_le FALLBACK
- op op_if_eqz FALLBACK
- op op_if_nez FALLBACK
- op op_if_ltz FALLBACK
- op op_if_gez FALLBACK
- op op_if_gtz FALLBACK
- op op_if_lez FALLBACK
- op_unused_3e FALLBACK
- op_unused_3f FALLBACK
- op_unused_40 FALLBACK
- op_unused_41 FALLBACK
- op_unused_42 FALLBACK
- op_unused_43 FALLBACK
- op op_aget FALLBACK
- op op_aget_wide FALLBACK
- op op_aget_object FALLBACK
- op op_aget_boolean FALLBACK
- op op_aget_byte FALLBACK
- op op_aget_char FALLBACK
- op op_aget_short FALLBACK
- op op_aput FALLBACK
- op op_aput_wide FALLBACK
- op op_aput_object FALLBACK
- op op_aput_boolean FALLBACK
- op op_aput_byte FALLBACK
- op op_aput_char FALLBACK
- op op_aput_short FALLBACK
- op op_iget FALLBACK
- op op_iget_wide FALLBACK
- op op_iget_object FALLBACK
- op op_iget_boolean FALLBACK
- op op_iget_byte FALLBACK
- op op_iget_char FALLBACK
- op op_iget_short FALLBACK
- op op_iput FALLBACK
- op op_iput_wide FALLBACK
- op op_iput_object FALLBACK
- op op_iput_boolean FALLBACK
- op op_iput_byte FALLBACK
- op op_iput_char FALLBACK
- op op_iput_short FALLBACK
- op op_sget FALLBACK
- op op_sget_wide FALLBACK
- op op_sget_object FALLBACK
- op op_sget_boolean FALLBACK
- op op_sget_byte FALLBACK
- op op_sget_char FALLBACK
- op op_sget_short FALLBACK
- op op_sput FALLBACK
- op op_sput_wide FALLBACK
- op op_sput_object FALLBACK
- op op_sput_boolean FALLBACK
- op op_sput_byte FALLBACK
- op op_sput_char FALLBACK
- op op_sput_short FALLBACK
- op op_invoke_virtual FALLBACK
- op op_invoke_super FALLBACK
- op op_invoke_direct FALLBACK
- op op_invoke_static FALLBACK
- op op_invoke_interface FALLBACK
- op op_return_void_no_barrier FALLBACK
- op op_invoke_virtual_range FALLBACK
- op op_invoke_super_range FALLBACK
- op op_invoke_direct_range FALLBACK
- op op_invoke_static_range FALLBACK
- op op_invoke_interface_range FALLBACK
- op_unused_79 FALLBACK
- op_unused_7a FALLBACK
- op op_neg_int FALLBACK
- op op_not_int FALLBACK
- op op_neg_long FALLBACK
- op op_not_long FALLBACK
- op op_neg_float FALLBACK
- op op_neg_double FALLBACK
- op op_int_to_long FALLBACK
- op op_int_to_float FALLBACK
- op op_int_to_double FALLBACK
- op op_long_to_int FALLBACK
- op op_long_to_float FALLBACK
- op op_long_to_double FALLBACK
- op op_float_to_int FALLBACK
- op op_float_to_long FALLBACK
- op op_float_to_double FALLBACK
- op op_double_to_int FALLBACK
- op op_double_to_long FALLBACK
- op op_double_to_float FALLBACK
- op op_int_to_byte FALLBACK
- op op_int_to_char FALLBACK
- op op_int_to_short FALLBACK
- op op_add_int FALLBACK
- op op_sub_int FALLBACK
- op op_mul_int FALLBACK
- op op_div_int FALLBACK
- op op_rem_int FALLBACK
- op op_and_int FALLBACK
- op op_or_int FALLBACK
- op op_xor_int FALLBACK
- op op_shl_int FALLBACK
- op op_shr_int FALLBACK
- op op_ushr_int FALLBACK
- op op_add_long FALLBACK
- op op_sub_long FALLBACK
- op op_mul_long FALLBACK
- op op_div_long FALLBACK
- op op_rem_long FALLBACK
- op op_and_long FALLBACK
- op op_or_long FALLBACK
- op op_xor_long FALLBACK
- op op_shl_long FALLBACK
- op op_shr_long FALLBACK
- op op_ushr_long FALLBACK
- op op_add_float FALLBACK
- op op_sub_float FALLBACK
- op op_mul_float FALLBACK
- op op_div_float FALLBACK
- op op_rem_float FALLBACK
- op op_add_double FALLBACK
- op op_sub_double FALLBACK
- op op_mul_double FALLBACK
- op op_div_double FALLBACK
- op op_rem_double FALLBACK
- op op_add_int_2addr FALLBACK
- op op_sub_int_2addr FALLBACK
- op op_mul_int_2addr FALLBACK
- op op_div_int_2addr FALLBACK
- op op_rem_int_2addr FALLBACK
- op op_and_int_2addr FALLBACK
- op op_or_int_2addr FALLBACK
- op op_xor_int_2addr FALLBACK
- op op_shl_int_2addr FALLBACK
- op op_shr_int_2addr FALLBACK
- op op_ushr_int_2addr FALLBACK
- op op_add_long_2addr FALLBACK
- op op_sub_long_2addr FALLBACK
- op op_mul_long_2addr FALLBACK
- op op_div_long_2addr FALLBACK
- op op_rem_long_2addr FALLBACK
- op op_and_long_2addr FALLBACK
- op op_or_long_2addr FALLBACK
- op op_xor_long_2addr FALLBACK
- op op_shl_long_2addr FALLBACK
- op op_shr_long_2addr FALLBACK
- op op_ushr_long_2addr FALLBACK
- op op_add_float_2addr FALLBACK
- op op_sub_float_2addr FALLBACK
- op op_mul_float_2addr FALLBACK
- op op_div_float_2addr FALLBACK
- op op_rem_float_2addr FALLBACK
- op op_add_double_2addr FALLBACK
- op op_sub_double_2addr FALLBACK
- op op_mul_double_2addr FALLBACK
- op op_div_double_2addr FALLBACK
- op op_rem_double_2addr FALLBACK
- op op_add_int_lit16 FALLBACK
- op op_rsub_int FALLBACK
- op op_mul_int_lit16 FALLBACK
- op op_div_int_lit16 FALLBACK
- op op_rem_int_lit16 FALLBACK
- op op_and_int_lit16 FALLBACK
- op op_or_int_lit16 FALLBACK
- op op_xor_int_lit16 FALLBACK
- op op_add_int_lit8 FALLBACK
- op op_rsub_int_lit8 FALLBACK
- op op_mul_int_lit8 FALLBACK
- op op_div_int_lit8 FALLBACK
- op op_rem_int_lit8 FALLBACK
- op op_and_int_lit8 FALLBACK
- op op_or_int_lit8 FALLBACK
- op op_xor_int_lit8 FALLBACK
- op op_shl_int_lit8 FALLBACK
- op op_shr_int_lit8 FALLBACK
- op op_ushr_int_lit8 FALLBACK
- op op_iget_quick FALLBACK
- op op_iget_wide_quick FALLBACK
- op op_iget_object_quick FALLBACK
- op op_iput_quick FALLBACK
- op op_iput_wide_quick FALLBACK
- op op_iput_object_quick FALLBACK
- op op_invoke_virtual_quick FALLBACK
- op op_invoke_virtual_range_quick FALLBACK
- op op_iput_boolean_quick FALLBACK
- op op_iput_byte_quick FALLBACK
- op op_iput_char_quick FALLBACK
- op op_iput_short_quick FALLBACK
- op op_iget_boolean_quick FALLBACK
- op op_iget_byte_quick FALLBACK
- op op_iget_char_quick FALLBACK
- op op_iget_short_quick FALLBACK
- op_unused_f3 FALLBACK
- op_unused_f4 FALLBACK
- op_unused_f5 FALLBACK
- op_unused_f6 FALLBACK
- op_unused_f7 FALLBACK
- op_unused_f8 FALLBACK
- op_unused_f9 FALLBACK
- op_unused_fa FALLBACK
- op_unused_fb FALLBACK
- op_unused_fc FALLBACK
- op_unused_fd FALLBACK
- op_unused_fe FALLBACK
- op_unused_ff FALLBACK
+ # op op_nop FALLBACK
+ # op op_move FALLBACK
+ # op op_move_from16 FALLBACK
+ # op op_move_16 FALLBACK
+ # op op_move_wide FALLBACK
+ # op op_move_wide_from16 FALLBACK
+ # op op_move_wide_16 FALLBACK
+ # op op_move_object FALLBACK
+ # op op_move_object_from16 FALLBACK
+ # op op_move_object_16 FALLBACK
+ # op op_move_result FALLBACK
+ # op op_move_result_wide FALLBACK
+ # op op_move_result_object FALLBACK
+ # op op_move_exception FALLBACK
+ # op op_return_void FALLBACK
+ # op op_return FALLBACK
+ # op op_return_wide FALLBACK
+ # op op_return_object FALLBACK
+ # op op_const_4 FALLBACK
+ # op op_const_16 FALLBACK
+ # op op_const FALLBACK
+ # op op_const_high16 FALLBACK
+ # op op_const_wide_16 FALLBACK
+ # op op_const_wide_32 FALLBACK
+ # op op_const_wide FALLBACK
+ # op op_const_wide_high16 FALLBACK
+ # op op_const_string FALLBACK
+ # op op_const_string_jumbo FALLBACK
+ # op op_const_class FALLBACK
+ # op op_monitor_enter FALLBACK
+ # op op_monitor_exit FALLBACK
+ # op op_check_cast FALLBACK
+ # op op_instance_of FALLBACK
+ # op op_array_length FALLBACK
+ # op op_new_instance FALLBACK
+ # op op_new_array FALLBACK
+ # op op_filled_new_array FALLBACK
+ # op op_filled_new_array_range FALLBACK
+ # op op_fill_array_data FALLBACK
+ # op op_throw FALLBACK
+ # op op_goto FALLBACK
+ # op op_goto_16 FALLBACK
+ # op op_goto_32 FALLBACK
+ # op op_packed_switch FALLBACK
+ # op op_sparse_switch FALLBACK
+ # op op_cmpl_float FALLBACK
+ # op op_cmpg_float FALLBACK
+ # op op_cmpl_double FALLBACK
+ # op op_cmpg_double FALLBACK
+ # op op_cmp_long FALLBACK
+ # op op_if_eq FALLBACK
+ # op op_if_ne FALLBACK
+ # op op_if_lt FALLBACK
+ # op op_if_ge FALLBACK
+ # op op_if_gt FALLBACK
+ # op op_if_le FALLBACK
+ # op op_if_eqz FALLBACK
+ # op op_if_nez FALLBACK
+ # op op_if_ltz FALLBACK
+ # op op_if_gez FALLBACK
+ # op op_if_gtz FALLBACK
+ # op op_if_lez FALLBACK
+ # op op_unused_3e FALLBACK
+ # op op_unused_3f FALLBACK
+ # op op_unused_40 FALLBACK
+ # op op_unused_41 FALLBACK
+ # op op_unused_42 FALLBACK
+ # op op_unused_43 FALLBACK
+ # op op_aget FALLBACK
+ # op op_aget_wide FALLBACK
+ # op op_aget_object FALLBACK
+ # op op_aget_boolean FALLBACK
+ # op op_aget_byte FALLBACK
+ # op op_aget_char FALLBACK
+ # op op_aget_short FALLBACK
+ # op op_aput FALLBACK
+ # op op_aput_wide FALLBACK
+ # op op_aput_object FALLBACK
+ # op op_aput_boolean FALLBACK
+ # op op_aput_byte FALLBACK
+ # op op_aput_char FALLBACK
+ # op op_aput_short FALLBACK
+ # op op_iget FALLBACK
+ # op op_iget_wide FALLBACK
+ # op op_iget_object FALLBACK
+ # op op_iget_boolean FALLBACK
+ # op op_iget_byte FALLBACK
+ # op op_iget_char FALLBACK
+ # op op_iget_short FALLBACK
+ # op op_iput FALLBACK
+ # op op_iput_wide FALLBACK
+ # op op_iput_object FALLBACK
+ # op op_iput_boolean FALLBACK
+ # op op_iput_byte FALLBACK
+ # op op_iput_char FALLBACK
+ # op op_iput_short FALLBACK
+ # op op_sget FALLBACK
+ # op op_sget_wide FALLBACK
+ # op op_sget_object FALLBACK
+ # op op_sget_boolean FALLBACK
+ # op op_sget_byte FALLBACK
+ # op op_sget_char FALLBACK
+ # op op_sget_short FALLBACK
+ # op op_sput FALLBACK
+ # op op_sput_wide FALLBACK
+ # op op_sput_object FALLBACK
+ # op op_sput_boolean FALLBACK
+ # op op_sput_byte FALLBACK
+ # op op_sput_char FALLBACK
+ # op op_sput_short FALLBACK
+ # op op_invoke_virtual FALLBACK
+ # op op_invoke_super FALLBACK
+ # op op_invoke_direct FALLBACK
+ # op op_invoke_static FALLBACK
+ # op op_invoke_interface FALLBACK
+ # op op_return_void_no_barrier FALLBACK
+ # op op_invoke_virtual_range FALLBACK
+ # op op_invoke_super_range FALLBACK
+ # op op_invoke_direct_range FALLBACK
+ # op op_invoke_static_range FALLBACK
+ # op op_invoke_interface_range FALLBACK
+ # op op_unused_79 FALLBACK
+ # op op_unused_7a FALLBACK
+ # op op_neg_int FALLBACK
+ # op op_not_int FALLBACK
+ # op op_neg_long FALLBACK
+ # op op_not_long FALLBACK
+ # op op_neg_float FALLBACK
+ # op op_neg_double FALLBACK
+ # op op_int_to_long FALLBACK
+ # op op_int_to_float FALLBACK
+ # op op_int_to_double FALLBACK
+ # op op_long_to_int FALLBACK
+ # op op_long_to_float FALLBACK
+ # op op_long_to_double FALLBACK
+ # op op_float_to_int FALLBACK
+ # op op_float_to_long FALLBACK
+ # op op_float_to_double FALLBACK
+ # op op_double_to_int FALLBACK
+ # op op_double_to_long FALLBACK
+ # op op_double_to_float FALLBACK
+ # op op_int_to_byte FALLBACK
+ # op op_int_to_char FALLBACK
+ # op op_int_to_short FALLBACK
+ # op op_add_int FALLBACK
+ # op op_sub_int FALLBACK
+ # op op_mul_int FALLBACK
+ # op op_div_int FALLBACK
+ # op op_rem_int FALLBACK
+ # op op_and_int FALLBACK
+ # op op_or_int FALLBACK
+ # op op_xor_int FALLBACK
+ # op op_shl_int FALLBACK
+ # op op_shr_int FALLBACK
+ # op op_ushr_int FALLBACK
+ # op op_add_long FALLBACK
+ # op op_sub_long FALLBACK
+ # op op_mul_long FALLBACK
+ # op op_div_long FALLBACK
+ # op op_rem_long FALLBACK
+ # op op_and_long FALLBACK
+ # op op_or_long FALLBACK
+ # op op_xor_long FALLBACK
+ # op op_shl_long FALLBACK
+ # op op_shr_long FALLBACK
+ # op op_ushr_long FALLBACK
+ # op op_add_float FALLBACK
+ # op op_sub_float FALLBACK
+ # op op_mul_float FALLBACK
+ # op op_div_float FALLBACK
+ # op op_rem_float FALLBACK
+ # op op_add_double FALLBACK
+ # op op_sub_double FALLBACK
+ # op op_mul_double FALLBACK
+ # op op_div_double FALLBACK
+ # op op_rem_double FALLBACK
+ # op op_add_int_2addr FALLBACK
+ # op op_sub_int_2addr FALLBACK
+ # op op_mul_int_2addr FALLBACK
+ # op op_div_int_2addr FALLBACK
+ # op op_rem_int_2addr FALLBACK
+ # op op_and_int_2addr FALLBACK
+ # op op_or_int_2addr FALLBACK
+ # op op_xor_int_2addr FALLBACK
+ # op op_shl_int_2addr FALLBACK
+ # op op_shr_int_2addr FALLBACK
+ # op op_ushr_int_2addr FALLBACK
+ # op op_add_long_2addr FALLBACK
+ # op op_sub_long_2addr FALLBACK
+ # op op_mul_long_2addr FALLBACK
+ # op op_div_long_2addr FALLBACK
+ # op op_rem_long_2addr FALLBACK
+ # op op_and_long_2addr FALLBACK
+ # op op_or_long_2addr FALLBACK
+ # op op_xor_long_2addr FALLBACK
+ # op op_shl_long_2addr FALLBACK
+ # op op_shr_long_2addr FALLBACK
+ # op op_ushr_long_2addr FALLBACK
+ # op op_add_float_2addr FALLBACK
+ # op op_sub_float_2addr FALLBACK
+ # op op_mul_float_2addr FALLBACK
+ # op op_div_float_2addr FALLBACK
+ # op op_rem_float_2addr FALLBACK
+ # op op_add_double_2addr FALLBACK
+ # op op_sub_double_2addr FALLBACK
+ # op op_mul_double_2addr FALLBACK
+ # op op_div_double_2addr FALLBACK
+ # op op_rem_double_2addr FALLBACK
+ # op op_add_int_lit16 FALLBACK
+ # op op_rsub_int FALLBACK
+ # op op_mul_int_lit16 FALLBACK
+ # op op_div_int_lit16 FALLBACK
+ # op op_rem_int_lit16 FALLBACK
+ # op op_and_int_lit16 FALLBACK
+ # op op_or_int_lit16 FALLBACK
+ # op op_xor_int_lit16 FALLBACK
+ # op op_add_int_lit8 FALLBACK
+ # op op_rsub_int_lit8 FALLBACK
+ # op op_mul_int_lit8 FALLBACK
+ # op op_div_int_lit8 FALLBACK
+ # op op_rem_int_lit8 FALLBACK
+ # op op_and_int_lit8 FALLBACK
+ # op op_or_int_lit8 FALLBACK
+ # op op_xor_int_lit8 FALLBACK
+ # op op_shl_int_lit8 FALLBACK
+ # op op_shr_int_lit8 FALLBACK
+ # op op_ushr_int_lit8 FALLBACK
+ # op op_iget_quick FALLBACK
+ # op op_iget_wide_quick FALLBACK
+ # op op_iget_object_quick FALLBACK
+ # op op_iput_quick FALLBACK
+ # op op_iput_wide_quick FALLBACK
+ # op op_iput_object_quick FALLBACK
+ # op op_invoke_virtual_quick FALLBACK
+ # op op_invoke_virtual_range_quick FALLBACK
+ # op op_iput_boolean_quick FALLBACK
+ # op op_iput_byte_quick FALLBACK
+ # op op_iput_char_quick FALLBACK
+ # op op_iput_short_quick FALLBACK
+ # op op_iget_boolean_quick FALLBACK
+ # op op_iget_byte_quick FALLBACK
+ # op op_iget_char_quick FALLBACK
+ # op op_iget_short_quick FALLBACK
+ op op_invoke_lambda FALLBACK
+ # op op_unused_f4 FALLBACK
+ op op_capture_variable FALLBACK
+ op op_create_lambda FALLBACK
+ op op_liberate_variable FALLBACK
+ op op_box_lambda FALLBACK
+ op op_unbox_lambda FALLBACK
+ # op op_unused_fa FALLBACK
+ # op op_unused_fb FALLBACK
+ # op op_unused_fc FALLBACK
+ # op op_unused_fd FALLBACK
+ # op op_unused_fe FALLBACK
+ # op op_unused_ff FALLBACK
op-end
# common subroutines for asm
diff --git a/runtime/interpreter/mterp/mips/alt_stub.S b/runtime/interpreter/mterp/mips/alt_stub.S
new file mode 100644
index 0000000..4598061
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/alt_stub.S
@@ -0,0 +1,13 @@
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (${opnum} * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
diff --git a/runtime/interpreter/mterp/mips/bincmp.S b/runtime/interpreter/mterp/mips/bincmp.S
new file mode 100644
index 0000000..70057f6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/bincmp.S
@@ -0,0 +1,37 @@
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ GET_OPA4(a0) # a0 <- A+
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a3, a1) # a3 <- vB
+ GET_VREG(a2, a0) # a2 <- vA
+ b${revcmp} a2, a3, 1f # branch to 1 if comparison failed
+ FETCH_S(rINST, 1) # rINST<- branch offset, in code units
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a2, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ bgez a2, .L_${opcode}_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+
+%break
+
+.L_${opcode}_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/binop.S b/runtime/interpreter/mterp/mips/binop.S
new file mode 100644
index 0000000..ce09da45
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/binop.S
@@ -0,0 +1,33 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if $chkzero
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO($result, rOBJ, t0) # vAA <- $result
+ /* 11-14 instructions */
diff --git a/runtime/interpreter/mterp/mips/binop2addr.S b/runtime/interpreter/mterp/mips/binop2addr.S
new file mode 100644
index 0000000..548cbcb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/binop2addr.S
@@ -0,0 +1,29 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if $chkzero
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO($result, rOBJ, t0) # vAA <- $result
+ /* 10-13 instructions */
diff --git a/runtime/interpreter/mterp/mips/binopLit16.S b/runtime/interpreter/mterp/mips/binopLit16.S
new file mode 100644
index 0000000..fc0c9ff
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/binopLit16.S
@@ -0,0 +1,30 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if $chkzero
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO($result, rOBJ, t0) # vAA <- $result
+ /* 10-13 instructions */
diff --git a/runtime/interpreter/mterp/mips/binopLit8.S b/runtime/interpreter/mterp/mips/binopLit8.S
new file mode 100644
index 0000000..a591408
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/binopLit8.S
@@ -0,0 +1,31 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if $chkzero
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO($result, rOBJ, t0) # vAA <- $result
+ /* 10-12 instructions */
diff --git a/runtime/interpreter/mterp/mips/binopWide.S b/runtime/interpreter/mterp/mips/binopWide.S
new file mode 100644
index 0000000..608525b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/binopWide.S
@@ -0,0 +1,35 @@
+%default {"preinstr":"", "result0":"a0", "result1":"a1", "chkzero":"0", "arg0":"a0", "arg1":"a1", "arg2":"a2", "arg3":"a3"}
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+ * xor-long
+ *
+ * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64($arg0, $arg1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64($arg2, $arg3, t1) # a2/a3 <- vCC/vCC+1
+ .if $chkzero
+ or t0, $arg2, $arg3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ $preinstr # optional op
+ $instr # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO($result0, $result1, rOBJ, t0) # vAA/vAA+1 <- $result0/$result1
+ /* 14-17 instructions */
diff --git a/runtime/interpreter/mterp/mips/binopWide2addr.S b/runtime/interpreter/mterp/mips/binopWide2addr.S
new file mode 100644
index 0000000..cc92149
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/binopWide2addr.S
@@ -0,0 +1,33 @@
+%default {"preinstr":"", "result0":"a0", "result1":"a1", "chkzero":"0", "arg0":"a0", "arg1":"a1", "arg2":"a2", "arg3":"a3"}
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+ * and-long/2addr, or-long/2addr, xor-long/2addr
+ * rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64($arg2, $arg3, a1) # a2/a3 <- vBB/vBB+1
+ LOAD64($arg0, $arg1, t0) # a0/a1 <- vAA/vAA+1
+ .if $chkzero
+ or t0, $arg2, $arg3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ $preinstr # optional op
+ $instr # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64($result0, $result1, rOBJ) # vAA/vAA+1 <- $result0/$result1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-15 instructions */
diff --git a/runtime/interpreter/mterp/mips/entry.S b/runtime/interpreter/mterp/mips/entry.S
new file mode 100644
index 0000000..cef08fe
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/entry.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Interpreter entry point.
+ */
+
+ .text
+ .align 2
+ .global ExecuteMterpImpl
+ .ent ExecuteMterpImpl
+ .frame sp, STACK_SIZE, ra
+/*
+ * On entry:
+ * a0 Thread* self
+ * a1 code_item
+ * a2 ShadowFrame
+ * a3 JValue* result_register
+ *
+ */
+
+ExecuteMterpImpl:
+ .set noreorder
+ .cpload t9
+ .set reorder
+/* Save to the stack. Frame size = STACK_SIZE */
+ STACK_STORE_FULL()
+/* This directive will make sure all subsequent jal restore gp at a known offset */
+ .cprestore STACK_OFFSET_GP
+
+ /* Remember the return register */
+ sw a3, SHADOWFRAME_RESULT_REGISTER_OFFSET(a2)
+
+ /* Remember the code_item */
+ sw a1, SHADOWFRAME_CODE_ITEM_OFFSET(a2)
+
+ /* set up "named" registers */
+ move rSELF, a0
+ lw a0, SHADOWFRAME_NUMBER_OF_VREGS_OFFSET(a2)
+ addu rFP, a2, SHADOWFRAME_VREGS_OFFSET # point to insns[] (i.e. - the dalivk byte code).
+ EAS2(rREFS, rFP, a0) # point to reference array in shadow frame
+ lw a0, SHADOWFRAME_DEX_PC_OFFSET(a2) # Get starting dex_pc
+ addu rPC, a1, CODEITEM_INSNS_OFFSET # Point to base of insns[]
+ EAS1(rPC, rPC, a0) # Create direct pointer to 1st dex opcode
+
+ EXPORT_PC()
+
+ /* Starting ibase */
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
+
+ /* start executing the instruction at rPC */
+ FETCH_INST() # load rINST from rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* NOTE: no fallthrough */
diff --git a/runtime/interpreter/mterp/mips/fallback.S b/runtime/interpreter/mterp/mips/fallback.S
new file mode 100644
index 0000000..82cbc63
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/fallback.S
@@ -0,0 +1,2 @@
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
diff --git a/runtime/interpreter/mterp/mips/fbinop.S b/runtime/interpreter/mterp/mips/fbinop.S
new file mode 100644
index 0000000..d0d39ae
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/fbinop.S
@@ -0,0 +1,19 @@
+ /*
+ * Generic 32-bit binary float operation.
+ *
+ * For: add-fp, sub-fp, mul-fp, div-fp, rem-fp
+ */
+
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG_F(fa1, a3) # a1 <- vCC
+ GET_VREG_F(fa0, a2) # a0 <- vBB
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ $instr # f0 = result
+ SET_VREG_F(fv0, rOBJ) # vAA <- fv0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/fbinop2addr.S b/runtime/interpreter/mterp/mips/fbinop2addr.S
new file mode 100644
index 0000000..ccb67b1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/fbinop2addr.S
@@ -0,0 +1,19 @@
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr"
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr,
+ * div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # t1 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, rOBJ)
+ GET_VREG_F(fa1, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ $instr
+ SET_VREG_F(fv0, rOBJ) # vAA <- result
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/fbinopWide.S b/runtime/interpreter/mterp/mips/fbinopWide.S
new file mode 100644
index 0000000..3be9325
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/fbinopWide.S
@@ -0,0 +1,28 @@
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * for: add-double, sub-double, mul-double, div-double,
+ * rem-double
+ *
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64_F(fa0, fa0f, a2)
+ LOAD64_F(fa1, fa1f, t1)
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ $instr
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ b .L${opcode}_finish
+%break
+
+.L${opcode}_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/fbinopWide2addr.S b/runtime/interpreter/mterp/mips/fbinopWide2addr.S
new file mode 100644
index 0000000..8541f11
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/fbinopWide2addr.S
@@ -0,0 +1,21 @@
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+ * div-double/2addr, rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64_F(fa0, fa0f, t0)
+ LOAD64_F(fa1, fa1f, a1)
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ $instr
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/footer.S b/runtime/interpreter/mterp/mips/footer.S
new file mode 100644
index 0000000..083dc15
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/footer.S
@@ -0,0 +1,179 @@
+/*
+ * ===========================================================================
+ * Common subroutines and data
+ * ===========================================================================
+ */
+
+ .text
+ .align 2
+
+/*
+ * We've detected a condition that will result in an exception, but the exception
+ * has not yet been thrown. Just bail out to the reference interpreter to deal with it.
+ * TUNING: for consistency, we may want to just go ahead and handle these here.
+ */
+common_errDivideByZero:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogDivideByZeroException)
+#endif
+ b MterpCommonFallback
+
+common_errArrayIndex:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogArrayIndexException)
+#endif
+ b MterpCommonFallback
+
+common_errNegativeArraySize:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogNegativeArraySizeException)
+#endif
+ b MterpCommonFallback
+
+common_errNoSuchMethod:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogNoSuchMethodException)
+#endif
+ b MterpCommonFallback
+
+common_errNullObject:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogNullObjectException)
+#endif
+ b MterpCommonFallback
+
+common_exceptionThrown:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogExceptionThrownException)
+#endif
+ b MterpCommonFallback
+
+MterpSuspendFallback:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ lw a2, THREAD_FLAGS_OFFSET(rSELF)
+ JAL(MterpLogSuspendFallback)
+#endif
+ b MterpCommonFallback
+
+/*
+ * If we're here, something is out of the ordinary. If there is a pending
+ * exception, handle it. Otherwise, roll back and retry with the reference
+ * interpreter.
+ */
+MterpPossibleException:
+ lw a0, THREAD_EXCEPTION_OFFSET(rSELF)
+ beqz a0, MterpFallback # If exception, fall back to reference interpreter.
+ /* intentional fallthrough - handle pending exception. */
+/*
+ * On return from a runtime helper routine, we've found a pending exception.
+ * Can we handle it here - or need to bail out to caller?
+ *
+ */
+MterpException:
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpHandleException) # (self, shadow_frame)
+ beqz v0, MterpExceptionReturn # no local catch, back to caller.
+ lw a0, OFF_FP_CODE_ITEM(rFP)
+ lw a1, OFF_FP_DEX_PC(rFP)
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
+ addu rPC, a0, CODEITEM_INSNS_OFFSET
+ sll a1, a1, 1
+ addu rPC, rPC, a1 # generate new dex_pc_ptr
+ /* Do we need to switch interpreters? */
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ /* resume execution at catch block */
+ EXPORT_PC()
+ FETCH_INST()
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+ /* NOTE: no fallthrough */
+
+/*
+ * Check for suspend check request. Assumes rINST already loaded, rPC advanced and
+ * still needs to get the opcode and branch to it, and flags are in lr.
+ */
+MterpCheckSuspendAndContinue:
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh rIBASE
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ bnez ra, 1f
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+1:
+ EXPORT_PC()
+ move a0, rSELF
+ JAL(MterpSuspendCheck) # (self)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/*
+ * On-stack replacement has happened, and now we've returned from the compiled method.
+ */
+MterpOnStackReplacement:
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpLogOSR)
+#endif
+ li v0, 1 # Signal normal return
+ b MterpDone
+
+/*
+ * Bail out to reference interpreter.
+ */
+MterpFallback:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogFallback)
+#endif
+MterpCommonFallback:
+ move v0, zero # signal retry with reference interpreter.
+ b MterpDone
+/*
+ * We pushed some registers on the stack in ExecuteMterpImpl, then saved
+ * SP and LR. Here we restore SP, restore the registers, and then restore
+ * LR to PC.
+ *
+ * On entry:
+ * uint32_t* rFP (should still be live, pointer to base of vregs)
+ */
+MterpExceptionReturn:
+ li v0, 1 # signal return to caller.
+ b MterpDone
+MterpReturn:
+ lw a2, OFF_FP_RESULT_REGISTER(rFP)
+ sw v0, 0(a2)
+ sw v1, 4(a2)
+ li v0, 1 # signal return to caller.
+MterpDone:
+/* Restore from the stack and return. Frame size = STACK_SIZE */
+ STACK_LOAD_FULL()
+ jalr zero, ra
+
+ .end ExecuteMterpImpl
diff --git a/runtime/interpreter/mterp/mips/funop.S b/runtime/interpreter/mterp/mips/funop.S
new file mode 100644
index 0000000..bfb9346
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/funop.S
@@ -0,0 +1,18 @@
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: int-to-float, float-to-int
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(rOBJ) # t0 <- A+
+ GET_VREG_F(fa0, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ $instr
+
+.L${opcode}_set_vreg_f:
+ SET_VREG_F(fv0, rOBJ)
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ GOTO_OPCODE(t1) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/funopWide.S b/runtime/interpreter/mterp/mips/funopWide.S
new file mode 100644
index 0000000..3d4cf22
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/funopWide.S
@@ -0,0 +1,22 @@
+%default {"preinstr":"", "ld_arg":"LOAD64_F(fa0, fa0f, a3)", "st_result":"SET_VREG64_F(fv0, fv0f, rOBJ)"}
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0/a1".
+ * This could be a MIPS instruction or a function call.
+ *
+ * long-to-double, double-to-long
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # t1 <- A+
+ GET_OPB(a3) # a3 <- B
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ $ld_arg
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # a0/a1 <- op, a2-a3 changed
+
+.L${opcode}_set_vreg:
+ $st_result # vAA <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-13 instructions */
diff --git a/runtime/interpreter/mterp/mips/funopWider.S b/runtime/interpreter/mterp/mips/funopWider.S
new file mode 100644
index 0000000..efb85f3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/funopWider.S
@@ -0,0 +1,19 @@
+%default {"st_result":"SET_VREG64_F(fv0, fv0f, rOBJ)"}
+ /*
+ * Generic 32bit-to-64bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0", where
+ * "result" is a 64-bit quantity in a0/a1.
+ *
+ * For: int-to-double, float-to-long, float-to-double
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ $instr
+
+.L${opcode}_set_vreg:
+ $st_result # vA/vA+1 <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/header.S b/runtime/interpreter/mterp/mips/header.S
new file mode 100644
index 0000000..37ab21d
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/header.S
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ Art assembly interpreter notes:
+
+ First validate assembly code by implementing ExecuteXXXImpl() style body (doesn't
+ handle invoke, allows higher-level code to create frame & shadow frame.
+
+ Once that's working, support direct entry code & eliminate shadow frame (and
+ excess locals allocation.
+
+ Some (hopefully) temporary ugliness. We'll treat rFP as pointing to the
+ base of the vreg array within the shadow frame. Access the other fields,
+ dex_pc_, method_ and number_of_vregs_ via negative offsets. For now, we'll continue
+ the shadow frame mechanism of double-storing object references - via rFP &
+ number_of_vregs_.
+
+ */
+
+#include "asm_support.h"
+
+#if (__mips==32) && (__mips_isa_rev>=2)
+#define MIPS32REVGE2 /* mips32r2 and greater */
+#if (__mips==32) && (__mips_isa_rev>=5)
+#define FPU64 /* 64 bit FPU */
+#if (__mips==32) && (__mips_isa_rev>=6)
+#define MIPS32REVGE6 /* mips32r6 and greater */
+#endif
+#endif
+#endif
+
+/* MIPS definitions and declarations
+
+ reg nick purpose
+ s0 rPC interpreted program counter, used for fetching instructions
+ s1 rFP interpreted frame pointer, used for accessing locals and args
+ s2 rSELF self (Thread) pointer
+ s3 rIBASE interpreted instruction base pointer, used for computed goto
+ s4 rINST first 16-bit code unit of current instruction
+ s6 rREFS base of object references in shadow frame (ideally, we'll get rid of this later).
+*/
+
+/* single-purpose registers, given names for clarity */
+#define rPC s0
+#define rFP s1
+#define rSELF s2
+#define rIBASE s3
+#define rINST s4
+#define rOBJ s5
+#define rREFS s6
+#define rTEMP s7
+
+#define rARG0 a0
+#define rARG1 a1
+#define rARG2 a2
+#define rARG3 a3
+#define rRESULT0 v0
+#define rRESULT1 v1
+
+/* GP register definitions */
+#define zero $$0 /* always zero */
+#define AT $$at /* assembler temp */
+#define v0 $$2 /* return value */
+#define v1 $$3
+#define a0 $$4 /* argument registers */
+#define a1 $$5
+#define a2 $$6
+#define a3 $$7
+#define t0 $$8 /* temp registers (not saved across subroutine calls) */
+#define t1 $$9
+#define t2 $$10
+#define t3 $$11
+#define t4 $$12
+#define t5 $$13
+#define t6 $$14
+#define t7 $$15
+#define ta0 $$12 /* alias */
+#define ta1 $$13
+#define ta2 $$14
+#define ta3 $$15
+#define s0 $$16 /* saved across subroutine calls (callee saved) */
+#define s1 $$17
+#define s2 $$18
+#define s3 $$19
+#define s4 $$20
+#define s5 $$21
+#define s6 $$22
+#define s7 $$23
+#define t8 $$24 /* two more temp registers */
+#define t9 $$25
+#define k0 $$26 /* kernel temporary */
+#define k1 $$27
+#define gp $$28 /* global pointer */
+#define sp $$29 /* stack pointer */
+#define s8 $$30 /* one more callee saved */
+#define ra $$31 /* return address */
+
+/* FP register definitions */
+#define fv0 $$f0
+#define fv0f $$f1
+#define fv1 $$f2
+#define fv1f $$f3
+#define fa0 $$f12
+#define fa0f $$f13
+#define fa1 $$f14
+#define fa1f $$f15
+#define ft0 $$f4
+#define ft0f $$f5
+#define ft1 $$f6
+#define ft1f $$f7
+#define ft2 $$f8
+#define ft2f $$f9
+#define ft3 $$f10
+#define ft3f $$f11
+#define ft4 $$f16
+#define ft4f $$f17
+#define ft5 $$f18
+#define ft5f $$f19
+#define fs0 $$f20
+#define fs0f $$f21
+#define fs1 $$f22
+#define fs1f $$f23
+#define fs2 $$f24
+#define fs2f $$f25
+#define fs3 $$f26
+#define fs3f $$f27
+#define fs4 $$f28
+#define fs4f $$f29
+#define fs5 $$f30
+#define fs5f $$f31
+
+#ifndef MIPS32REVGE6
+#define fcc0 $$fcc0
+#define fcc1 $$fcc1
+#endif
+
+/*
+ * Instead of holding a pointer to the shadow frame, we keep rFP at the base of the vregs. So,
+ * to access other shadow frame fields, we need to use a backwards offset. Define those here.
+ */
+#define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET)
+#define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET)
+#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET)
+#define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET)
+#define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET)
+#define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET)
+#define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET)
+#define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET)
+#define OFF_FP_SHADOWFRAME (-SHADOWFRAME_VREGS_OFFSET)
+
+#define MTERP_PROFILE_BRANCHES 1
+#define MTERP_LOGGING 0
+
+/*
+ * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must
+ * be done *before* something throws.
+ *
+ * It's okay to do this more than once.
+ *
+ * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped
+ * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction
+ * offset into the code_items_[] array. For effiency, we will "export" the
+ * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC
+ * to convert to a dex pc when needed.
+ */
+#define EXPORT_PC() \
+ sw rPC, OFF_FP_DEX_PC_PTR(rFP)
+
+#define EXPORT_DEX_PC(tmp) \
+ lw tmp, OFF_FP_CODE_ITEM(rFP) \
+ sw rPC, OFF_FP_DEX_PC_PTR(rFP) \
+ addu tmp, CODEITEM_INSNS_OFFSET \
+ subu tmp, rPC, tmp \
+ sra tmp, tmp, 1 \
+ sw tmp, OFF_FP_DEX_PC(rFP)
+
+/*
+ * Fetch the next instruction from rPC into rINST. Does not advance rPC.
+ */
+#define FETCH_INST() lhu rINST, (rPC)
+
+/*
+ * Fetch the next instruction from the specified offset. Advances rPC
+ * to point to the next instruction. "_count" is in 16-bit code units.
+ *
+ * This must come AFTER anything that can throw an exception, or the
+ * exception catch may miss. (This also implies that it must come after
+ * EXPORT_PC().)
+ */
+#define FETCH_ADVANCE_INST(_count) lhu rINST, ((_count)*2)(rPC); \
+ addu rPC, rPC, ((_count) * 2)
+
+/*
+ * The operation performed here is similar to FETCH_ADVANCE_INST, except the
+ * src and dest registers are parameterized (not hard-wired to rPC and rINST).
+ */
+#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
+ lhu _dreg, ((_count)*2)(_sreg) ; \
+ addu _sreg, _sreg, (_count)*2
+
+/*
+ * Similar to FETCH_ADVANCE_INST, but does not update rPC. Used to load
+ * rINST ahead of possible exception point. Be sure to manually advance rPC
+ * later.
+ */
+#define PREFETCH_INST(_count) lhu rINST, ((_count)*2)(rPC)
+
+/* Advance rPC by some number of code units. */
+#define ADVANCE(_count) addu rPC, rPC, ((_count) * 2)
+
+/*
+ * Fetch the next instruction from an offset specified by rd. Updates
+ * rPC to point to the next instruction. "rd" must specify the distance
+ * in bytes, *not* 16-bit code units, and may be a signed value.
+ */
+#define FETCH_ADVANCE_INST_RB(rd) addu rPC, rPC, rd; \
+ lhu rINST, (rPC)
+
+/*
+ * Fetch a half-word code unit from an offset past the current PC. The
+ * "_count" value is in 16-bit code units. Does not advance rPC.
+ *
+ * The "_S" variant works the same but treats the value as signed.
+ */
+#define FETCH(rd, _count) lhu rd, ((_count) * 2)(rPC)
+#define FETCH_S(rd, _count) lh rd, ((_count) * 2)(rPC)
+
+/*
+ * Fetch one byte from an offset past the current PC. Pass in the same
+ * "_count" as you would for FETCH, and an additional 0/1 indicating which
+ * byte of the halfword you want (lo/hi).
+ */
+#define FETCH_B(rd, _count, _byte) lbu rd, ((_count) * 2 + _byte)(rPC)
+
+/*
+ * Put the instruction's opcode field into the specified register.
+ */
+#define GET_INST_OPCODE(rd) and rd, rINST, 0xFF
+
+/*
+ * Put the prefetched instruction's opcode field into the specified register.
+ */
+#define GET_PREFETCHED_OPCODE(dreg, sreg) andi dreg, sreg, 255
+
+/*
+ * Begin executing the opcode in rd.
+ */
+#define GOTO_OPCODE(rd) sll rd, rd, ${handler_size_bits}; \
+ addu rd, rIBASE, rd; \
+ jalr zero, rd
+
+#define GOTO_OPCODE_BASE(_base, rd) sll rd, rd, ${handler_size_bits}; \
+ addu rd, _base, rd; \
+ jalr zero, rd
+
+/*
+ * Get/set the 32-bit value from a Dalvik register.
+ */
+#define GET_VREG(rd, rix) LOAD_eas2(rd, rFP, rix)
+
+#define GET_VREG_F(rd, rix) EAS2(AT, rFP, rix); \
+ .set noat; l.s rd, (AT); .set at
+
+#define SET_VREG(rd, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rd, 0(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8)
+
+#define SET_VREG64(rlo, rhi, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rlo, 0(t8); \
+ sw rhi, 4(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8); \
+ sw zero, 4(t8)
+
+#ifdef FPU64
+#define SET_VREG64_F(rlo, rhi, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rREFS, AT; \
+ sw zero, 0(t8); \
+ sw zero, 4(t8); \
+ addu t8, rFP, AT; \
+ mfhc1 AT, rlo; \
+ sw AT, 4(t8); \
+ .set at; \
+ s.s rlo, 0(t8)
+#else
+#define SET_VREG64_F(rlo, rhi, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ s.s rlo, 0(t8); \
+ s.s rhi, 4(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8); \
+ sw zero, 4(t8)
+#endif
+
+#define SET_VREG_OBJECT(rd, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rd, 0(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw rd, 0(t8)
+
+/* Combination of the SET_VREG and GOTO_OPCODE functions to save 1 instruction */
+#define SET_VREG_GOTO(rd, rix, dst) .set noreorder; \
+ sll dst, dst, ${handler_size_bits}; \
+ addu dst, rIBASE, dst; \
+ .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rd, 0(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ jalr zero, dst; \
+ sw zero, 0(t8); \
+ .set reorder
+
+/* Combination of the SET_VREG64 and GOTO_OPCODE functions to save 1 instruction */
+#define SET_VREG64_GOTO(rlo, rhi, rix, dst) .set noreorder; \
+ sll dst, dst, ${handler_size_bits}; \
+ addu dst, rIBASE, dst; \
+ .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rlo, 0(t8); \
+ sw rhi, 4(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8); \
+ jalr zero, dst; \
+ sw zero, 4(t8); \
+ .set reorder
+
+#define SET_VREG_F(rd, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ s.s rd, 0(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8)
+
+#define GET_OPA(rd) srl rd, rINST, 8
+#ifdef MIPS32REVGE2
+#define GET_OPA4(rd) ext rd, rINST, 8, 4
+#else
+#define GET_OPA4(rd) GET_OPA(rd); and rd, 0xf
+#endif
+#define GET_OPB(rd) srl rd, rINST, 12
+
+/*
+ * Form an Effective Address rd = rbase + roff<<n;
+ * Uses reg AT
+ */
+#define EASN(rd, rbase, roff, rshift) .set noat; \
+ sll AT, roff, rshift; \
+ addu rd, rbase, AT; \
+ .set at
+
+#define EAS1(rd, rbase, roff) EASN(rd, rbase, roff, 1)
+#define EAS2(rd, rbase, roff) EASN(rd, rbase, roff, 2)
+#define EAS3(rd, rbase, roff) EASN(rd, rbase, roff, 3)
+#define EAS4(rd, rbase, roff) EASN(rd, rbase, roff, 4)
+
+/*
+ * Form an Effective Shift Right rd = rbase + roff>>n;
+ * Uses reg AT
+ */
+#define ESRN(rd, rbase, roff, rshift) .set noat; \
+ srl AT, roff, rshift; \
+ addu rd, rbase, AT; \
+ .set at
+
+#define LOAD_eas2(rd, rbase, roff) EAS2(AT, rbase, roff); \
+ .set noat; lw rd, 0(AT); .set at
+
+#define STORE_eas2(rd, rbase, roff) EAS2(AT, rbase, roff); \
+ .set noat; sw rd, 0(AT); .set at
+
+#define LOAD_RB_OFF(rd, rbase, off) lw rd, off(rbase)
+#define STORE_RB_OFF(rd, rbase, off) sw rd, off(rbase)
+
+#define STORE64_off(rlo, rhi, rbase, off) sw rlo, off(rbase); \
+ sw rhi, (off+4)(rbase)
+#define LOAD64_off(rlo, rhi, rbase, off) lw rlo, off(rbase); \
+ lw rhi, (off+4)(rbase)
+
+#define STORE64(rlo, rhi, rbase) STORE64_off(rlo, rhi, rbase, 0)
+#define LOAD64(rlo, rhi, rbase) LOAD64_off(rlo, rhi, rbase, 0)
+
+#ifdef FPU64
+#define STORE64_off_F(rlo, rhi, rbase, off) s.s rlo, off(rbase); \
+ .set noat; \
+ mfhc1 AT, rlo; \
+ sw AT, (off+4)(rbase); \
+ .set at
+#define LOAD64_off_F(rlo, rhi, rbase, off) l.s rlo, off(rbase); \
+ .set noat; \
+ lw AT, (off+4)(rbase); \
+ mthc1 AT, rlo; \
+ .set at
+#else
+#define STORE64_off_F(rlo, rhi, rbase, off) s.s rlo, off(rbase); \
+ s.s rhi, (off+4)(rbase)
+#define LOAD64_off_F(rlo, rhi, rbase, off) l.s rlo, off(rbase); \
+ l.s rhi, (off+4)(rbase)
+#endif
+
+#define STORE64_F(rlo, rhi, rbase) STORE64_off_F(rlo, rhi, rbase, 0)
+#define LOAD64_F(rlo, rhi, rbase) LOAD64_off_F(rlo, rhi, rbase, 0)
+
+
+#define LOAD_base_offMirrorArray_length(rd, rbase) LOAD_RB_OFF(rd, rbase, MIRROR_ARRAY_LENGTH_OFFSET)
+
+#define STACK_STORE(rd, off) sw rd, off(sp)
+#define STACK_LOAD(rd, off) lw rd, off(sp)
+#define CREATE_STACK(n) subu sp, sp, n
+#define DELETE_STACK(n) addu sp, sp, n
+
+#define LOAD_ADDR(dest, addr) la dest, addr
+#define LOAD_IMM(dest, imm) li dest, imm
+#define MOVE_REG(dest, src) move dest, src
+#define STACK_SIZE 128
+
+#define STACK_OFFSET_ARG04 16
+#define STACK_OFFSET_ARG05 20
+#define STACK_OFFSET_ARG06 24
+#define STACK_OFFSET_ARG07 28
+#define STACK_OFFSET_GP 84
+
+#define JAL(n) jal n
+#define BAL(n) bal n
+
+/*
+ * FP register usage restrictions:
+ * 1) We don't use the callee save FP registers so we don't have to save them.
+ * 2) We don't use the odd FP registers so we can share code with mips32r6.
+ */
+#define STACK_STORE_FULL() CREATE_STACK(STACK_SIZE); \
+ STACK_STORE(ra, 124); \
+ STACK_STORE(s8, 120); \
+ STACK_STORE(s0, 116); \
+ STACK_STORE(s1, 112); \
+ STACK_STORE(s2, 108); \
+ STACK_STORE(s3, 104); \
+ STACK_STORE(s4, 100); \
+ STACK_STORE(s5, 96); \
+ STACK_STORE(s6, 92); \
+ STACK_STORE(s7, 88);
+
+#define STACK_LOAD_FULL() STACK_LOAD(gp, STACK_OFFSET_GP); \
+ STACK_LOAD(s7, 88); \
+ STACK_LOAD(s6, 92); \
+ STACK_LOAD(s5, 96); \
+ STACK_LOAD(s4, 100); \
+ STACK_LOAD(s3, 104); \
+ STACK_LOAD(s2, 108); \
+ STACK_LOAD(s1, 112); \
+ STACK_LOAD(s0, 116); \
+ STACK_LOAD(s8, 120); \
+ STACK_LOAD(ra, 124); \
+ DELETE_STACK(STACK_SIZE)
diff --git a/runtime/interpreter/mterp/mips/invoke.S b/runtime/interpreter/mterp/mips/invoke.S
new file mode 100644
index 0000000..bcd3a57
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/invoke.S
@@ -0,0 +1,19 @@
+%default { "helper":"UndefinedInvokeHandler" }
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern $helper
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL($helper)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
diff --git a/runtime/interpreter/mterp/mips/op_add_double.S b/runtime/interpreter/mterp/mips/op_add_double.S
new file mode 100644
index 0000000..12ef0cf3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_double.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide.S" {"instr":"add.d fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_add_double_2addr.S b/runtime/interpreter/mterp/mips/op_add_double_2addr.S
new file mode 100644
index 0000000..c57add5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_double_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide2addr.S" {"instr":"add.d fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_add_float.S b/runtime/interpreter/mterp/mips/op_add_float.S
new file mode 100644
index 0000000..6a46cf0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_float.S
@@ -0,0 +1 @@
+%include "mips/fbinop.S" {"instr":"add.s fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_add_float_2addr.S b/runtime/interpreter/mterp/mips/op_add_float_2addr.S
new file mode 100644
index 0000000..6ab5cc1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_float_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinop2addr.S" {"instr":"add.s fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_add_int.S b/runtime/interpreter/mterp/mips/op_add_int.S
new file mode 100644
index 0000000..53a0cb1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_int.S
@@ -0,0 +1 @@
+%include "mips/binop.S" {"instr":"addu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_add_int_2addr.S b/runtime/interpreter/mterp/mips/op_add_int_2addr.S
new file mode 100644
index 0000000..ddd9214
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_int_2addr.S
@@ -0,0 +1 @@
+%include "mips/binop2addr.S" {"instr":"addu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_add_int_lit16.S b/runtime/interpreter/mterp/mips/op_add_int_lit16.S
new file mode 100644
index 0000000..05535c1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_int_lit16.S
@@ -0,0 +1 @@
+%include "mips/binopLit16.S" {"instr":"addu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_add_int_lit8.S b/runtime/interpreter/mterp/mips/op_add_int_lit8.S
new file mode 100644
index 0000000..fd021b3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_int_lit8.S
@@ -0,0 +1 @@
+%include "mips/binopLit8.S" {"instr":"addu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_add_long.S b/runtime/interpreter/mterp/mips/op_add_long.S
new file mode 100644
index 0000000..faacc6a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_long.S
@@ -0,0 +1,9 @@
+/*
+ * The compiler generates the following sequence for
+ * [v1 v0] = [a1 a0] + [a3 a2];
+ * addu v0,a2,a0
+ * addu a1,a3,a1
+ * sltu v1,v0,a2
+ * addu v1,v1,a1
+ */
+%include "mips/binopWide.S" { "result0":"v0", "result1":"v1", "preinstr":"addu v0, a2, a0", "instr":"addu a1, a3, a1; sltu v1, v0, a2; addu v1, v1, a1" }
diff --git a/runtime/interpreter/mterp/mips/op_add_long_2addr.S b/runtime/interpreter/mterp/mips/op_add_long_2addr.S
new file mode 100644
index 0000000..bf827c1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_add_long_2addr.S
@@ -0,0 +1,4 @@
+/*
+ * See op_add_long.S for details
+ */
+%include "mips/binopWide2addr.S" { "result0":"v0", "result1":"v1", "preinstr":"addu v0, a2, a0", "instr":"addu a1, a3, a1; sltu v1, v0, a2; addu v1, v1, a1" }
diff --git a/runtime/interpreter/mterp/mips/op_aget.S b/runtime/interpreter/mterp/mips/op_aget.S
new file mode 100644
index 0000000..8aa8992
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aget.S
@@ -0,0 +1,32 @@
+%default { "load":"lw", "shift":"2", "data_offset":"MIRROR_INT_ARRAY_DATA_OFFSET" }
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+ * instructions. We use a pair of FETCH_Bs instead.
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if $shift
+ EASN(a0, a0, a1, $shift) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ # a1 >= a3; compare unsigned index
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ $load a2, $data_offset(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a2, rOBJ, t0) # vAA <- a2
diff --git a/runtime/interpreter/mterp/mips/op_aget_boolean.S b/runtime/interpreter/mterp/mips/op_aget_boolean.S
new file mode 100644
index 0000000..59f7f82
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aget_boolean.S
@@ -0,0 +1 @@
+%include "mips/op_aget.S" { "load":"lbu", "shift":"0", "data_offset":"MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips/op_aget_byte.S b/runtime/interpreter/mterp/mips/op_aget_byte.S
new file mode 100644
index 0000000..11038fa
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aget_byte.S
@@ -0,0 +1 @@
+%include "mips/op_aget.S" { "load":"lb", "shift":"0", "data_offset":"MIRROR_BYTE_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips/op_aget_char.S b/runtime/interpreter/mterp/mips/op_aget_char.S
new file mode 100644
index 0000000..96f2ab6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aget_char.S
@@ -0,0 +1 @@
+%include "mips/op_aget.S" { "load":"lhu", "shift":"1", "data_offset":"MIRROR_CHAR_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips/op_aget_object.S b/runtime/interpreter/mterp/mips/op_aget_object.S
new file mode 100644
index 0000000..e3ab9d8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aget_object.S
@@ -0,0 +1,20 @@
+ /*
+ * Array object get. vAA <- vBB[vCC].
+ *
+ * for: aget-object
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ EXPORT_PC()
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ JAL(artAGetObjectFromMterp) # v0 <- GetObj(array, index)
+ lw a1, THREAD_EXCEPTION_OFFSET(rSELF)
+ PREFETCH_INST(2) # load rINST
+ bnez a1, MterpException
+ SET_VREG_OBJECT(v0, rOBJ) # vAA <- v0
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_aget_short.S b/runtime/interpreter/mterp/mips/op_aget_short.S
new file mode 100644
index 0000000..cd7f7bf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aget_short.S
@@ -0,0 +1 @@
+%include "mips/op_aget.S" { "load":"lh", "shift":"1", "data_offset":"MIRROR_SHORT_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips/op_aget_wide.S b/runtime/interpreter/mterp/mips/op_aget_wide.S
new file mode 100644
index 0000000..08822f5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aget_wide.S
@@ -0,0 +1,22 @@
+ /*
+ * Array get, 64 bits. vAA <- vBB[vCC].
+ *
+ * Arrays of long/double are 64-bit aligned.
+ */
+ /* aget-wide vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ EAS3(a0, a0, a1) # a0 <- arrayObj + index*width
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ LOAD64_off(a2, a3, a0, MIRROR_WIDE_ARRAY_DATA_OFFSET)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO(a2, a3, rOBJ, t0) # vAA/vAA+1 <- a2/a3
diff --git a/runtime/interpreter/mterp/mips/op_and_int.S b/runtime/interpreter/mterp/mips/op_and_int.S
new file mode 100644
index 0000000..98fe4af
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_and_int.S
@@ -0,0 +1 @@
+%include "mips/binop.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_and_int_2addr.S b/runtime/interpreter/mterp/mips/op_and_int_2addr.S
new file mode 100644
index 0000000..7f90ed4
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_and_int_2addr.S
@@ -0,0 +1 @@
+%include "mips/binop2addr.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_and_int_lit16.S b/runtime/interpreter/mterp/mips/op_and_int_lit16.S
new file mode 100644
index 0000000..e46f23b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_and_int_lit16.S
@@ -0,0 +1 @@
+%include "mips/binopLit16.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_and_int_lit8.S b/runtime/interpreter/mterp/mips/op_and_int_lit8.S
new file mode 100644
index 0000000..3332883
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_and_int_lit8.S
@@ -0,0 +1 @@
+%include "mips/binopLit8.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_and_long.S b/runtime/interpreter/mterp/mips/op_and_long.S
new file mode 100644
index 0000000..a98a6df
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_and_long.S
@@ -0,0 +1 @@
+%include "mips/binopWide.S" {"preinstr":"and a0, a0, a2", "instr":"and a1, a1, a3"}
diff --git a/runtime/interpreter/mterp/mips/op_and_long_2addr.S b/runtime/interpreter/mterp/mips/op_and_long_2addr.S
new file mode 100644
index 0000000..350c044
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_and_long_2addr.S
@@ -0,0 +1 @@
+%include "mips/binopWide2addr.S" {"preinstr":"and a0, a0, a2", "instr":"and a1, a1, a3"}
diff --git a/runtime/interpreter/mterp/mips/op_aput.S b/runtime/interpreter/mterp/mips/op_aput.S
new file mode 100644
index 0000000..53d6ae0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aput.S
@@ -0,0 +1,30 @@
+%default { "store":"sw", "shift":"2", "data_offset":"MIRROR_INT_ARRAY_DATA_OFFSET" }
+
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if $shift
+ EASN(a0, a0, a1, $shift) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_VREG(a2, rOBJ) # a2 <- vAA
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ $store a2, $data_offset(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_aput_boolean.S b/runtime/interpreter/mterp/mips/op_aput_boolean.S
new file mode 100644
index 0000000..9cae5ef
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aput_boolean.S
@@ -0,0 +1 @@
+%include "mips/op_aput.S" { "store":"sb", "shift":"0", "data_offset":"MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips/op_aput_byte.S b/runtime/interpreter/mterp/mips/op_aput_byte.S
new file mode 100644
index 0000000..3bbd12c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aput_byte.S
@@ -0,0 +1 @@
+%include "mips/op_aput.S" { "store":"sb", "shift":"0", "data_offset":"MIRROR_BYTE_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips/op_aput_char.S b/runtime/interpreter/mterp/mips/op_aput_char.S
new file mode 100644
index 0000000..ae69717
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aput_char.S
@@ -0,0 +1 @@
+%include "mips/op_aput.S" { "store":"sh", "shift":"1", "data_offset":"MIRROR_CHAR_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips/op_aput_object.S b/runtime/interpreter/mterp/mips/op_aput_object.S
new file mode 100644
index 0000000..55b13b1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aput_object.S
@@ -0,0 +1,14 @@
+ /*
+ * Store an object into an array. vBB[vCC] <- vAA.
+ *
+ */
+ /* op vAA, vBB, vCC */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ JAL(MterpAputObject)
+ beqz v0, MterpPossibleException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_aput_short.S b/runtime/interpreter/mterp/mips/op_aput_short.S
new file mode 100644
index 0000000..9586259
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aput_short.S
@@ -0,0 +1 @@
+%include "mips/op_aput.S" { "store":"sh", "shift":"1", "data_offset":"MIRROR_SHORT_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips/op_aput_wide.S b/runtime/interpreter/mterp/mips/op_aput_wide.S
new file mode 100644
index 0000000..ef99261
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_aput_wide.S
@@ -0,0 +1,25 @@
+ /*
+ * Array put, 64 bits. vBB[vCC] <- vAA.
+ *
+ * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
+ */
+ /* aput-wide vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(t0) # t0 <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ EAS3(a0, a0, a1) # a0 <- arrayObj + index*width
+ EAS2(rOBJ, rFP, t0) # rOBJ <- &fp[AA]
+ # compare unsigned index, length
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ LOAD64(a2, a3, rOBJ) # a2/a3 <- vAA/vAA+1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ STORE64_off(a2, a3, a0, MIRROR_WIDE_ARRAY_DATA_OFFSET) # a2/a3 <- vBB[vCC]
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_array_length.S b/runtime/interpreter/mterp/mips/op_array_length.S
new file mode 100644
index 0000000..2b4a86f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_array_length.S
@@ -0,0 +1,12 @@
+ /*
+ * Return the length of an array.
+ */
+ GET_OPB(a1) # a1 <- B
+ GET_OPA4(a2) # a2 <- A+
+ GET_VREG(a0, a1) # a0 <- vB (object ref)
+ # is object null?
+ beqz a0, common_errNullObject # yup, fail
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- array length
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a3, a2, t0) # vA <- length
diff --git a/runtime/interpreter/mterp/mips/op_check_cast.S b/runtime/interpreter/mterp/mips/op_check_cast.S
new file mode 100644
index 0000000..9a6cefa
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_check_cast.S
@@ -0,0 +1,16 @@
+ /*
+ * Check to see if a cast from one class to another is allowed.
+ */
+ # check-cast vAA, class /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- BBBB
+ GET_OPA(a1) # a1 <- AA
+ EAS2(a1, rFP, a1) # a1 <- &object
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ JAL(MterpCheckCast) # v0 <- CheckCast(index, &obj, method, self)
+ PREFETCH_INST(2)
+ bnez v0, MterpPossibleException
+ ADVANCE(2)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_cmp_long.S b/runtime/interpreter/mterp/mips/op_cmp_long.S
new file mode 100644
index 0000000..44806c3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_cmp_long.S
@@ -0,0 +1,34 @@
+ /*
+ * Compare two 64-bit values
+ * x = y return 0
+ * x < y return -1
+ * x > y return 1
+ *
+ * I think I can improve on the ARM code by the following observation
+ * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
+ * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
+ * subu v0, t0, t1 # v0= -1:1:0 for [ < > = ]
+ */
+ /* cmp-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(a3, rFP, a3) # a3 <- &fp[CC]
+ LOAD64(a0, a1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64(a2, a3, a3) # a2/a3 <- vCC/vCC+1
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ slt t0, a1, a3 # compare hi
+ sgt t1, a1, a3
+ subu v0, t1, t0 # v0 <- (-1, 1, 0)
+ bnez v0, .L${opcode}_finish
+ # at this point x.hi==y.hi
+ sltu t0, a0, a2 # compare lo
+ sgtu t1, a0, a2
+ subu v0, t1, t0 # v0 <- (-1, 1, 0) for [< > =]
+
+.L${opcode}_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(v0, rOBJ, t0) # vAA <- v0
diff --git a/runtime/interpreter/mterp/mips/op_cmpg_double.S b/runtime/interpreter/mterp/mips/op_cmpg_double.S
new file mode 100644
index 0000000..e7965a7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_cmpg_double.S
@@ -0,0 +1 @@
+%include "mips/op_cmpl_double.S" { "naninst":"li rTEMP, 1" }
diff --git a/runtime/interpreter/mterp/mips/op_cmpg_float.S b/runtime/interpreter/mterp/mips/op_cmpg_float.S
new file mode 100644
index 0000000..53519a6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_cmpg_float.S
@@ -0,0 +1 @@
+%include "mips/op_cmpl_float.S" { "naninst":"li rTEMP, 1" }
diff --git a/runtime/interpreter/mterp/mips/op_cmpl_double.S b/runtime/interpreter/mterp/mips/op_cmpl_double.S
new file mode 100644
index 0000000..5a47fd7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_cmpl_double.S
@@ -0,0 +1,54 @@
+%default { "naninst":"li rTEMP, -1" }
+ /*
+ * Compare two floating-point values. Puts 0(==), 1(>), or -1(<)
+ * into the destination register (rTEMP) based on the comparison results.
+ *
+ * Provide a "naninst" instruction that puts 1 or -1 into rTEMP depending
+ * on what value we'd like to return when one of the operands is NaN.
+ *
+ * See op_cmpl_float for more details.
+ *
+ * For: cmpl-double, cmpg-double
+ */
+ /* op vAA, vBB, vCC */
+
+ FETCH(a0, 1) # a0 <- CCBB
+ and rOBJ, a0, 255 # s5 <- BB
+ srl t0, a0, 8 # t0 <- CC
+ EAS2(rOBJ, rFP, rOBJ) # s5 <- &fp[BB]
+ EAS2(t0, rFP, t0) # t0 <- &fp[CC]
+ LOAD64_F(ft0, ft0f, rOBJ)
+ LOAD64_F(ft1, ft1f, t0)
+#ifdef MIPS32REVGE6
+ cmp.ult.d ft2, ft0, ft1
+ li rTEMP, -1
+ bc1nez ft2, .L${opcode}_finish
+ cmp.ult.d ft2, ft1, ft0
+ li rTEMP, 1
+ bc1nez ft2, .L${opcode}_finish
+ cmp.eq.d ft2, ft0, ft1
+ li rTEMP, 0
+ bc1nez ft2, .L${opcode}_finish
+ b .L${opcode}_nan
+#else
+ c.olt.d fcc0, ft0, ft1
+ li rTEMP, -1
+ bc1t fcc0, .L${opcode}_finish
+ c.olt.d fcc0, ft1, ft0
+ li rTEMP, 1
+ bc1t fcc0, .L${opcode}_finish
+ c.eq.d fcc0, ft0, ft1
+ li rTEMP, 0
+ bc1t fcc0, .L${opcode}_finish
+ b .L${opcode}_nan
+#endif
+%break
+
+.L${opcode}_nan:
+ $naninst
+
+.L${opcode}_finish:
+ GET_OPA(rOBJ)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(rTEMP, rOBJ, t0) # vAA <- rTEMP
diff --git a/runtime/interpreter/mterp/mips/op_cmpl_float.S b/runtime/interpreter/mterp/mips/op_cmpl_float.S
new file mode 100644
index 0000000..cfd87ee
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_cmpl_float.S
@@ -0,0 +1,61 @@
+%default { "naninst":"li rTEMP, -1" }
+ /*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register rTEMP based on the results of the comparison.
+ *
+ * Provide a "naninst" instruction that puts 1 or -1 into rTEMP depending
+ * on what value we'd like to return when one of the operands is NaN.
+ *
+ * The operation we're implementing is:
+ * if (x == y)
+ * return 0;
+ * else if (x < y)
+ * return -1;
+ * else if (x > y)
+ * return 1;
+ * else
+ * return {-1 or 1}; // one or both operands was NaN
+ *
+ * for: cmpl-float, cmpg-float
+ */
+ /* op vAA, vBB, vCC */
+
+ /* "clasic" form */
+ FETCH(a0, 1) # a0 <- CCBB
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8
+ GET_VREG_F(ft0, a2)
+ GET_VREG_F(ft1, a3)
+#ifdef MIPS32REVGE6
+ cmp.ult.s ft2, ft0, ft1 # Is ft0 < ft1
+ li rTEMP, -1
+ bc1nez ft2, .L${opcode}_finish
+ cmp.ult.s ft2, ft1, ft0
+ li rTEMP, 1
+ bc1nez ft2, .L${opcode}_finish
+ cmp.eq.s ft2, ft0, ft1
+ li rTEMP, 0
+ bc1nez ft2, .L${opcode}_finish
+ b .L${opcode}_nan
+#else
+ c.olt.s fcc0, ft0, ft1 # Is ft0 < ft1
+ li rTEMP, -1
+ bc1t fcc0, .L${opcode}_finish
+ c.olt.s fcc0, ft1, ft0
+ li rTEMP, 1
+ bc1t fcc0, .L${opcode}_finish
+ c.eq.s fcc0, ft0, ft1
+ li rTEMP, 0
+ bc1t fcc0, .L${opcode}_finish
+ b .L${opcode}_nan
+#endif
+%break
+
+.L${opcode}_nan:
+ $naninst
+
+.L${opcode}_finish:
+ GET_OPA(rOBJ)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(rTEMP, rOBJ, t0) # vAA <- rTEMP
diff --git a/runtime/interpreter/mterp/mips/op_const.S b/runtime/interpreter/mterp/mips/op_const.S
new file mode 100644
index 0000000..c505761
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const.S
@@ -0,0 +1,9 @@
+ # const vAA, /* +BBBBbbbb */
+ GET_OPA(a3) # a3 <- AA
+ FETCH(a0, 1) # a0 <- bbbb (low)
+ FETCH(a1, 2) # a1 <- BBBB (high)
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ sll a1, a1, 16
+ or a0, a1, a0 # a0 <- BBBBbbbb
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a3, t0) # vAA <- a0
diff --git a/runtime/interpreter/mterp/mips/op_const_16.S b/runtime/interpreter/mterp/mips/op_const_16.S
new file mode 100644
index 0000000..5e47633
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_16.S
@@ -0,0 +1,6 @@
+ # const/16 vAA, /* +BBBB */
+ FETCH_S(a0, 1) # a0 <- ssssBBBB (sign-extended)
+ GET_OPA(a3) # a3 <- AA
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a3, t0) # vAA <- a0
diff --git a/runtime/interpreter/mterp/mips/op_const_4.S b/runtime/interpreter/mterp/mips/op_const_4.S
new file mode 100644
index 0000000..8b662f9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_4.S
@@ -0,0 +1,8 @@
+ # const/4 vA, /* +B */
+ sll a1, rINST, 16 # a1 <- Bxxx0000
+ GET_OPA(a0) # a0 <- A+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ sra a1, a1, 28 # a1 <- sssssssB (sign-extended)
+ and a0, a0, 15
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a1, a0, t0) # fp[A] <- a1
diff --git a/runtime/interpreter/mterp/mips/op_const_class.S b/runtime/interpreter/mterp/mips/op_const_class.S
new file mode 100644
index 0000000..7202b11
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_class.S
@@ -0,0 +1,12 @@
+ # const/class vAA, Class /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- BBBB
+ GET_OPA(a1) # a1 <- AA
+ addu a2, rFP, OFF_FP_SHADOWFRAME # a2 <- shadow frame
+ move a3, rSELF
+ JAL(MterpConstClass)
+ PREFETCH_INST(2) # load rINST
+ bnez v0, MterpPossibleException
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_const_high16.S b/runtime/interpreter/mterp/mips/op_const_high16.S
new file mode 100644
index 0000000..36c1c35
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_high16.S
@@ -0,0 +1,7 @@
+ # const/high16 vAA, /* +BBBB0000 */
+ FETCH(a0, 1) # a0 <- 0000BBBB (zero-extended)
+ GET_OPA(a3) # a3 <- AA
+ sll a0, a0, 16 # a0 <- BBBB0000
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a3, t0) # vAA <- a0
diff --git a/runtime/interpreter/mterp/mips/op_const_string.S b/runtime/interpreter/mterp/mips/op_const_string.S
new file mode 100644
index 0000000..d8eeb46
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_string.S
@@ -0,0 +1,12 @@
+ # const/string vAA, String /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- BBBB
+ GET_OPA(a1) # a1 <- AA
+ addu a2, rFP, OFF_FP_SHADOWFRAME # a2 <- shadow frame
+ move a3, rSELF
+ JAL(MterpConstString) # v0 <- Mterp(index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST(2) # load rINST
+ bnez v0, MterpPossibleException
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_const_string_jumbo.S b/runtime/interpreter/mterp/mips/op_const_string_jumbo.S
new file mode 100644
index 0000000..d732ca1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_string_jumbo.S
@@ -0,0 +1,15 @@
+ # const/string vAA, String /* BBBBBBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- bbbb (low)
+ FETCH(a2, 2) # a2 <- BBBB (high)
+ GET_OPA(a1) # a1 <- AA
+ sll a2, a2, 16
+ or a0, a0, a2 # a0 <- BBBBbbbb
+ addu a2, rFP, OFF_FP_SHADOWFRAME # a2 <- shadow frame
+ move a3, rSELF
+ JAL(MterpConstString) # v0 <- Mterp(index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST(3) # load rINST
+ bnez v0, MterpPossibleException
+ ADVANCE(3) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_const_wide.S b/runtime/interpreter/mterp/mips/op_const_wide.S
new file mode 100644
index 0000000..01d0f87
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_wide.S
@@ -0,0 +1,14 @@
+ # const-wide vAA, /* +HHHHhhhhBBBBbbbb */
+ FETCH(a0, 1) # a0 <- bbbb (low)
+ FETCH(a1, 2) # a1 <- BBBB (low middle)
+ FETCH(a2, 3) # a2 <- hhhh (high middle)
+ sll a1, 16 #
+ or a0, a1 # a0 <- BBBBbbbb (low word)
+ FETCH(a3, 4) # a3 <- HHHH (high)
+ GET_OPA(t1) # t1 <- AA
+ sll a3, 16
+ or a1, a3, a2 # a1 <- HHHHhhhh (high word)
+ FETCH_ADVANCE_INST(5) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, t1) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_const_wide_16.S b/runtime/interpreter/mterp/mips/op_const_wide_16.S
new file mode 100644
index 0000000..583d9ef
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_wide_16.S
@@ -0,0 +1,8 @@
+ # const-wide/16 vAA, /* +BBBB */
+ FETCH_S(a0, 1) # a0 <- ssssBBBB (sign-extended)
+ GET_OPA(a3) # a3 <- AA
+ sra a1, a0, 31 # a1 <- ssssssss
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, a3) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_const_wide_32.S b/runtime/interpreter/mterp/mips/op_const_wide_32.S
new file mode 100644
index 0000000..3eb4574
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_wide_32.S
@@ -0,0 +1,11 @@
+ # const-wide/32 vAA, /* +BBBBbbbb */
+ FETCH(a0, 1) # a0 <- 0000bbbb (low)
+ GET_OPA(a3) # a3 <- AA
+ FETCH_S(a2, 2) # a2 <- ssssBBBB (high)
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ sll a2, a2, 16
+ or a0, a0, a2 # a0 <- BBBBbbbb
+ sra a1, a0, 31 # a1 <- ssssssss
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, a3) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_const_wide_high16.S b/runtime/interpreter/mterp/mips/op_const_wide_high16.S
new file mode 100644
index 0000000..88382c6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_const_wide_high16.S
@@ -0,0 +1,9 @@
+ # const-wide/high16 vAA, /* +BBBB000000000000 */
+ FETCH(a1, 1) # a1 <- 0000BBBB (zero-extended)
+ GET_OPA(a3) # a3 <- AA
+ li a0, 0 # a0 <- 00000000
+ sll a1, 16 # a1 <- BBBB0000
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, a3) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_div_double.S b/runtime/interpreter/mterp/mips/op_div_double.S
new file mode 100644
index 0000000..84e4c4e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_double.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide.S" {"instr":"div.d fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_div_double_2addr.S b/runtime/interpreter/mterp/mips/op_div_double_2addr.S
new file mode 100644
index 0000000..65b92e3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_double_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide2addr.S" {"instr":"div.d fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_div_float.S b/runtime/interpreter/mterp/mips/op_div_float.S
new file mode 100644
index 0000000..44b8d47
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_float.S
@@ -0,0 +1 @@
+%include "mips/fbinop.S" {"instr":"div.s fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_div_float_2addr.S b/runtime/interpreter/mterp/mips/op_div_float_2addr.S
new file mode 100644
index 0000000..e5fff92
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_float_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinop2addr.S" {"instr":"div.s fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_div_int.S b/runtime/interpreter/mterp/mips/op_div_int.S
new file mode 100644
index 0000000..5d28c84
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_int.S
@@ -0,0 +1,5 @@
+#ifdef MIPS32REVGE6
+%include "mips/binop.S" {"instr":"div a0, a0, a1", "chkzero":"1"}
+#else
+%include "mips/binop.S" {"preinstr":"div zero, a0, a1", "instr":"mflo a0", "chkzero":"1"}
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_div_int_2addr.S b/runtime/interpreter/mterp/mips/op_div_int_2addr.S
new file mode 100644
index 0000000..6c079e0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_int_2addr.S
@@ -0,0 +1,5 @@
+#ifdef MIPS32REVGE6
+%include "mips/binop2addr.S" {"instr":"div a0, a0, a1", "chkzero":"1"}
+#else
+%include "mips/binop2addr.S" {"preinstr":"div zero, a0, a1", "instr":"mflo a0", "chkzero":"1"}
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_div_int_lit16.S b/runtime/interpreter/mterp/mips/op_div_int_lit16.S
new file mode 100644
index 0000000..ee7452c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_int_lit16.S
@@ -0,0 +1,5 @@
+#ifdef MIPS32REVGE6
+%include "mips/binopLit16.S" {"instr":"div a0, a0, a1", "chkzero":"1"}
+#else
+%include "mips/binopLit16.S" {"preinstr":"div zero, a0, a1", "instr":"mflo a0", "chkzero":"1"}
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_div_int_lit8.S b/runtime/interpreter/mterp/mips/op_div_int_lit8.S
new file mode 100644
index 0000000..d2964b8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_int_lit8.S
@@ -0,0 +1,5 @@
+#ifdef MIPS32REVGE6
+%include "mips/binopLit8.S" {"instr":"div a0, a0, a1", "chkzero":"1"}
+#else
+%include "mips/binopLit8.S" {"preinstr":"div zero, a0, a1", "instr":"mflo a0", "chkzero":"1"}
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_div_long.S b/runtime/interpreter/mterp/mips/op_div_long.S
new file mode 100644
index 0000000..2097866
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_long.S
@@ -0,0 +1 @@
+%include "mips/binopWide.S" {"result0":"v0", "result1":"v1", "instr":"JAL(__divdi3)", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips/op_div_long_2addr.S b/runtime/interpreter/mterp/mips/op_div_long_2addr.S
new file mode 100644
index 0000000..c279305
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_div_long_2addr.S
@@ -0,0 +1 @@
+%include "mips/binopWide2addr.S" {"result0":"v0", "result1":"v1", "instr":"JAL(__divdi3)", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips/op_double_to_float.S b/runtime/interpreter/mterp/mips/op_double_to_float.S
new file mode 100644
index 0000000..1d32c2e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_double_to_float.S
@@ -0,0 +1 @@
+%include "mips/unopNarrower.S" {"instr":"cvt.s.d fv0, fa0"}
diff --git a/runtime/interpreter/mterp/mips/op_double_to_int.S b/runtime/interpreter/mterp/mips/op_double_to_int.S
new file mode 100644
index 0000000..30a0a73
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_double_to_int.S
@@ -0,0 +1,58 @@
+%include "mips/unopNarrower.S" {"instr":"b d2i_doconv"}
+/*
+ * Convert the double in a0/a1 to an int in a0.
+ *
+ * We have to clip values to int min/max per the specification. The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer. The EABI convert function isn't doing this for us.
+ */
+%break
+
+d2i_doconv:
+#ifdef MIPS32REVGE6
+ la t0, .LDOUBLE_TO_INT_max
+ LOAD64_F(fa1, fa1f, t0)
+ cmp.ule.d ft2, fa1, fa0
+ l.s fv0, .LDOUBLE_TO_INT_maxret
+ bc1nez ft2, .L${opcode}_set_vreg_f
+
+ la t0, .LDOUBLE_TO_INT_min
+ LOAD64_F(fa1, fa1f, t0)
+ cmp.ule.d ft2, fa0, fa1
+ l.s fv0, .LDOUBLE_TO_INT_minret
+ bc1nez ft2, .L${opcode}_set_vreg_f
+
+ mov.d fa1, fa0
+ cmp.un.d ft2, fa0, fa1
+ li.s fv0, 0
+ bc1nez ft2, .L${opcode}_set_vreg_f
+#else
+ la t0, .LDOUBLE_TO_INT_max
+ LOAD64_F(fa1, fa1f, t0)
+ c.ole.d fcc0, fa1, fa0
+ l.s fv0, .LDOUBLE_TO_INT_maxret
+ bc1t .L${opcode}_set_vreg_f
+
+ la t0, .LDOUBLE_TO_INT_min
+ LOAD64_F(fa1, fa1f, t0)
+ c.ole.d fcc0, fa0, fa1
+ l.s fv0, .LDOUBLE_TO_INT_minret
+ bc1t .L${opcode}_set_vreg_f
+
+ mov.d fa1, fa0
+ c.un.d fcc0, fa0, fa1
+ li.s fv0, 0
+ bc1t .L${opcode}_set_vreg_f
+#endif
+
+ trunc.w.d fv0, fa0
+ b .L${opcode}_set_vreg_f
+
+.LDOUBLE_TO_INT_max:
+ .dword 0x41dfffffffc00000
+.LDOUBLE_TO_INT_min:
+ .dword 0xc1e0000000000000 # minint, as a double (high word)
+.LDOUBLE_TO_INT_maxret:
+ .word 0x7fffffff
+.LDOUBLE_TO_INT_minret:
+ .word 0x80000000
diff --git a/runtime/interpreter/mterp/mips/op_double_to_long.S b/runtime/interpreter/mterp/mips/op_double_to_long.S
new file mode 100644
index 0000000..4f9e367
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_double_to_long.S
@@ -0,0 +1,56 @@
+%include "mips/funopWide.S" {"instr":"b d2l_doconv", "st_result":"SET_VREG64(rRESULT0, rRESULT1, rOBJ)"}
+%break
+
+d2l_doconv:
+#ifdef MIPS32REVGE6
+ la t0, .LDOUBLE_TO_LONG_max
+ LOAD64_F(fa1, fa1f, t0)
+ cmp.ule.d ft2, fa1, fa0
+ la t0, .LDOUBLE_TO_LONG_ret_max
+ LOAD64(rRESULT0, rRESULT1, t0)
+ bc1nez ft2, .L${opcode}_set_vreg
+
+ la t0, .LDOUBLE_TO_LONG_min
+ LOAD64_F(fa1, fa1f, t0)
+ cmp.ule.d ft2, fa0, fa1
+ la t0, .LDOUBLE_TO_LONG_ret_min
+ LOAD64(rRESULT0, rRESULT1, t0)
+ bc1nez ft2, .L${opcode}_set_vreg
+
+ mov.d fa1, fa0
+ cmp.un.d ft2, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0
+ bc1nez ft2, .L${opcode}_set_vreg
+#else
+ la t0, .LDOUBLE_TO_LONG_max
+ LOAD64_F(fa1, fa1f, t0)
+ c.ole.d fcc0, fa1, fa0
+ la t0, .LDOUBLE_TO_LONG_ret_max
+ LOAD64(rRESULT0, rRESULT1, t0)
+ bc1t .L${opcode}_set_vreg
+
+ la t0, .LDOUBLE_TO_LONG_min
+ LOAD64_F(fa1, fa1f, t0)
+ c.ole.d fcc0, fa0, fa1
+ la t0, .LDOUBLE_TO_LONG_ret_min
+ LOAD64(rRESULT0, rRESULT1, t0)
+ bc1t .L${opcode}_set_vreg
+
+ mov.d fa1, fa0
+ c.un.d fcc0, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0
+ bc1t .L${opcode}_set_vreg
+#endif
+ JAL(__fixdfdi)
+ b .L${opcode}_set_vreg
+
+.LDOUBLE_TO_LONG_max:
+ .dword 0x43e0000000000000 # maxlong, as a double (high word)
+.LDOUBLE_TO_LONG_min:
+ .dword 0xc3e0000000000000 # minlong, as a double (high word)
+.LDOUBLE_TO_LONG_ret_max:
+ .dword 0x7fffffffffffffff
+.LDOUBLE_TO_LONG_ret_min:
+ .dword 0x8000000000000000
diff --git a/runtime/interpreter/mterp/mips/op_fill_array_data.S b/runtime/interpreter/mterp/mips/op_fill_array_data.S
new file mode 100644
index 0000000..8605746
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_fill_array_data.S
@@ -0,0 +1,14 @@
+ /* fill-array-data vAA, +BBBBBBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- bbbb (lo)
+ FETCH(a1, 2) # a1 <- BBBB (hi)
+ GET_OPA(a3) # a3 <- AA
+ sll a1, a1, 16 # a1 <- BBBBbbbb
+ or a1, a0, a1 # a1 <- BBBBbbbb
+ GET_VREG(a0, a3) # a0 <- vAA (array object)
+ EAS1(a1, rPC, a1) # a1 <- PC + BBBBbbbb*2 (array data off.)
+ JAL(MterpFillArrayData) # v0 <- Mterp(obj, payload)
+ beqz v0, MterpPossibleException # has exception
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_filled_new_array.S b/runtime/interpreter/mterp/mips/op_filled_new_array.S
new file mode 100644
index 0000000..3f62fae
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_filled_new_array.S
@@ -0,0 +1,18 @@
+%default { "helper":"MterpFilledNewArray" }
+ /*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, type /* BBBB */
+ .extern $helper
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME # a0 <- shadow frame
+ move a1, rPC
+ move a2, rSELF
+ JAL($helper) # v0 <- helper(shadow_frame, pc, self)
+ beqz v0, MterpPossibleException # has exception
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_filled_new_array_range.S b/runtime/interpreter/mterp/mips/op_filled_new_array_range.S
new file mode 100644
index 0000000..f8dcb0e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_filled_new_array_range.S
@@ -0,0 +1 @@
+%include "mips/op_filled_new_array.S" { "helper":"MterpFilledNewArrayRange" }
diff --git a/runtime/interpreter/mterp/mips/op_float_to_double.S b/runtime/interpreter/mterp/mips/op_float_to_double.S
new file mode 100644
index 0000000..1315255
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_float_to_double.S
@@ -0,0 +1 @@
+%include "mips/funopWider.S" {"instr":"cvt.d.s fv0, fa0"}
diff --git a/runtime/interpreter/mterp/mips/op_float_to_int.S b/runtime/interpreter/mterp/mips/op_float_to_int.S
new file mode 100644
index 0000000..e032869
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_float_to_int.S
@@ -0,0 +1,50 @@
+%include "mips/funop.S" {"instr":"b f2i_doconv"}
+%break
+
+/*
+ * Not an entry point as it is used only once !!
+ */
+f2i_doconv:
+#ifdef MIPS32REVGE6
+ l.s fa1, .LFLOAT_TO_INT_max
+ cmp.ule.s ft2, fa1, fa0
+ l.s fv0, .LFLOAT_TO_INT_ret_max
+ bc1nez ft2, .L${opcode}_set_vreg_f
+
+ l.s fa1, .LFLOAT_TO_INT_min
+ cmp.ule.s ft2, fa0, fa1
+ l.s fv0, .LFLOAT_TO_INT_ret_min
+ bc1nez ft2, .L${opcode}_set_vreg_f
+
+ mov.s fa1, fa0
+ cmp.un.s ft2, fa0, fa1
+ li.s fv0, 0
+ bc1nez ft2, .L${opcode}_set_vreg_f
+#else
+ l.s fa1, .LFLOAT_TO_INT_max
+ c.ole.s fcc0, fa1, fa0
+ l.s fv0, .LFLOAT_TO_INT_ret_max
+ bc1t .L${opcode}_set_vreg_f
+
+ l.s fa1, .LFLOAT_TO_INT_min
+ c.ole.s fcc0, fa0, fa1
+ l.s fv0, .LFLOAT_TO_INT_ret_min
+ bc1t .L${opcode}_set_vreg_f
+
+ mov.s fa1, fa0
+ c.un.s fcc0, fa0, fa1
+ li.s fv0, 0
+ bc1t .L${opcode}_set_vreg_f
+#endif
+
+ trunc.w.s fv0, fa0
+ b .L${opcode}_set_vreg_f
+
+.LFLOAT_TO_INT_max:
+ .word 0x4f000000
+.LFLOAT_TO_INT_min:
+ .word 0xcf000000
+.LFLOAT_TO_INT_ret_max:
+ .word 0x7fffffff
+.LFLOAT_TO_INT_ret_min:
+ .word 0x80000000
diff --git a/runtime/interpreter/mterp/mips/op_float_to_long.S b/runtime/interpreter/mterp/mips/op_float_to_long.S
new file mode 100644
index 0000000..77b2c46
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_float_to_long.S
@@ -0,0 +1,51 @@
+%include "mips/funopWider.S" {"instr":"b f2l_doconv", "st_result":"SET_VREG64(rRESULT0, rRESULT1, rOBJ)"}
+%break
+
+f2l_doconv:
+#ifdef MIPS32REVGE6
+ l.s fa1, .LLONG_TO_max
+ cmp.ule.s ft2, fa1, fa0
+ li rRESULT0, ~0
+ li rRESULT1, ~0x80000000
+ bc1nez ft2, .L${opcode}_set_vreg
+
+ l.s fa1, .LLONG_TO_min
+ cmp.ule.s ft2, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0x80000000
+ bc1nez ft2, .L${opcode}_set_vreg
+
+ mov.s fa1, fa0
+ cmp.un.s ft2, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0
+ bc1nez ft2, .L${opcode}_set_vreg
+#else
+ l.s fa1, .LLONG_TO_max
+ c.ole.s fcc0, fa1, fa0
+ li rRESULT0, ~0
+ li rRESULT1, ~0x80000000
+ bc1t .L${opcode}_set_vreg
+
+ l.s fa1, .LLONG_TO_min
+ c.ole.s fcc0, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0x80000000
+ bc1t .L${opcode}_set_vreg
+
+ mov.s fa1, fa0
+ c.un.s fcc0, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0
+ bc1t .L${opcode}_set_vreg
+#endif
+
+ JAL(__fixsfdi)
+
+ b .L${opcode}_set_vreg
+
+.LLONG_TO_max:
+ .word 0x5f000000
+
+.LLONG_TO_min:
+ .word 0xdf000000
diff --git a/runtime/interpreter/mterp/mips/op_goto.S b/runtime/interpreter/mterp/mips/op_goto.S
new file mode 100644
index 0000000..d6f21c9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_goto.S
@@ -0,0 +1,38 @@
+ /*
+ * Unconditional branch, 8-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto +AA */
+#if MTERP_PROFILE_BRANCHES
+ sll a0, rINST, 16 # a0 <- AAxx0000
+ sra rINST, a0, 24 # rINST <- ssssssAA (sign-extended)
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+ addu a2, rINST, rINST # a2 <- byte offset
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ /* If backwards branch refresh rIBASE */
+ bgez a2, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#else
+ sll a0, rINST, 16 # a0 <- AAxx0000
+ sra rINST, a0, 24 # rINST <- ssssssAA (sign-extended)
+ addu a2, rINST, rINST # a2 <- byte offset
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ /* If backwards branch refresh rIBASE */
+ bgez a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_goto_16.S b/runtime/interpreter/mterp/mips/op_goto_16.S
new file mode 100644
index 0000000..cec4432
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_goto_16.S
@@ -0,0 +1,34 @@
+ /*
+ * Unconditional branch, 16-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto/16 +AAAA */
+#if MTERP_PROFILE_BRANCHES
+ FETCH_S(rINST, 1) # rINST <- ssssAAAA (sign-extended)
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+ addu a1, rINST, rINST # a1 <- byte offset, flags set
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#else
+ FETCH_S(rINST, 1) # rINST <- ssssAAAA (sign-extended)
+ addu a1, rINST, rINST # a1 <- byte offset, flags set
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_goto_32.S b/runtime/interpreter/mterp/mips/op_goto_32.S
new file mode 100644
index 0000000..083acd1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_goto_32.S
@@ -0,0 +1,43 @@
+ /*
+ * Unconditional branch, 32-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ *
+ * Unlike most opcodes, this one is allowed to branch to itself, so
+ * our "backward branch" test must be "<=0" instead of "<0".
+ */
+ /* goto/32 +AAAAAAAA */
+#if MTERP_PROFILE_BRANCHES
+ FETCH(a0, 1) # a0 <- aaaa (lo)
+ FETCH(a1, 2) # a1 <- AAAA (hi)
+ sll a1, a1, 16
+ or rINST, a0, a1 # rINST <- AAAAaaaa
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#else
+ FETCH(a0, 1) # a0 <- aaaa (lo)
+ FETCH(a1, 2) # a1 <- AAAA (hi)
+ sll a1, a1, 16
+ or rINST, a0, a1 # rINST <- AAAAaaaa
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_if_eq.S b/runtime/interpreter/mterp/mips/op_if_eq.S
new file mode 100644
index 0000000..e7190d8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_eq.S
@@ -0,0 +1 @@
+%include "mips/bincmp.S" { "revcmp":"ne" }
diff --git a/runtime/interpreter/mterp/mips/op_if_eqz.S b/runtime/interpreter/mterp/mips/op_if_eqz.S
new file mode 100644
index 0000000..0a78fd9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_eqz.S
@@ -0,0 +1 @@
+%include "mips/zcmp.S" { "revcmp":"ne" }
diff --git a/runtime/interpreter/mterp/mips/op_if_ge.S b/runtime/interpreter/mterp/mips/op_if_ge.S
new file mode 100644
index 0000000..b2629ba
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_ge.S
@@ -0,0 +1 @@
+%include "mips/bincmp.S" { "revcmp":"lt" }
diff --git a/runtime/interpreter/mterp/mips/op_if_gez.S b/runtime/interpreter/mterp/mips/op_if_gez.S
new file mode 100644
index 0000000..b02f677
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_gez.S
@@ -0,0 +1 @@
+%include "mips/zcmp.S" { "revcmp":"lt" }
diff --git a/runtime/interpreter/mterp/mips/op_if_gt.S b/runtime/interpreter/mterp/mips/op_if_gt.S
new file mode 100644
index 0000000..f620d4a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_gt.S
@@ -0,0 +1 @@
+%include "mips/bincmp.S" { "revcmp":"le" }
diff --git a/runtime/interpreter/mterp/mips/op_if_gtz.S b/runtime/interpreter/mterp/mips/op_if_gtz.S
new file mode 100644
index 0000000..5e5dd70
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_gtz.S
@@ -0,0 +1 @@
+%include "mips/zcmp.S" { "revcmp":"le" }
diff --git a/runtime/interpreter/mterp/mips/op_if_le.S b/runtime/interpreter/mterp/mips/op_if_le.S
new file mode 100644
index 0000000..a4e8b1a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_le.S
@@ -0,0 +1 @@
+%include "mips/bincmp.S" { "revcmp":"gt" }
diff --git a/runtime/interpreter/mterp/mips/op_if_lez.S b/runtime/interpreter/mterp/mips/op_if_lez.S
new file mode 100644
index 0000000..af551a6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_lez.S
@@ -0,0 +1 @@
+%include "mips/zcmp.S" { "revcmp":"gt" }
diff --git a/runtime/interpreter/mterp/mips/op_if_lt.S b/runtime/interpreter/mterp/mips/op_if_lt.S
new file mode 100644
index 0000000..f33b9a4
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_lt.S
@@ -0,0 +1 @@
+%include "mips/bincmp.S" { "revcmp":"ge" }
diff --git a/runtime/interpreter/mterp/mips/op_if_ltz.S b/runtime/interpreter/mterp/mips/op_if_ltz.S
new file mode 100644
index 0000000..18fcb1d
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_ltz.S
@@ -0,0 +1 @@
+%include "mips/zcmp.S" { "revcmp":"ge" }
diff --git a/runtime/interpreter/mterp/mips/op_if_ne.S b/runtime/interpreter/mterp/mips/op_if_ne.S
new file mode 100644
index 0000000..e0a102b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_ne.S
@@ -0,0 +1 @@
+%include "mips/bincmp.S" { "revcmp":"eq" }
diff --git a/runtime/interpreter/mterp/mips/op_if_nez.S b/runtime/interpreter/mterp/mips/op_if_nez.S
new file mode 100644
index 0000000..d1866a0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_if_nez.S
@@ -0,0 +1 @@
+%include "mips/zcmp.S" { "revcmp":"eq" }
diff --git a/runtime/interpreter/mterp/mips/op_iget.S b/runtime/interpreter/mterp/mips/op_iget.S
new file mode 100644
index 0000000..86d44fa
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget.S
@@ -0,0 +1,25 @@
+%default { "is_object":"0", "helper":"artGet32InstanceFromCode"}
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ JAL($helper)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpPossibleException # bail out
+ .if $is_object
+ SET_VREG_OBJECT(v0, a2) # fp[A] <- v0
+ .else
+ SET_VREG(v0, a2) # fp[A] <- v0
+ .endif
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_iget_boolean.S b/runtime/interpreter/mterp/mips/op_iget_boolean.S
new file mode 100644
index 0000000..e03364e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_boolean.S
@@ -0,0 +1 @@
+%include "mips/op_iget.S" { "helper":"artGetBooleanInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips/op_iget_boolean_quick.S b/runtime/interpreter/mterp/mips/op_iget_boolean_quick.S
new file mode 100644
index 0000000..f3032b3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_boolean_quick.S
@@ -0,0 +1 @@
+%include "mips/op_iget_quick.S" { "load":"lbu" }
diff --git a/runtime/interpreter/mterp/mips/op_iget_byte.S b/runtime/interpreter/mterp/mips/op_iget_byte.S
new file mode 100644
index 0000000..dc87cfe
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_byte.S
@@ -0,0 +1 @@
+%include "mips/op_iget.S" { "helper":"artGetByteInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips/op_iget_byte_quick.S b/runtime/interpreter/mterp/mips/op_iget_byte_quick.S
new file mode 100644
index 0000000..d93f844
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_byte_quick.S
@@ -0,0 +1 @@
+%include "mips/op_iget_quick.S" { "load":"lb" }
diff --git a/runtime/interpreter/mterp/mips/op_iget_char.S b/runtime/interpreter/mterp/mips/op_iget_char.S
new file mode 100644
index 0000000..55f8a93
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_char.S
@@ -0,0 +1 @@
+%include "mips/op_iget.S" { "helper":"artGetCharInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips/op_iget_char_quick.S b/runtime/interpreter/mterp/mips/op_iget_char_quick.S
new file mode 100644
index 0000000..6f6d608
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_char_quick.S
@@ -0,0 +1 @@
+%include "mips/op_iget_quick.S" { "load":"lhu" }
diff --git a/runtime/interpreter/mterp/mips/op_iget_object.S b/runtime/interpreter/mterp/mips/op_iget_object.S
new file mode 100644
index 0000000..11d93a4
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_object.S
@@ -0,0 +1 @@
+%include "mips/op_iget.S" { "is_object":"1", "helper":"artGetObjInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips/op_iget_object_quick.S b/runtime/interpreter/mterp/mips/op_iget_object_quick.S
new file mode 100644
index 0000000..31d94b9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_object_quick.S
@@ -0,0 +1,15 @@
+ /* For: iget-object-quick */
+ /* op vA, vB, offset@CCCC */
+ GET_OPB(a2) # a2 <- B
+ FETCH(a1, 1) # a1 <- field byte offset
+ EXPORT_PC()
+ GET_VREG(a0, a2) # a0 <- object we're operating on
+ JAL(artIGetObjectFromMterp) # v0 <- GetObj(obj, offset)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpPossibleException # bail out
+ SET_VREG_OBJECT(v0, a2) # fp[A] <- v0
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_iget_quick.S b/runtime/interpreter/mterp/mips/op_iget_quick.S
new file mode 100644
index 0000000..fbafa5b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_quick.S
@@ -0,0 +1,14 @@
+%default { "load":"lw" }
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- object we're operating on
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ # check object for null
+ beqz a3, common_errNullObject # object was null
+ addu t0, a3, a1
+ $load a0, 0(t0) # a0 <- obj.field (8/16/32 bits)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a2, t0) # fp[A] <- a0
diff --git a/runtime/interpreter/mterp/mips/op_iget_short.S b/runtime/interpreter/mterp/mips/op_iget_short.S
new file mode 100644
index 0000000..9086246
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_short.S
@@ -0,0 +1 @@
+%include "mips/op_iget.S" { "helper":"artGetShortInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips/op_iget_short_quick.S b/runtime/interpreter/mterp/mips/op_iget_short_quick.S
new file mode 100644
index 0000000..899a0fe
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_short_quick.S
@@ -0,0 +1 @@
+%include "mips/op_iget_quick.S" { "load":"lh" }
diff --git a/runtime/interpreter/mterp/mips/op_iget_wide.S b/runtime/interpreter/mterp/mips/op_iget_wide.S
new file mode 100644
index 0000000..8fe3089
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_wide.S
@@ -0,0 +1,20 @@
+ /*
+ * 64-bit instance field get.
+ *
+ * for: iget-wide
+ */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field byte offset
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ JAL(artGet64InstanceFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpException # bail out
+ SET_VREG64(v0, v1, a2) # fp[A] <- v0/v1
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_iget_wide_quick.S b/runtime/interpreter/mterp/mips/op_iget_wide_quick.S
new file mode 100644
index 0000000..4d2f291
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iget_wide_quick.S
@@ -0,0 +1,13 @@
+ # iget-wide-quick vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- object we're operating on
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ # check object for null
+ beqz a3, common_errNullObject # object was null
+ addu t0, a3, a1 # t0 <- a3 + a1
+ LOAD64(a0, a1, t0) # a0 <- obj.field (64 bits, aligned)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, a2) # fp[A] <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_instance_of.S b/runtime/interpreter/mterp/mips/op_instance_of.S
new file mode 100644
index 0000000..d2679bd
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_instance_of.S
@@ -0,0 +1,21 @@
+ /*
+ * Check to see if an object reference is an instance of a class.
+ *
+ * Most common situation is a non-null object, being compared against
+ * an already-resolved class.
+ */
+ # instance-of vA, vB, class /* CCCC */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- CCCC
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &object
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ JAL(MterpInstanceOf) # v0 <- Mterp(index, &obj, method, self)
+ lw a1, THREAD_EXCEPTION_OFFSET(rSELF)
+ PREFETCH_INST(2) # load rINST
+ bnez a1, MterpException
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(v0, rOBJ, t0) # vA <- v0
diff --git a/runtime/interpreter/mterp/mips/op_int_to_byte.S b/runtime/interpreter/mterp/mips/op_int_to_byte.S
new file mode 100644
index 0000000..77314c62
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_int_to_byte.S
@@ -0,0 +1 @@
+%include "mips/unop.S" {"preinstr":"sll a0, a0, 24", "instr":"sra a0, a0, 24"}
diff --git a/runtime/interpreter/mterp/mips/op_int_to_char.S b/runtime/interpreter/mterp/mips/op_int_to_char.S
new file mode 100644
index 0000000..1b74a6e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_int_to_char.S
@@ -0,0 +1 @@
+%include "mips/unop.S" {"preinstr":"", "instr":"and a0, 0xffff"}
diff --git a/runtime/interpreter/mterp/mips/op_int_to_double.S b/runtime/interpreter/mterp/mips/op_int_to_double.S
new file mode 100644
index 0000000..89484ce
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_int_to_double.S
@@ -0,0 +1 @@
+%include "mips/funopWider.S" {"instr":"cvt.d.w fv0, fa0"}
diff --git a/runtime/interpreter/mterp/mips/op_int_to_float.S b/runtime/interpreter/mterp/mips/op_int_to_float.S
new file mode 100644
index 0000000..d6f4b36
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_int_to_float.S
@@ -0,0 +1 @@
+%include "mips/funop.S" {"instr":"cvt.s.w fv0, fa0"}
diff --git a/runtime/interpreter/mterp/mips/op_int_to_long.S b/runtime/interpreter/mterp/mips/op_int_to_long.S
new file mode 100644
index 0000000..9907463
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_int_to_long.S
@@ -0,0 +1 @@
+%include "mips/unopWider.S" {"instr":"sra a1, a0, 31"}
diff --git a/runtime/interpreter/mterp/mips/op_int_to_short.S b/runtime/interpreter/mterp/mips/op_int_to_short.S
new file mode 100644
index 0000000..5649c2a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_int_to_short.S
@@ -0,0 +1 @@
+%include "mips/unop.S" {"preinstr":"sll a0, 16", "instr":"sra a0, 16"}
diff --git a/runtime/interpreter/mterp/mips/op_invoke_direct.S b/runtime/interpreter/mterp/mips/op_invoke_direct.S
new file mode 100644
index 0000000..1ef198a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_direct.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeDirect" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_direct_range.S b/runtime/interpreter/mterp/mips/op_invoke_direct_range.S
new file mode 100644
index 0000000..af7477f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_direct_range.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeDirectRange" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_interface.S b/runtime/interpreter/mterp/mips/op_invoke_interface.S
new file mode 100644
index 0000000..80a485a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_interface.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeInterface" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_interface_range.S b/runtime/interpreter/mterp/mips/op_invoke_interface_range.S
new file mode 100644
index 0000000..8d725dc
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_interface_range.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeInterfaceRange" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_static.S b/runtime/interpreter/mterp/mips/op_invoke_static.S
new file mode 100644
index 0000000..46253cb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_static.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeStatic" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_static_range.S b/runtime/interpreter/mterp/mips/op_invoke_static_range.S
new file mode 100644
index 0000000..96abafe
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_static_range.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeStaticRange" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_super.S b/runtime/interpreter/mterp/mips/op_invoke_super.S
new file mode 100644
index 0000000..473951b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_super.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeSuper" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_super_range.S b/runtime/interpreter/mterp/mips/op_invoke_super_range.S
new file mode 100644
index 0000000..963ff27
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_super_range.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeSuperRange" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_virtual.S b/runtime/interpreter/mterp/mips/op_invoke_virtual.S
new file mode 100644
index 0000000..ea51e98
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_virtual.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeVirtual" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_virtual_quick.S b/runtime/interpreter/mterp/mips/op_invoke_virtual_quick.S
new file mode 100644
index 0000000..0c00091
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_virtual_quick.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeVirtualQuick" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_virtual_range.S b/runtime/interpreter/mterp/mips/op_invoke_virtual_range.S
new file mode 100644
index 0000000..82201e7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_virtual_range.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeVirtualRange" }
diff --git a/runtime/interpreter/mterp/mips/op_invoke_virtual_range_quick.S b/runtime/interpreter/mterp/mips/op_invoke_virtual_range_quick.S
new file mode 100644
index 0000000..c783675
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_invoke_virtual_range_quick.S
@@ -0,0 +1 @@
+%include "mips/invoke.S" { "helper":"MterpInvokeVirtualQuickRange" }
diff --git a/runtime/interpreter/mterp/mips/op_iput.S b/runtime/interpreter/mterp/mips/op_iput.S
new file mode 100644
index 0000000..732a9a4
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput.S
@@ -0,0 +1,21 @@
+%default { "handler":"artSet32InstanceFromMterp" }
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ # op vA, vB, field /* CCCC */
+ .extern $handler
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ GET_OPA4(a2) # a2 <- A+
+ GET_VREG(a2, a2) # a2 <- fp[A]
+ lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST(2) # load rINST
+ JAL($handler)
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_iput_boolean.S b/runtime/interpreter/mterp/mips/op_iput_boolean.S
new file mode 100644
index 0000000..da28c97
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_boolean.S
@@ -0,0 +1 @@
+%include "mips/op_iput.S" { "handler":"artSet8InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/mips/op_iput_boolean_quick.S b/runtime/interpreter/mterp/mips/op_iput_boolean_quick.S
new file mode 100644
index 0000000..7d5caf6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_boolean_quick.S
@@ -0,0 +1 @@
+%include "mips/op_iput_quick.S" { "store":"sb" }
diff --git a/runtime/interpreter/mterp/mips/op_iput_byte.S b/runtime/interpreter/mterp/mips/op_iput_byte.S
new file mode 100644
index 0000000..da28c97
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_byte.S
@@ -0,0 +1 @@
+%include "mips/op_iput.S" { "handler":"artSet8InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/mips/op_iput_byte_quick.S b/runtime/interpreter/mterp/mips/op_iput_byte_quick.S
new file mode 100644
index 0000000..7d5caf6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_byte_quick.S
@@ -0,0 +1 @@
+%include "mips/op_iput_quick.S" { "store":"sb" }
diff --git a/runtime/interpreter/mterp/mips/op_iput_char.S b/runtime/interpreter/mterp/mips/op_iput_char.S
new file mode 100644
index 0000000..389b0bf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_char.S
@@ -0,0 +1 @@
+%include "mips/op_iput.S" { "handler":"artSet16InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/mips/op_iput_char_quick.S b/runtime/interpreter/mterp/mips/op_iput_char_quick.S
new file mode 100644
index 0000000..4bc84eb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_char_quick.S
@@ -0,0 +1 @@
+%include "mips/op_iput_quick.S" { "store":"sh" }
diff --git a/runtime/interpreter/mterp/mips/op_iput_object.S b/runtime/interpreter/mterp/mips/op_iput_object.S
new file mode 100644
index 0000000..6b856e7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_object.S
@@ -0,0 +1,16 @@
+ /*
+ * 32-bit instance field put.
+ *
+ * for: iput-object, iput-object-volatile
+ */
+ # op vA, vB, field /* CCCC */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ JAL(MterpIputObject)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_iput_object_quick.S b/runtime/interpreter/mterp/mips/op_iput_object_quick.S
new file mode 100644
index 0000000..c3f1526
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_object_quick.S
@@ -0,0 +1,11 @@
+ /* For: iput-object-quick */
+ # op vA, vB, offset /* CCCC */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ JAL(MterpIputObjectQuick)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_iput_quick.S b/runtime/interpreter/mterp/mips/op_iput_quick.S
new file mode 100644
index 0000000..0829666
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_quick.S
@@ -0,0 +1,14 @@
+%default { "store":"sw" }
+ /* For: iput-quick, iput-object-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- fp[B], the object pointer
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ beqz a3, common_errNullObject # object was null
+ GET_VREG(a0, a2) # a0 <- fp[A]
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ addu t0, a3, a1
+ $store a0, 0(t0) # obj.field (8/16/32 bits) <- a0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_iput_short.S b/runtime/interpreter/mterp/mips/op_iput_short.S
new file mode 100644
index 0000000..389b0bf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_short.S
@@ -0,0 +1 @@
+%include "mips/op_iput.S" { "handler":"artSet16InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/mips/op_iput_short_quick.S b/runtime/interpreter/mterp/mips/op_iput_short_quick.S
new file mode 100644
index 0000000..4bc84eb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_short_quick.S
@@ -0,0 +1 @@
+%include "mips/op_iput_quick.S" { "store":"sh" }
diff --git a/runtime/interpreter/mterp/mips/op_iput_wide.S b/runtime/interpreter/mterp/mips/op_iput_wide.S
new file mode 100644
index 0000000..6d23f8c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_wide.S
@@ -0,0 +1,15 @@
+ # iput-wide vA, vB, field /* CCCC */
+ .extern artSet64InstanceFromMterp
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ GET_OPA4(a2) # a2 <- A+
+ EAS2(a2, rFP, a2) # a2 <- &fp[A]
+ lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet64InstanceFromMterp)
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_iput_wide_quick.S b/runtime/interpreter/mterp/mips/op_iput_wide_quick.S
new file mode 100644
index 0000000..9fdb847
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_iput_wide_quick.S
@@ -0,0 +1,14 @@
+ # iput-wide-quick vA, vB, offset /* CCCC */
+ GET_OPA4(a0) # a0 <- A(+)
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a2, a1) # a2 <- fp[B], the object pointer
+ # check object for null
+ beqz a2, common_errNullObject # object was null
+ EAS2(a3, rFP, a0) # a3 <- &fp[A]
+ LOAD64(a0, a1, a3) # a0/a1 <- fp[A]
+ FETCH(a3, 1) # a3 <- field byte offset
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ addu a2, a2, a3 # obj.field (64 bits, aligned) <- a0/a1
+ STORE64(a0, a1, a2) # obj.field (64 bits, aligned) <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_long_to_double.S b/runtime/interpreter/mterp/mips/op_long_to_double.S
new file mode 100644
index 0000000..b83aaf4
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_long_to_double.S
@@ -0,0 +1 @@
+%include "mips/funopWide.S" {"instr":"JAL(__floatdidf)", "ld_arg":"LOAD64(rARG0, rARG1, a3)"}
diff --git a/runtime/interpreter/mterp/mips/op_long_to_float.S b/runtime/interpreter/mterp/mips/op_long_to_float.S
new file mode 100644
index 0000000..27faba5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_long_to_float.S
@@ -0,0 +1 @@
+%include "mips/unopNarrower.S" {"instr":"JAL(__floatdisf)", "load":"LOAD64(rARG0, rARG1, a3)"}
diff --git a/runtime/interpreter/mterp/mips/op_long_to_int.S b/runtime/interpreter/mterp/mips/op_long_to_int.S
new file mode 100644
index 0000000..949c180
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_long_to_int.S
@@ -0,0 +1,2 @@
+/* we ignore the high word, making this equivalent to a 32-bit reg move */
+%include "mips/op_move.S"
diff --git a/runtime/interpreter/mterp/mips/op_monitor_enter.S b/runtime/interpreter/mterp/mips/op_monitor_enter.S
new file mode 100644
index 0000000..20d9029
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_monitor_enter.S
@@ -0,0 +1,13 @@
+ /*
+ * Synchronize on an object.
+ */
+ /* monitor-enter vAA */
+ EXPORT_PC()
+ GET_OPA(a2) # a2 <- AA
+ GET_VREG(a0, a2) # a0 <- vAA (object)
+ move a1, rSELF # a1 <- self
+ JAL(artLockObjectFromCode) # v0 <- artLockObject(obj, self)
+ bnez v0, MterpException
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_monitor_exit.S b/runtime/interpreter/mterp/mips/op_monitor_exit.S
new file mode 100644
index 0000000..1eadff9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_monitor_exit.S
@@ -0,0 +1,17 @@
+ /*
+ * Unlock an object.
+ *
+ * Exceptions that occur when unlocking a monitor need to appear as
+ * if they happened at the following instruction. See the Dalvik
+ * instruction spec.
+ */
+ /* monitor-exit vAA */
+ EXPORT_PC()
+ GET_OPA(a2) # a2 <- AA
+ GET_VREG(a0, a2) # a0 <- vAA (object)
+ move a1, rSELF # a1 <- self
+ JAL(artUnlockObjectFromCode) # v0 <- artUnlockObject(obj, self)
+ bnez v0, MterpException
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_move.S b/runtime/interpreter/mterp/mips/op_move.S
new file mode 100644
index 0000000..76588ba
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move.S
@@ -0,0 +1,14 @@
+%default { "is_object":"0" }
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ GET_OPB(a1) # a1 <- B from 15:12
+ GET_OPA4(a0) # a0 <- A from 11:8
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[B]
+ GET_INST_OPCODE(t0) # t0 <- opcode from rINST
+ .if $is_object
+ SET_VREG_OBJECT(a2, a0) # fp[A] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[A] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_move_16.S b/runtime/interpreter/mterp/mips/op_move_16.S
new file mode 100644
index 0000000..f7de6c2
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_16.S
@@ -0,0 +1,14 @@
+%default { "is_object":"0" }
+ /* for: move/16, move-object/16 */
+ /* op vAAAA, vBBBB */
+ FETCH(a1, 2) # a1 <- BBBB
+ FETCH(a0, 1) # a0 <- AAAA
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[BBBB]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ .if $is_object
+ SET_VREG_OBJECT(a2, a0) # fp[AAAA] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[AAAA] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_move_exception.S b/runtime/interpreter/mterp/mips/op_move_exception.S
new file mode 100644
index 0000000..f04a035
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_exception.S
@@ -0,0 +1,8 @@
+ /* move-exception vAA */
+ GET_OPA(a2) # a2 <- AA
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF) # get exception obj
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ SET_VREG_OBJECT(a3, a2) # fp[AA] <- exception obj
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ sw zero, THREAD_EXCEPTION_OFFSET(rSELF) # clear exception
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_move_from16.S b/runtime/interpreter/mterp/mips/op_move_from16.S
new file mode 100644
index 0000000..b8be741
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_from16.S
@@ -0,0 +1,14 @@
+%default { "is_object":"0" }
+ /* for: move/from16, move-object/from16 */
+ /* op vAA, vBBBB */
+ FETCH(a1, 1) # a1 <- BBBB
+ GET_OPA(a0) # a0 <- AA
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[BBBB]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ .if $is_object
+ SET_VREG_OBJECT(a2, a0) # fp[AA] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[AA] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_move_object.S b/runtime/interpreter/mterp/mips/op_move_object.S
new file mode 100644
index 0000000..9420ff3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_object.S
@@ -0,0 +1 @@
+%include "mips/op_move.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/mips/op_move_object_16.S b/runtime/interpreter/mterp/mips/op_move_object_16.S
new file mode 100644
index 0000000..d6454c2
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_object_16.S
@@ -0,0 +1 @@
+%include "mips/op_move_16.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/mips/op_move_object_from16.S b/runtime/interpreter/mterp/mips/op_move_object_from16.S
new file mode 100644
index 0000000..db0aca1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_object_from16.S
@@ -0,0 +1 @@
+%include "mips/op_move_from16.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/mips/op_move_result.S b/runtime/interpreter/mterp/mips/op_move_result.S
new file mode 100644
index 0000000..315c68e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_result.S
@@ -0,0 +1,14 @@
+%default { "is_object":"0" }
+ /* for: move-result, move-result-object */
+ /* op vAA */
+ GET_OPA(a2) # a2 <- AA
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ lw a0, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ lw a0, 0(a0) # a0 <- result.i
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ .if $is_object
+ SET_VREG_OBJECT(a0, a2) # fp[AA] <- a0
+ .else
+ SET_VREG(a0, a2) # fp[AA] <- a0
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_move_result_object.S b/runtime/interpreter/mterp/mips/op_move_result_object.S
new file mode 100644
index 0000000..fcbffee
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_result_object.S
@@ -0,0 +1 @@
+%include "mips/op_move_result.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/mips/op_move_result_wide.S b/runtime/interpreter/mterp/mips/op_move_result_wide.S
new file mode 100644
index 0000000..940c1ff
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_result_wide.S
@@ -0,0 +1,8 @@
+ /* move-result-wide vAA */
+ GET_OPA(a2) # a2 <- AA
+ lw a3, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ LOAD64(a0, a1, a3) # a0/a1 <- retval.j
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ SET_VREG64(a0, a1, a2) # fp[AA] <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_move_wide.S b/runtime/interpreter/mterp/mips/op_move_wide.S
new file mode 100644
index 0000000..dd224c3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_wide.S
@@ -0,0 +1,10 @@
+ /* move-wide vA, vB */
+ /* NOTE: regs can overlap, e.g. "move v6, v7" or "move v7, v6" */
+ GET_OPA4(a2) # a2 <- A(+)
+ GET_OPB(a3) # a3 <- B
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64(a0, a1, a3) # a0/a1 <- fp[B]
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ SET_VREG64(a0, a1, a2) # fp[A] <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_move_wide_16.S b/runtime/interpreter/mterp/mips/op_move_wide_16.S
new file mode 100644
index 0000000..d8761eb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_wide_16.S
@@ -0,0 +1,10 @@
+ /* move-wide/16 vAAAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6, v7" or "move v7, v6" */
+ FETCH(a3, 2) # a3 <- BBBB
+ FETCH(a2, 1) # a2 <- AAAA
+ EAS2(a3, rFP, a3) # a3 <- &fp[BBBB]
+ LOAD64(a0, a1, a3) # a0/a1 <- fp[BBBB]
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ SET_VREG64(a0, a1, a2) # fp[AAAA] <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_move_wide_from16.S b/runtime/interpreter/mterp/mips/op_move_wide_from16.S
new file mode 100644
index 0000000..2103fa1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_move_wide_from16.S
@@ -0,0 +1,10 @@
+ /* move-wide/from16 vAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6, v7" or "move v7, v6" */
+ FETCH(a3, 1) # a3 <- BBBB
+ GET_OPA(a2) # a2 <- AA
+ EAS2(a3, rFP, a3) # a3 <- &fp[BBBB]
+ LOAD64(a0, a1, a3) # a0/a1 <- fp[BBBB]
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ SET_VREG64(a0, a1, a2) # fp[AA] <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_mul_double.S b/runtime/interpreter/mterp/mips/op_mul_double.S
new file mode 100644
index 0000000..44a473b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_double.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide.S" {"instr":"mul.d fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_mul_double_2addr.S b/runtime/interpreter/mterp/mips/op_mul_double_2addr.S
new file mode 100644
index 0000000..4e5c230
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_double_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide2addr.S" {"instr":"mul.d fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_mul_float.S b/runtime/interpreter/mterp/mips/op_mul_float.S
new file mode 100644
index 0000000..abc9390
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_float.S
@@ -0,0 +1 @@
+%include "mips/fbinop.S" {"instr":"mul.s fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_mul_float_2addr.S b/runtime/interpreter/mterp/mips/op_mul_float_2addr.S
new file mode 100644
index 0000000..2469109
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_float_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinop2addr.S" {"instr":"mul.s fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_mul_int.S b/runtime/interpreter/mterp/mips/op_mul_int.S
new file mode 100644
index 0000000..266823c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_int.S
@@ -0,0 +1 @@
+%include "mips/binop.S" {"instr":"mul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_mul_int_2addr.S b/runtime/interpreter/mterp/mips/op_mul_int_2addr.S
new file mode 100644
index 0000000..b7dc5d3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_int_2addr.S
@@ -0,0 +1 @@
+%include "mips/binop2addr.S" {"instr":"mul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_mul_int_lit16.S b/runtime/interpreter/mterp/mips/op_mul_int_lit16.S
new file mode 100644
index 0000000..fb4c8ec
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_int_lit16.S
@@ -0,0 +1 @@
+%include "mips/binopLit16.S" {"instr":"mul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_mul_int_lit8.S b/runtime/interpreter/mterp/mips/op_mul_int_lit8.S
new file mode 100644
index 0000000..6d2e7de
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_int_lit8.S
@@ -0,0 +1 @@
+%include "mips/binopLit8.S" {"instr":"mul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_mul_long.S b/runtime/interpreter/mterp/mips/op_mul_long.S
new file mode 100644
index 0000000..803bbec
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_long.S
@@ -0,0 +1,43 @@
+ /*
+ * Signed 64-bit integer multiply.
+ * a1 a0
+ * x a3 a2
+ * -------------
+ * a2a1 a2a0
+ * a3a0
+ * a3a1 (<= unused)
+ * ---------------
+ * v1 v0
+ */
+ /* mul-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ and t0, a0, 255 # a2 <- BB
+ srl t1, a0, 8 # a3 <- CC
+ EAS2(t0, rFP, t0) # t0 <- &fp[BB]
+ LOAD64(a0, a1, t0) # a0/a1 <- vBB/vBB+1
+
+ EAS2(t1, rFP, t1) # t0 <- &fp[CC]
+ LOAD64(a2, a3, t1) # a2/a3 <- vCC/vCC+1
+
+ mul v1, a3, a0 # v1= a3a0
+#ifdef MIPS32REVGE6
+ mulu v0, a2, a0 # v0= a2a0
+ muhu t1, a2, a0
+#else
+ multu a2, a0
+ mfhi t1
+ mflo v0 # v0= a2a0
+#endif
+ mul t0, a2, a1 # t0= a2a1
+ addu v1, v1, t1 # v1+= hi(a2a0)
+ addu v1, v1, t0 # v1= a3a0 + a2a1;
+
+ GET_OPA(a0) # a0 <- AA
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ b .L${opcode}_finish
+%break
+
+.L${opcode}_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(v0, v1, a0) # vAA::vAA+1 <- v0(low) :: v1(high)
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_mul_long_2addr.S b/runtime/interpreter/mterp/mips/op_mul_long_2addr.S
new file mode 100644
index 0000000..6950b71
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_mul_long_2addr.S
@@ -0,0 +1,31 @@
+ /*
+ * See op_mul_long.S for more details
+ */
+ /* mul-long/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64(a0, a1, t0) # vAA.low / high
+
+ GET_OPB(t1) # t1 <- B
+ EAS2(t1, rFP, t1) # t1 <- &fp[B]
+ LOAD64(a2, a3, t1) # vBB.low / high
+
+ mul v1, a3, a0 # v1= a3a0
+#ifdef MIPS32REVGE6
+ mulu v0, a2, a0 # v0= a2a0
+ muhu t1, a2, a0
+#else
+ multu a2, a0
+ mfhi t1
+ mflo v0 # v0= a2a0
+ #endif
+ mul t2, a2, a1 # t2= a2a1
+ addu v1, v1, t1 # v1= a3a0 + hi(a2a0)
+ addu v1, v1, t2 # v1= v1 + a2a1;
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ # vAA <- v0 (low)
+ SET_VREG64(v0, v1, rOBJ) # vAA+1 <- v1 (high)
+ GOTO_OPCODE(t1) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_neg_double.S b/runtime/interpreter/mterp/mips/op_neg_double.S
new file mode 100644
index 0000000..89cc918
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_neg_double.S
@@ -0,0 +1 @@
+%include "mips/unopWide.S" {"instr":"addu a1, a1, 0x80000000"}
diff --git a/runtime/interpreter/mterp/mips/op_neg_float.S b/runtime/interpreter/mterp/mips/op_neg_float.S
new file mode 100644
index 0000000..e702755
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_neg_float.S
@@ -0,0 +1 @@
+%include "mips/unop.S" {"instr":"addu a0, a0, 0x80000000"}
diff --git a/runtime/interpreter/mterp/mips/op_neg_int.S b/runtime/interpreter/mterp/mips/op_neg_int.S
new file mode 100644
index 0000000..4461731
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_neg_int.S
@@ -0,0 +1 @@
+%include "mips/unop.S" {"instr":"negu a0, a0"}
diff --git a/runtime/interpreter/mterp/mips/op_neg_long.S b/runtime/interpreter/mterp/mips/op_neg_long.S
new file mode 100644
index 0000000..71e60f5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_neg_long.S
@@ -0,0 +1 @@
+%include "mips/unopWide.S" {"result0":"v0", "result1":"v1", "preinstr":"negu v0, a0", "instr":"negu v1, a1; sltu a0, zero, v0; subu v1, v1, a0"}
diff --git a/runtime/interpreter/mterp/mips/op_new_array.S b/runtime/interpreter/mterp/mips/op_new_array.S
new file mode 100644
index 0000000..4a6512d
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_new_array.S
@@ -0,0 +1,18 @@
+ /*
+ * Allocate an array of objects, specified with the array class
+ * and a count.
+ *
+ * The verifier guarantees that this is an array class, so we don't
+ * check for it here.
+ */
+ /* new-array vA, vB, class@CCCC */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ JAL(MterpNewArray)
+ beqz v0, MterpPossibleException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_new_instance.S b/runtime/interpreter/mterp/mips/op_new_instance.S
new file mode 100644
index 0000000..51a09b2
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_new_instance.S
@@ -0,0 +1,13 @@
+ /*
+ * Create a new instance of a class.
+ */
+ # new-instance vAA, class /* BBBB */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rSELF
+ move a2, rINST
+ JAL(MterpNewInstance)
+ beqz v0, MterpPossibleException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_nop.S b/runtime/interpreter/mterp/mips/op_nop.S
new file mode 100644
index 0000000..3565631
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_nop.S
@@ -0,0 +1,3 @@
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_not_int.S b/runtime/interpreter/mterp/mips/op_not_int.S
new file mode 100644
index 0000000..55d8cc1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_not_int.S
@@ -0,0 +1 @@
+%include "mips/unop.S" {"instr":"not a0, a0"}
diff --git a/runtime/interpreter/mterp/mips/op_not_long.S b/runtime/interpreter/mterp/mips/op_not_long.S
new file mode 100644
index 0000000..9e7c95b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_not_long.S
@@ -0,0 +1 @@
+%include "mips/unopWide.S" {"preinstr":"not a0, a0", "instr":"not a1, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_or_int.S b/runtime/interpreter/mterp/mips/op_or_int.S
new file mode 100644
index 0000000..c7ce760
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_or_int.S
@@ -0,0 +1 @@
+%include "mips/binop.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_or_int_2addr.S b/runtime/interpreter/mterp/mips/op_or_int_2addr.S
new file mode 100644
index 0000000..192d611
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_or_int_2addr.S
@@ -0,0 +1 @@
+%include "mips/binop2addr.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_or_int_lit16.S b/runtime/interpreter/mterp/mips/op_or_int_lit16.S
new file mode 100644
index 0000000..f4ef75f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_or_int_lit16.S
@@ -0,0 +1 @@
+%include "mips/binopLit16.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_or_int_lit8.S b/runtime/interpreter/mterp/mips/op_or_int_lit8.S
new file mode 100644
index 0000000..f6212e2
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_or_int_lit8.S
@@ -0,0 +1 @@
+%include "mips/binopLit8.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_or_long.S b/runtime/interpreter/mterp/mips/op_or_long.S
new file mode 100644
index 0000000..0f94486
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_or_long.S
@@ -0,0 +1 @@
+%include "mips/binopWide.S" {"preinstr":"or a0, a0, a2", "instr":"or a1, a1, a3"}
diff --git a/runtime/interpreter/mterp/mips/op_or_long_2addr.S b/runtime/interpreter/mterp/mips/op_or_long_2addr.S
new file mode 100644
index 0000000..43c3d05
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_or_long_2addr.S
@@ -0,0 +1 @@
+%include "mips/binopWide2addr.S" {"preinstr":"or a0, a0, a2", "instr":"or a1, a1, a3"}
diff --git a/runtime/interpreter/mterp/mips/op_packed_switch.S b/runtime/interpreter/mterp/mips/op_packed_switch.S
new file mode 100644
index 0000000..93fae97
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_packed_switch.S
@@ -0,0 +1,57 @@
+%default { "func":"MterpDoPackedSwitch" }
+ /*
+ * Handle a packed-switch or sparse-switch instruction. In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+ /* op vAA, +BBBB */
+#if MTERP_PROFILE_BRANCHES
+ FETCH(a0, 1) # a0 <- bbbb (lo)
+ FETCH(a1, 2) # a1 <- BBBB (hi)
+ GET_OPA(a3) # a3 <- AA
+ sll t0, a1, 16
+ or a0, a0, t0 # a0 <- BBBBbbbb
+ GET_VREG(a1, a3) # a1 <- vAA
+ EAS1(a0, rPC, a0) # a0 <- PC + BBBBbbbb*2
+ JAL($func) # a0 <- code-unit branch offset
+ move rINST, v0
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, .L${opcode}_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+#else
+ FETCH(a0, 1) # a0 <- bbbb (lo)
+ FETCH(a1, 2) # a1 <- BBBB (hi)
+ GET_OPA(a3) # a3 <- AA
+ sll t0, a1, 16
+ or a0, a0, t0 # a0 <- BBBBbbbb
+ GET_VREG(a1, a3) # a1 <- vAA
+ EAS1(a0, rPC, a0) # a0 <- PC + BBBBbbbb*2
+ JAL($func) # a0 <- code-unit branch offset
+ move rINST, v0
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#endif
+
+%break
+
+.L${opcode}_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_rem_double.S b/runtime/interpreter/mterp/mips/op_rem_double.S
new file mode 100644
index 0000000..a6890a8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_double.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide.S" {"instr":"JAL(fmod)"}
diff --git a/runtime/interpreter/mterp/mips/op_rem_double_2addr.S b/runtime/interpreter/mterp/mips/op_rem_double_2addr.S
new file mode 100644
index 0000000..a24e160
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_double_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide2addr.S" {"instr":"JAL(fmod)"}
diff --git a/runtime/interpreter/mterp/mips/op_rem_float.S b/runtime/interpreter/mterp/mips/op_rem_float.S
new file mode 100644
index 0000000..ac3d50c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_float.S
@@ -0,0 +1 @@
+%include "mips/fbinop.S" {"instr":"JAL(fmodf)"}
diff --git a/runtime/interpreter/mterp/mips/op_rem_float_2addr.S b/runtime/interpreter/mterp/mips/op_rem_float_2addr.S
new file mode 100644
index 0000000..7f0a932
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_float_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinop2addr.S" {"instr":"JAL(fmodf)"}
diff --git a/runtime/interpreter/mterp/mips/op_rem_int.S b/runtime/interpreter/mterp/mips/op_rem_int.S
new file mode 100644
index 0000000..c2a334a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_int.S
@@ -0,0 +1,5 @@
+#ifdef MIPS32REVGE6
+%include "mips/binop.S" {"instr":"mod a0, a0, a1", "chkzero":"1"}
+#else
+%include "mips/binop.S" {"preinstr":"div zero, a0, a1", "instr":"mfhi a0", "chkzero":"1"}
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_rem_int_2addr.S b/runtime/interpreter/mterp/mips/op_rem_int_2addr.S
new file mode 100644
index 0000000..46c353f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_int_2addr.S
@@ -0,0 +1,5 @@
+#ifdef MIPS32REVGE6
+%include "mips/binop2addr.S" {"instr":"mod a0, a0, a1", "chkzero":"1"}
+#else
+%include "mips/binop2addr.S" {"preinstr":"div zero, a0, a1", "instr":"mfhi a0", "chkzero":"1"}
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_rem_int_lit16.S b/runtime/interpreter/mterp/mips/op_rem_int_lit16.S
new file mode 100644
index 0000000..2894ad3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_int_lit16.S
@@ -0,0 +1,5 @@
+#ifdef MIPS32REVGE6
+%include "mips/binopLit16.S" {"instr":"mod a0, a0, a1", "chkzero":"1"}
+#else
+%include "mips/binopLit16.S" {"preinstr":"div zero, a0, a1", "instr":"mfhi a0", "chkzero":"1"}
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_rem_int_lit8.S b/runtime/interpreter/mterp/mips/op_rem_int_lit8.S
new file mode 100644
index 0000000..582248b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_int_lit8.S
@@ -0,0 +1,5 @@
+#ifdef MIPS32REVGE6
+%include "mips/binopLit8.S" {"instr":"mod a0, a0, a1", "chkzero":"1"}
+#else
+%include "mips/binopLit8.S" {"preinstr":"div zero, a0, a1", "instr":"mfhi a0", "chkzero":"1"}
+#endif
diff --git a/runtime/interpreter/mterp/mips/op_rem_long.S b/runtime/interpreter/mterp/mips/op_rem_long.S
new file mode 100644
index 0000000..e3eb19b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_long.S
@@ -0,0 +1 @@
+%include "mips/binopWide.S" { "result0":"v0", "result1":"v1", "instr":"JAL(__moddi3)", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips/op_rem_long_2addr.S b/runtime/interpreter/mterp/mips/op_rem_long_2addr.S
new file mode 100644
index 0000000..8fc9fdb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rem_long_2addr.S
@@ -0,0 +1 @@
+%include "mips/binopWide2addr.S" { "result0":"v0", "result1":"v1", "instr":"JAL(__moddi3)", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips/op_return.S b/runtime/interpreter/mterp/mips/op_return.S
new file mode 100644
index 0000000..894ae18
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_return.S
@@ -0,0 +1,18 @@
+ /*
+ * Return a 32-bit value.
+ *
+ * for: return, return-object
+ */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ JAL(MterpThreadFenceForConstructor)
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqz ra, 1f
+ JAL(MterpSuspendCheck) # (self)
+1:
+ GET_OPA(a2) # a2 <- AA
+ GET_VREG(v0, a2) # v0 <- vAA
+ move v1, zero
+ b MterpReturn
diff --git a/runtime/interpreter/mterp/mips/op_return_object.S b/runtime/interpreter/mterp/mips/op_return_object.S
new file mode 100644
index 0000000..7350e00
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_return_object.S
@@ -0,0 +1 @@
+%include "mips/op_return.S"
diff --git a/runtime/interpreter/mterp/mips/op_return_void.S b/runtime/interpreter/mterp/mips/op_return_void.S
new file mode 100644
index 0000000..35c1326
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_return_void.S
@@ -0,0 +1,11 @@
+ .extern MterpThreadFenceForConstructor
+ JAL(MterpThreadFenceForConstructor)
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqz ra, 1f
+ JAL(MterpSuspendCheck) # (self)
+1:
+ move v0, zero
+ move v1, zero
+ b MterpReturn
diff --git a/runtime/interpreter/mterp/mips/op_return_void_no_barrier.S b/runtime/interpreter/mterp/mips/op_return_void_no_barrier.S
new file mode 100644
index 0000000..56968b5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_return_void_no_barrier.S
@@ -0,0 +1,9 @@
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqz ra, 1f
+ JAL(MterpSuspendCheck) # (self)
+1:
+ move v0, zero
+ move v1, zero
+ b MterpReturn
diff --git a/runtime/interpreter/mterp/mips/op_return_wide.S b/runtime/interpreter/mterp/mips/op_return_wide.S
new file mode 100644
index 0000000..91d62bf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_return_wide.S
@@ -0,0 +1,16 @@
+ /*
+ * Return a 64-bit value.
+ */
+ /* return-wide vAA */
+ .extern MterpThreadFenceForConstructor
+ JAL(MterpThreadFenceForConstructor)
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqz ra, 1f
+ JAL(MterpSuspendCheck) # (self)
+1:
+ GET_OPA(a2) # a2 <- AA
+ EAS2(a2, rFP, a2) # a2 <- &fp[AA]
+ LOAD64(v0, v1, a2) # v0/v1 <- vAA/vAA+1
+ b MterpReturn
diff --git a/runtime/interpreter/mterp/mips/op_rsub_int.S b/runtime/interpreter/mterp/mips/op_rsub_int.S
new file mode 100644
index 0000000..f7e61bb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rsub_int.S
@@ -0,0 +1,2 @@
+/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
+%include "mips/binopLit16.S" {"instr":"subu a0, a1, a0"}
diff --git a/runtime/interpreter/mterp/mips/op_rsub_int_lit8.S b/runtime/interpreter/mterp/mips/op_rsub_int_lit8.S
new file mode 100644
index 0000000..3968a5e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_rsub_int_lit8.S
@@ -0,0 +1 @@
+%include "mips/binopLit8.S" {"instr":"subu a0, a1, a0"}
diff --git a/runtime/interpreter/mterp/mips/op_sget.S b/runtime/interpreter/mterp/mips/op_sget.S
new file mode 100644
index 0000000..3efcfbb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sget.S
@@ -0,0 +1,25 @@
+%default { "is_object":"0", "helper":"artGet32StaticFromCode" }
+ /*
+ * General SGET handler.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ # op vAA, field /* BBBB */
+ .extern $helper
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ move a2, rSELF # a2 <- self
+ JAL($helper)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA(a2) # a2 <- AA
+ PREFETCH_INST(2)
+ bnez a3, MterpException # bail out
+.if $is_object
+ SET_VREG_OBJECT(v0, a2) # fp[AA] <- v0
+.else
+ SET_VREG(v0, a2) # fp[AA] <- v0
+.endif
+ ADVANCE(2)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_sget_boolean.S b/runtime/interpreter/mterp/mips/op_sget_boolean.S
new file mode 100644
index 0000000..45a5a70
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sget_boolean.S
@@ -0,0 +1 @@
+%include "mips/op_sget.S" {"helper":"artGetBooleanStaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_byte.S b/runtime/interpreter/mterp/mips/op_sget_byte.S
new file mode 100644
index 0000000..319122c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sget_byte.S
@@ -0,0 +1 @@
+%include "mips/op_sget.S" {"helper":"artGetByteStaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_char.S b/runtime/interpreter/mterp/mips/op_sget_char.S
new file mode 100644
index 0000000..7103847
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sget_char.S
@@ -0,0 +1 @@
+%include "mips/op_sget.S" {"helper":"artGetCharStaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_object.S b/runtime/interpreter/mterp/mips/op_sget_object.S
new file mode 100644
index 0000000..b205f51
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sget_object.S
@@ -0,0 +1 @@
+%include "mips/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_short.S b/runtime/interpreter/mterp/mips/op_sget_short.S
new file mode 100644
index 0000000..3301823
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sget_short.S
@@ -0,0 +1 @@
+%include "mips/op_sget.S" {"helper":"artGetShortStaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_wide.S b/runtime/interpreter/mterp/mips/op_sget_wide.S
new file mode 100644
index 0000000..7aee386
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sget_wide.S
@@ -0,0 +1,17 @@
+ /*
+ * 64-bit SGET handler.
+ */
+ # sget-wide vAA, field /* BBBB */
+ .extern artGet64StaticFromCode
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ move a2, rSELF # a2 <- self
+ JAL(artGet64StaticFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ bnez a3, MterpException
+ GET_OPA(a1) # a1 <- AA
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ SET_VREG64(v0, v1, a1) # vAA/vAA+1 <- v0/v1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_shl_int.S b/runtime/interpreter/mterp/mips/op_shl_int.S
new file mode 100644
index 0000000..15cbe94
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shl_int.S
@@ -0,0 +1 @@
+%include "mips/binop.S" {"instr":"sll a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_shl_int_2addr.S b/runtime/interpreter/mterp/mips/op_shl_int_2addr.S
new file mode 100644
index 0000000..ef9bd65
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shl_int_2addr.S
@@ -0,0 +1 @@
+%include "mips/binop2addr.S" {"instr":"sll a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_shl_int_lit8.S b/runtime/interpreter/mterp/mips/op_shl_int_lit8.S
new file mode 100644
index 0000000..d2afb53
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shl_int_lit8.S
@@ -0,0 +1 @@
+%include "mips/binopLit8.S" {"instr":"sll a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_shl_long.S b/runtime/interpreter/mterp/mips/op_shl_long.S
new file mode 100644
index 0000000..0121669
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shl_long.S
@@ -0,0 +1,31 @@
+ /*
+ * Long integer shift. This is different from the generic 32/64-bit
+ * binary operations because vAA/vBB are 64-bit but vCC (the shift
+ * distance) is 32-bit. Also, Dalvik requires us to mask off the low
+ * 6 bits of the shift distance.
+ */
+ /* shl-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(t2) # t2 <- AA
+ and a3, a0, 255 # a3 <- BB
+ srl a0, a0, 8 # a0 <- CC
+ EAS2(a3, rFP, a3) # a3 <- &fp[BB]
+ GET_VREG(a2, a0) # a2 <- vCC
+ LOAD64(a0, a1, a3) # a0/a1 <- vBB/vBB+1
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v1, a2, 0x20 # shift< shift & 0x20
+ sll v0, a0, a2 # rlo<- alo << (shift&31)
+ bnez v1, .L${opcode}_finish
+ not v1, a2 # rhi<- 31-shift (shift is 5b)
+ srl a0, 1
+ srl a0, v1 # alo<- alo >> (32-(shift&31))
+ sll v1, a1, a2 # rhi<- ahi << (shift&31)
+ or v1, a0 # rhi<- rhi | alo
+ SET_VREG64_GOTO(v0, v1, t2, t0) # vAA/vAA+1 <- a0/a1
+%break
+
+.L${opcode}_finish:
+ SET_VREG64_GOTO(zero, v0, t2, t0) # vAA/vAA+1 <- rlo/rhi
diff --git a/runtime/interpreter/mterp/mips/op_shl_long_2addr.S b/runtime/interpreter/mterp/mips/op_shl_long_2addr.S
new file mode 100644
index 0000000..8ce6058
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shl_long_2addr.S
@@ -0,0 +1,27 @@
+ /*
+ * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
+ * 32-bit shift distance.
+ */
+ /* shl-long/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a2, a3) # a2 <- vB
+ EAS2(t2, rFP, rOBJ) # t2 <- &fp[A]
+ LOAD64(a0, a1, t2) # a0/a1 <- vAA/vAA+1
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v1, a2, 0x20 # shift< shift & 0x20
+ sll v0, a0, a2 # rlo<- alo << (shift&31)
+ bnez v1, .L${opcode}_finish
+ not v1, a2 # rhi<- 31-shift (shift is 5b)
+ srl a0, 1
+ srl a0, v1 # alo<- alo >> (32-(shift&31))
+ sll v1, a1, a2 # rhi<- ahi << (shift&31)
+ or v1, a0 # rhi<- rhi | alo
+ SET_VREG64_GOTO(v0, v1, rOBJ, t0) # vAA/vAA+1 <- a0/a1
+%break
+
+.L${opcode}_finish:
+ SET_VREG64_GOTO(zero, v0, rOBJ, t0) # vAA/vAA+1 <- rlo/rhi
diff --git a/runtime/interpreter/mterp/mips/op_shr_int.S b/runtime/interpreter/mterp/mips/op_shr_int.S
new file mode 100644
index 0000000..61108399
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shr_int.S
@@ -0,0 +1 @@
+%include "mips/binop.S" {"instr":"sra a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_shr_int_2addr.S b/runtime/interpreter/mterp/mips/op_shr_int_2addr.S
new file mode 100644
index 0000000..e00ff5b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shr_int_2addr.S
@@ -0,0 +1 @@
+%include "mips/binop2addr.S" {"instr":"sra a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_shr_int_lit8.S b/runtime/interpreter/mterp/mips/op_shr_int_lit8.S
new file mode 100644
index 0000000..d058f58
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shr_int_lit8.S
@@ -0,0 +1 @@
+%include "mips/binopLit8.S" {"instr":"sra a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_shr_long.S b/runtime/interpreter/mterp/mips/op_shr_long.S
new file mode 100644
index 0000000..4c42758
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shr_long.S
@@ -0,0 +1,31 @@
+ /*
+ * Long integer shift. This is different from the generic 32/64-bit
+ * binary operations because vAA/vBB are 64-bit but vCC (the shift
+ * distance) is 32-bit. Also, Dalvik requires us to mask off the low
+ * 6 bits of the shift distance.
+ */
+ /* shr-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(t3) # t3 <- AA
+ and a3, a0, 255 # a3 <- BB
+ srl a0, a0, 8 # a0 <- CC
+ EAS2(a3, rFP, a3) # a3 <- &fp[BB]
+ GET_VREG(a2, a0) # a2 <- vCC
+ LOAD64(a0, a1, a3) # a0/a1 <- vBB/vBB+1
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v0, a2, 0x20 # shift & 0x20
+ sra v1, a1, a2 # rhi<- ahi >> (shift&31)
+ bnez v0, .L${opcode}_finish
+ srl v0, a0, a2 # rlo<- alo >> (shift&31)
+ not a0, a2 # alo<- 31-shift (shift is 5b)
+ sll a1, 1
+ sll a1, a0 # ahi<- ahi << (32-(shift&31))
+ or v0, a1 # rlo<- rlo | ahi
+ SET_VREG64_GOTO(v0, v1, t3, t0) # vAA/VAA+1 <- v0/v0
+%break
+
+.L${opcode}_finish:
+ sra a3, a1, 31 # a3<- sign(ah)
+ SET_VREG64_GOTO(v1, a3, t3, t0) # vAA/VAA+1 <- rlo/rhi
diff --git a/runtime/interpreter/mterp/mips/op_shr_long_2addr.S b/runtime/interpreter/mterp/mips/op_shr_long_2addr.S
new file mode 100644
index 0000000..3adc085
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_shr_long_2addr.S
@@ -0,0 +1,27 @@
+ /*
+ * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
+ * 32-bit shift distance.
+ */
+ /* shr-long/2addr vA, vB */
+ GET_OPA4(t2) # t2 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a2, a3) # a2 <- vB
+ EAS2(t0, rFP, t2) # t0 <- &fp[A]
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v0, a2, 0x20 # shift & 0x20
+ sra v1, a1, a2 # rhi<- ahi >> (shift&31)
+ bnez v0, .L${opcode}_finish
+ srl v0, a0, a2 # rlo<- alo >> (shift&31)
+ not a0, a2 # alo<- 31-shift (shift is 5b)
+ sll a1, 1
+ sll a1, a0 # ahi<- ahi << (32-(shift&31))
+ or v0, a1 # rlo<- rlo | ahi
+ SET_VREG64_GOTO(v0, v1, t2, t0) # vAA/vAA+1 <- a0/a1
+%break
+
+.L${opcode}_finish:
+ sra a3, a1, 31 # a3<- sign(ah)
+ SET_VREG64_GOTO(v1, a3, t2, t0) # vAA/vAA+1 <- rlo/rhi
diff --git a/runtime/interpreter/mterp/mips/op_sparse_switch.S b/runtime/interpreter/mterp/mips/op_sparse_switch.S
new file mode 100644
index 0000000..670f464
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sparse_switch.S
@@ -0,0 +1 @@
+%include "mips/op_packed_switch.S" { "func":"MterpDoSparseSwitch" }
diff --git a/runtime/interpreter/mterp/mips/op_sput.S b/runtime/interpreter/mterp/mips/op_sput.S
new file mode 100644
index 0000000..ee313b9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sput.S
@@ -0,0 +1,19 @@
+%default { "helper":"artSet32StaticFromCode"}
+ /*
+ * General SPUT handler.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ # op vAA, field /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ GET_OPA(a3) # a3 <- AA
+ GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ PREFETCH_INST(2) # load rINST
+ JAL($helper)
+ bnez v0, MterpException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_sput_boolean.S b/runtime/interpreter/mterp/mips/op_sput_boolean.S
new file mode 100644
index 0000000..7909ef5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sput_boolean.S
@@ -0,0 +1 @@
+%include "mips/op_sput.S" {"helper":"artSet8StaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips/op_sput_byte.S b/runtime/interpreter/mterp/mips/op_sput_byte.S
new file mode 100644
index 0000000..7909ef5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sput_byte.S
@@ -0,0 +1 @@
+%include "mips/op_sput.S" {"helper":"artSet8StaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips/op_sput_char.S b/runtime/interpreter/mterp/mips/op_sput_char.S
new file mode 100644
index 0000000..188195c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sput_char.S
@@ -0,0 +1 @@
+%include "mips/op_sput.S" {"helper":"artSet16StaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips/op_sput_object.S b/runtime/interpreter/mterp/mips/op_sput_object.S
new file mode 100644
index 0000000..4f9034e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sput_object.S
@@ -0,0 +1,16 @@
+ /*
+ * General 32-bit SPUT handler.
+ *
+ * for: sput-object,
+ */
+ /* op vAA, field@BBBB */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ JAL(MterpSputObject)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_sput_short.S b/runtime/interpreter/mterp/mips/op_sput_short.S
new file mode 100644
index 0000000..188195c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sput_short.S
@@ -0,0 +1 @@
+%include "mips/op_sput.S" {"helper":"artSet16StaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips/op_sput_wide.S b/runtime/interpreter/mterp/mips/op_sput_wide.S
new file mode 100644
index 0000000..1e11466
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sput_wide.S
@@ -0,0 +1,17 @@
+ /*
+ * 64-bit SPUT handler.
+ */
+ # sput-wide vAA, field /* BBBB */
+ .extern artSet64IndirectStaticFromMterp
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ GET_OPA(a2) # a2 <- AA
+ EAS2(a2, rFP, a2) # a2 <- &fp[AA]
+ move a3, rSELF # a3 <- self
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet64IndirectStaticFromMterp)
+ bnez v0, MterpException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/op_sub_double.S b/runtime/interpreter/mterp/mips/op_sub_double.S
new file mode 100644
index 0000000..9473218
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sub_double.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide.S" {"instr":"sub.d fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_sub_double_2addr.S b/runtime/interpreter/mterp/mips/op_sub_double_2addr.S
new file mode 100644
index 0000000..7ce7c74
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sub_double_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinopWide2addr.S" {"instr":"sub.d fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_sub_float.S b/runtime/interpreter/mterp/mips/op_sub_float.S
new file mode 100644
index 0000000..04650d9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sub_float.S
@@ -0,0 +1 @@
+%include "mips/fbinop.S" {"instr":"sub.s fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_sub_float_2addr.S b/runtime/interpreter/mterp/mips/op_sub_float_2addr.S
new file mode 100644
index 0000000..dfe935c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sub_float_2addr.S
@@ -0,0 +1 @@
+%include "mips/fbinop2addr.S" {"instr":"sub.s fv0, fa0, fa1"}
diff --git a/runtime/interpreter/mterp/mips/op_sub_int.S b/runtime/interpreter/mterp/mips/op_sub_int.S
new file mode 100644
index 0000000..43da1b6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sub_int.S
@@ -0,0 +1 @@
+%include "mips/binop.S" {"instr":"subu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_sub_int_2addr.S b/runtime/interpreter/mterp/mips/op_sub_int_2addr.S
new file mode 100644
index 0000000..cf34aa6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sub_int_2addr.S
@@ -0,0 +1 @@
+%include "mips/binop2addr.S" {"instr":"subu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_sub_long.S b/runtime/interpreter/mterp/mips/op_sub_long.S
new file mode 100644
index 0000000..0f58e8e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sub_long.S
@@ -0,0 +1,8 @@
+/*
+ * For little endian the code sequence looks as follows:
+ * subu v0,a0,a2
+ * subu v1,a1,a3
+ * sltu a0,a0,v0
+ * subu v1,v1,a0
+ */
+%include "mips/binopWide.S" { "result0":"v0", "result1":"v1", "preinstr":"subu v0, a0, a2", "instr":"subu v1, a1, a3; sltu a0, a0, v0; subu v1, v1, a0" }
diff --git a/runtime/interpreter/mterp/mips/op_sub_long_2addr.S b/runtime/interpreter/mterp/mips/op_sub_long_2addr.S
new file mode 100644
index 0000000..aa256c2
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_sub_long_2addr.S
@@ -0,0 +1,4 @@
+/*
+ * See op_sub_long.S for more details
+ */
+%include "mips/binopWide2addr.S" { "result0":"v0", "result1":"v1", "preinstr":"subu v0, a0, a2", "instr":"subu v1, a1, a3; sltu a0, a0, v0; subu v1, v1, a0" }
diff --git a/runtime/interpreter/mterp/mips/op_throw.S b/runtime/interpreter/mterp/mips/op_throw.S
new file mode 100644
index 0000000..adc8b04
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_throw.S
@@ -0,0 +1,11 @@
+ /*
+ * Throw an exception object in the current thread.
+ */
+ /* throw vAA */
+ EXPORT_PC() # exception handler can throw
+ GET_OPA(a2) # a2 <- AA
+ GET_VREG(a1, a2) # a1 <- vAA (exception object)
+ # null object?
+ beqz a1, common_errNullObject # yes, throw an NPE instead
+ sw a1, THREAD_EXCEPTION_OFFSET(rSELF) # thread->exception <- obj
+ b MterpException
diff --git a/runtime/interpreter/mterp/mips/op_unused_3e.S b/runtime/interpreter/mterp/mips/op_unused_3e.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_3e.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_3f.S b/runtime/interpreter/mterp/mips/op_unused_3f.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_3f.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_40.S b/runtime/interpreter/mterp/mips/op_unused_40.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_40.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_41.S b/runtime/interpreter/mterp/mips/op_unused_41.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_41.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_42.S b/runtime/interpreter/mterp/mips/op_unused_42.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_42.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_43.S b/runtime/interpreter/mterp/mips/op_unused_43.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_43.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_73.S b/runtime/interpreter/mterp/mips/op_unused_73.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_73.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_79.S b/runtime/interpreter/mterp/mips/op_unused_79.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_79.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_7a.S b/runtime/interpreter/mterp/mips/op_unused_7a.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_7a.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_f3.S b/runtime/interpreter/mterp/mips/op_unused_f3.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_f3.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_f4.S b/runtime/interpreter/mterp/mips/op_unused_f4.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_f4.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_f5.S b/runtime/interpreter/mterp/mips/op_unused_f5.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_f5.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_f6.S b/runtime/interpreter/mterp/mips/op_unused_f6.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_f6.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_f7.S b/runtime/interpreter/mterp/mips/op_unused_f7.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_f7.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_f8.S b/runtime/interpreter/mterp/mips/op_unused_f8.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_f8.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_f9.S b/runtime/interpreter/mterp/mips/op_unused_f9.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_f9.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_fa.S b/runtime/interpreter/mterp/mips/op_unused_fa.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_fa.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_fb.S b/runtime/interpreter/mterp/mips/op_unused_fb.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_fb.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_fc.S b/runtime/interpreter/mterp/mips/op_unused_fc.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_fc.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_fd.S b/runtime/interpreter/mterp/mips/op_unused_fd.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_fd.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_fe.S b/runtime/interpreter/mterp/mips/op_unused_fe.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_fe.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_unused_ff.S b/runtime/interpreter/mterp/mips/op_unused_ff.S
new file mode 100644
index 0000000..99ef3cf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_unused_ff.S
@@ -0,0 +1 @@
+%include "mips/unused.S"
diff --git a/runtime/interpreter/mterp/mips/op_ushr_int.S b/runtime/interpreter/mterp/mips/op_ushr_int.S
new file mode 100644
index 0000000..b95472b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_ushr_int.S
@@ -0,0 +1 @@
+%include "mips/binop.S" {"instr":"srl a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_ushr_int_2addr.S b/runtime/interpreter/mterp/mips/op_ushr_int_2addr.S
new file mode 100644
index 0000000..fc17778
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_ushr_int_2addr.S
@@ -0,0 +1 @@
+%include "mips/binop2addr.S" {"instr":"srl a0, a0, a1 "}
diff --git a/runtime/interpreter/mterp/mips/op_ushr_int_lit8.S b/runtime/interpreter/mterp/mips/op_ushr_int_lit8.S
new file mode 100644
index 0000000..c82cfba
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_ushr_int_lit8.S
@@ -0,0 +1 @@
+%include "mips/binopLit8.S" {"instr":"srl a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_ushr_long.S b/runtime/interpreter/mterp/mips/op_ushr_long.S
new file mode 100644
index 0000000..2e227a9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_ushr_long.S
@@ -0,0 +1,31 @@
+ /*
+ * Long integer shift. This is different from the generic 32/64-bit
+ * binary operations because vAA/vBB are 64-bit but vCC (the shift
+ * distance) is 32-bit. Also, Dalvik requires us to mask off the low
+ * 6 bits of the shift distance.
+ */
+ /* ushr-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a3, a0, 255 # a3 <- BB
+ srl a0, a0, 8 # a0 <- CC
+ EAS2(a3, rFP, a3) # a3 <- &fp[BB]
+ GET_VREG(a2, a0) # a2 <- vCC
+ LOAD64(a0, a1, a3) # a0/a1 <- vBB/vBB+1
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v0, a2, 0x20 # shift & 0x20
+ srl v1, a1, a2 # rhi<- ahi >> (shift&31)
+ bnez v0, .L${opcode}_finish
+ srl v0, a0, a2 # rlo<- alo >> (shift&31)
+ not a0, a2 # alo<- 31-n (shift is 5b)
+ sll a1, 1
+ sll a1, a0 # ahi<- ahi << (32-(shift&31))
+ or v0, a1 # rlo<- rlo | ahi
+ SET_VREG64_GOTO(v0, v1, rOBJ, t0) # vAA/vAA+1 <- v0/v1
+%break
+
+.L${opcode}_finish:
+ SET_VREG64_GOTO(v1, zero, rOBJ, t0) # vAA/vAA+1 <- rlo/rhi
diff --git a/runtime/interpreter/mterp/mips/op_ushr_long_2addr.S b/runtime/interpreter/mterp/mips/op_ushr_long_2addr.S
new file mode 100644
index 0000000..ccf1f7e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_ushr_long_2addr.S
@@ -0,0 +1,27 @@
+ /*
+ * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
+ * 32-bit shift distance.
+ */
+ /* ushr-long/2addr vA, vB */
+ GET_OPA4(t3) # t3 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a2, a3) # a2 <- vB
+ EAS2(t0, rFP, t3) # t0 <- &fp[A]
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v0, a2, 0x20 # shift & 0x20
+ srl v1, a1, a2 # rhi<- ahi >> (shift&31)
+ bnez v0, .L${opcode}_finish
+ srl v0, a0, a2 # rlo<- alo >> (shift&31)
+ not a0, a2 # alo<- 31-n (shift is 5b)
+ sll a1, 1
+ sll a1, a0 # ahi<- ahi << (32-(shift&31))
+ or v0, a1 # rlo<- rlo | ahi
+ SET_VREG64_GOTO(v0, v1, t3, t0) # vAA/vAA+1 <- a0/a1
+%break
+
+.L${opcode}_finish:
+ SET_VREG64_GOTO(v1, zero, t3, t0) # vAA/vAA+1 <- rlo/rhi
diff --git a/runtime/interpreter/mterp/mips/op_xor_int.S b/runtime/interpreter/mterp/mips/op_xor_int.S
new file mode 100644
index 0000000..6c23f1f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_xor_int.S
@@ -0,0 +1 @@
+%include "mips/binop.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_xor_int_2addr.S b/runtime/interpreter/mterp/mips/op_xor_int_2addr.S
new file mode 100644
index 0000000..5ee1667
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_xor_int_2addr.S
@@ -0,0 +1 @@
+%include "mips/binop2addr.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_xor_int_lit16.S b/runtime/interpreter/mterp/mips/op_xor_int_lit16.S
new file mode 100644
index 0000000..2af37a6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_xor_int_lit16.S
@@ -0,0 +1 @@
+%include "mips/binopLit16.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_xor_int_lit8.S b/runtime/interpreter/mterp/mips/op_xor_int_lit8.S
new file mode 100644
index 0000000..944ed69
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_xor_int_lit8.S
@@ -0,0 +1 @@
+%include "mips/binopLit8.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips/op_xor_long.S b/runtime/interpreter/mterp/mips/op_xor_long.S
new file mode 100644
index 0000000..93f8f70
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_xor_long.S
@@ -0,0 +1 @@
+%include "mips/binopWide.S" {"preinstr":"xor a0, a0, a2", "instr":"xor a1, a1, a3"}
diff --git a/runtime/interpreter/mterp/mips/op_xor_long_2addr.S b/runtime/interpreter/mterp/mips/op_xor_long_2addr.S
new file mode 100644
index 0000000..49f3fa4
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/op_xor_long_2addr.S
@@ -0,0 +1 @@
+%include "mips/binopWide2addr.S" {"preinstr":"xor a0, a0, a2", "instr":"xor a1, a1, a3"}
diff --git a/runtime/interpreter/mterp/mips/unop.S b/runtime/interpreter/mterp/mips/unop.S
new file mode 100644
index 0000000..52a8f0a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/unop.S
@@ -0,0 +1,19 @@
+%default {"preinstr":"", "result0":"a0"}
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+ * int-to-byte, int-to-char, int-to-short
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(t0) # t0 <- A+
+ GET_VREG(a0, a3) # a0 <- vB
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ SET_VREG_GOTO($result0, t0, t1) # vAA <- result0
+ /* 9-10 instructions */
diff --git a/runtime/interpreter/mterp/mips/unopNarrower.S b/runtime/interpreter/mterp/mips/unopNarrower.S
new file mode 100644
index 0000000..9c38bad
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/unopNarrower.S
@@ -0,0 +1,24 @@
+%default {"load":"LOAD64_F(fa0, fa0f, a3)"}
+ /*
+ * Generic 64bit-to-32bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0/a1", where
+ * "result" is a 32-bit quantity in a0.
+ *
+ * For: long-to-float, double-to-int, double-to-float
+ * If hard floating point support is available, use fa0 as the parameter,
+ * except for long-to-float opcode.
+ * (This would work for long-to-int, but that instruction is actually
+ * an exact match for OP_MOVE.)
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(rOBJ) # t1 <- A+
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ $load
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ $instr
+
+.L${opcode}_set_vreg_f:
+ SET_VREG_F(fv0, rOBJ) # vA <- result0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips/unopWide.S b/runtime/interpreter/mterp/mips/unopWide.S
new file mode 100644
index 0000000..fd25dff
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/unopWide.S
@@ -0,0 +1,20 @@
+%default {"preinstr":"", "result0":"a0", "result1":"a1"}
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0/a1".
+ * This could be MIPS instruction or a function call.
+ *
+ * For: neg-long, not-long, neg-double,
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64(a0, a1, a3) # a0/a1 <- vAA
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # a0/a1 <- op, a2-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64($result0, $result1, rOBJ) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-13 instructions */
diff --git a/runtime/interpreter/mterp/mips/unopWider.S b/runtime/interpreter/mterp/mips/unopWider.S
new file mode 100644
index 0000000..1c18837
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/unopWider.S
@@ -0,0 +1,19 @@
+%default {"preinstr":"", "result0":"a0", "result1":"a1"}
+ /*
+ * Generic 32bit-to-64bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0", where
+ * "result" is a 64-bit quantity in a0/a1.
+ *
+ * For: int-to-long
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, a3) # a0 <- vB
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64($result0, $result1, rOBJ) # vA/vA+1 <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 10-11 instructions */
diff --git a/runtime/interpreter/mterp/mips/unused.S b/runtime/interpreter/mterp/mips/unused.S
new file mode 100644
index 0000000..ffa00be
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/unused.S
@@ -0,0 +1,4 @@
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
diff --git a/runtime/interpreter/mterp/mips/zcmp.S b/runtime/interpreter/mterp/mips/zcmp.S
new file mode 100644
index 0000000..1fa1385
--- /dev/null
+++ b/runtime/interpreter/mterp/mips/zcmp.S
@@ -0,0 +1,32 @@
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ GET_OPA(a0) # a0 <- AA
+ GET_VREG(a2, a0) # a2 <- vAA
+ FETCH_S(rINST, 1) # rINST <- branch offset, in code units
+ b${revcmp} a2, zero, 1f # branch to 1 if comparison failed
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a1, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 3f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+3:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/alt_stub.S b/runtime/interpreter/mterp/mips64/alt_stub.S
new file mode 100644
index 0000000..bd76a1b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/alt_stub.S
@@ -0,0 +1,14 @@
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (${opnum} * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
diff --git a/runtime/interpreter/mterp/mips64/bincmp.S b/runtime/interpreter/mterp/mips64/bincmp.S
new file mode 100644
index 0000000..d39c900
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/bincmp.S
@@ -0,0 +1,32 @@
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-le" you would use "le".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ lh a4, 2(rPC) # a4 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+
+ b${condition}c a0, a1, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + CCCC * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # CCCC * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/binop.S b/runtime/interpreter/mterp/mips64/binop.S
new file mode 100644
index 0000000..fab48b7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/binop.S
@@ -0,0 +1,30 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if $chkzero
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG $result, a4 # vAA <- $result
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/binop2addr.S b/runtime/interpreter/mterp/mips64/binop2addr.S
new file mode 100644
index 0000000..1ae73f5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/binop2addr.S
@@ -0,0 +1,30 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if $chkzero
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG $result, a2 # vA <- $result
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/binopLit16.S b/runtime/interpreter/mterp/mips64/binopLit16.S
new file mode 100644
index 0000000..9257758
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/binopLit16.S
@@ -0,0 +1,28 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CCCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ lh a1, 2(rPC) # a1 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ .if $chkzero
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG $result, a2 # vA <- $result
+ GOTO_OPCODE v0 # jump to next instruction
+
diff --git a/runtime/interpreter/mterp/mips64/binopLit8.S b/runtime/interpreter/mterp/mips64/binopLit8.S
new file mode 100644
index 0000000..f4a0bba
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/binopLit8.S
@@ -0,0 +1,29 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if $chkzero
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG $result, a2 # vAA <- $result
+ GOTO_OPCODE v0 # jump to next instruction
+
diff --git a/runtime/interpreter/mterp/mips64/binopWide.S b/runtime/interpreter/mterp/mips64/binopWide.S
new file mode 100644
index 0000000..732f0d6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/binopWide.S
@@ -0,0 +1,30 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if $chkzero
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE $result, a4 # vAA <- $result
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/binopWide2addr.S b/runtime/interpreter/mterp/mips64/binopWide2addr.S
new file mode 100644
index 0000000..45d8d82
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/binopWide2addr.S
@@ -0,0 +1,30 @@
+%default {"preinstr":"", "result":"a0", "chkzero":"0"}
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if $chkzero
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ $preinstr # optional op
+ $instr # $result <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE $result, a2 # vA <- $result
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/entry.S b/runtime/interpreter/mterp/mips64/entry.S
new file mode 100644
index 0000000..ae6c26b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/entry.S
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Interpreter entry point.
+ */
+
+ .set reorder
+
+ .text
+ .global ExecuteMterpImpl
+ .type ExecuteMterpImpl, %function
+ .balign 16
+/*
+ * On entry:
+ * a0 Thread* self
+ * a1 code_item
+ * a2 ShadowFrame
+ * a3 JValue* result_register
+ *
+ */
+ExecuteMterpImpl:
+ .cfi_startproc
+ .cpsetup t9, t8, ExecuteMterpImpl
+
+ .cfi_def_cfa sp, 0
+ daddu sp, sp, -STACK_SIZE
+ .cfi_adjust_cfa_offset STACK_SIZE
+
+ sd t8, STACK_OFFSET_GP(sp)
+ .cfi_rel_offset 28, STACK_OFFSET_GP
+ sd ra, STACK_OFFSET_RA(sp)
+ .cfi_rel_offset 31, STACK_OFFSET_RA
+
+ sd s0, STACK_OFFSET_S0(sp)
+ .cfi_rel_offset 16, STACK_OFFSET_S0
+ sd s1, STACK_OFFSET_S1(sp)
+ .cfi_rel_offset 17, STACK_OFFSET_S1
+ sd s2, STACK_OFFSET_S2(sp)
+ .cfi_rel_offset 18, STACK_OFFSET_S2
+ sd s3, STACK_OFFSET_S3(sp)
+ .cfi_rel_offset 19, STACK_OFFSET_S3
+ sd s4, STACK_OFFSET_S4(sp)
+ .cfi_rel_offset 20, STACK_OFFSET_S4
+ sd s5, STACK_OFFSET_S5(sp)
+ .cfi_rel_offset 21, STACK_OFFSET_S5
+
+ /* Remember the return register */
+ sd a3, SHADOWFRAME_RESULT_REGISTER_OFFSET(a2)
+
+ /* Remember the code_item */
+ sd a1, SHADOWFRAME_CODE_ITEM_OFFSET(a2)
+
+ /* set up "named" registers */
+ move rSELF, a0
+ daddu rFP, a2, SHADOWFRAME_VREGS_OFFSET
+ lw v0, SHADOWFRAME_NUMBER_OF_VREGS_OFFSET(a2)
+ dlsa rREFS, v0, rFP, 2
+ daddu rPC, a1, CODEITEM_INSNS_OFFSET
+ lw v0, SHADOWFRAME_DEX_PC_OFFSET(a2)
+ dlsa rPC, v0, rPC, 1
+ EXPORT_PC
+
+ /* Starting ibase */
+ REFRESH_IBASE
+
+ /* start executing the instruction at rPC */
+ FETCH_INST
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+ /* NOTE: no fallthrough */
diff --git a/runtime/interpreter/mterp/mips64/fallback.S b/runtime/interpreter/mterp/mips64/fallback.S
new file mode 100644
index 0000000..560b994
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/fallback.S
@@ -0,0 +1,2 @@
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
diff --git a/runtime/interpreter/mterp/mips64/fbinop.S b/runtime/interpreter/mterp/mips64/fbinop.S
new file mode 100644
index 0000000..f19dd1c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/fbinop.S
@@ -0,0 +1,18 @@
+%default {}
+ /*:
+ * Generic 32-bit floating-point operation.
+ *
+ * For: add-float, sub-float, mul-float, div-float.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f0, a2 # f0 <- vBB
+ GET_VREG_FLOAT f1, a3 # f1 <- vCC
+ $instr # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/fbinop2addr.S b/runtime/interpreter/mterp/mips64/fbinop2addr.S
new file mode 100644
index 0000000..2e2cd7e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/fbinop2addr.S
@@ -0,0 +1,17 @@
+%default {}
+ /*:
+ * Generic 32-bit "/2addr" floating-point operation.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_FLOAT f0, a2 # f0 <- vA
+ GET_VREG_FLOAT f1, a3 # f1 <- vB
+ $instr # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/fbinopWide.S b/runtime/interpreter/mterp/mips64/fbinopWide.S
new file mode 100644
index 0000000..8915c94
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/fbinopWide.S
@@ -0,0 +1,18 @@
+%default {}
+ /*:
+ * Generic 64-bit floating-point operation.
+ *
+ * For: add-double, sub-double, mul-double, div-double.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f0, a2 # f0 <- vBB
+ GET_VREG_DOUBLE f1, a3 # f1 <- vCC
+ $instr # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/fbinopWide2addr.S b/runtime/interpreter/mterp/mips64/fbinopWide2addr.S
new file mode 100644
index 0000000..a3f4eaa
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/fbinopWide2addr.S
@@ -0,0 +1,17 @@
+%default {}
+ /*:
+ * Generic 64-bit "/2addr" floating-point operation.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr, div-double/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_DOUBLE f0, a2 # f0 <- vA
+ GET_VREG_DOUBLE f1, a3 # f1 <- vB
+ $instr # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/fcmp.S b/runtime/interpreter/mterp/mips64/fcmp.S
new file mode 100644
index 0000000..2e1a3e4
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/fcmp.S
@@ -0,0 +1,32 @@
+%default {}
+ /*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * For: cmpl-float, cmpg-float
+ */
+ /* op vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f0, a2 # f0 <- vBB
+ GET_VREG_FLOAT f1, a3 # f1 <- vCC
+ cmp.eq.s f2, f0, f1
+ li a0, 0
+ bc1nez f2, 1f # done if vBB == vCC (ordered)
+ .if $gt_bias
+ cmp.lt.s f2, f0, f1
+ li a0, -1
+ bc1nez f2, 1f # done if vBB < vCC (ordered)
+ li a0, 1 # vBB > vCC or unordered
+ .else
+ cmp.lt.s f2, f1, f0
+ li a0, 1
+ bc1nez f2, 1f # done if vBB > vCC (ordered)
+ li a0, -1 # vBB < vCC or unordered
+ .endif
+1:
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/fcmpWide.S b/runtime/interpreter/mterp/mips64/fcmpWide.S
new file mode 100644
index 0000000..2a3a341
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/fcmpWide.S
@@ -0,0 +1,32 @@
+%default {}
+ /*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * For: cmpl-double, cmpg-double
+ */
+ /* op vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f0, a2 # f0 <- vBB
+ GET_VREG_DOUBLE f1, a3 # f1 <- vCC
+ cmp.eq.d f2, f0, f1
+ li a0, 0
+ bc1nez f2, 1f # done if vBB == vCC (ordered)
+ .if $gt_bias
+ cmp.lt.d f2, f0, f1
+ li a0, -1
+ bc1nez f2, 1f # done if vBB < vCC (ordered)
+ li a0, 1 # vBB > vCC or unordered
+ .else
+ cmp.lt.d f2, f1, f0
+ li a0, 1
+ bc1nez f2, 1f # done if vBB > vCC (ordered)
+ li a0, -1 # vBB < vCC or unordered
+ .endif
+1:
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/fcvtFooter.S b/runtime/interpreter/mterp/mips64/fcvtFooter.S
new file mode 100644
index 0000000..06e9507
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/fcvtFooter.S
@@ -0,0 +1,18 @@
+ /*
+ * Stores a specified register containing the result of conversion
+ * from or to a floating-point type and jumps to the next instruction.
+ *
+ * Expects a1 to contain the destination Dalvik register number.
+ * a1 is set up by fcvtHeader.S.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ *
+ * Note that this file can't be included after a break in other files
+ * and in those files its contents appear as a copy.
+ * See: float-to-int, float-to-long, double-to-int, double-to-long.
+ */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG$suffix $valreg, a1
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/fcvtHeader.S b/runtime/interpreter/mterp/mips64/fcvtHeader.S
new file mode 100644
index 0000000..8742e42
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/fcvtHeader.S
@@ -0,0 +1,15 @@
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG$suffix $valreg, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
diff --git a/runtime/interpreter/mterp/mips64/footer.S b/runtime/interpreter/mterp/mips64/footer.S
new file mode 100644
index 0000000..1a2e22b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/footer.S
@@ -0,0 +1,154 @@
+/*
+ * We've detected a condition that will result in an exception, but the exception
+ * has not yet been thrown. Just bail out to the reference interpreter to deal with it.
+ * TUNING: for consistency, we may want to just go ahead and handle these here.
+ */
+
+ .extern MterpLogDivideByZeroException
+common_errDivideByZero:
+ EXPORT_PC
+#if MTERP_LOGGING
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpLogDivideByZeroException
+#endif
+ b MterpCommonFallback
+
+ .extern MterpLogArrayIndexException
+common_errArrayIndex:
+ EXPORT_PC
+#if MTERP_LOGGING
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpLogArrayIndexException
+#endif
+ b MterpCommonFallback
+
+ .extern MterpLogNullObjectException
+common_errNullObject:
+ EXPORT_PC
+#if MTERP_LOGGING
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpLogNullObjectException
+#endif
+ b MterpCommonFallback
+
+/*
+ * If we're here, something is out of the ordinary. If there is a pending
+ * exception, handle it. Otherwise, roll back and retry with the reference
+ * interpreter.
+ */
+MterpPossibleException:
+ ld a0, THREAD_EXCEPTION_OFFSET(rSELF)
+ beqzc a0, MterpFallback # If not, fall back to reference interpreter.
+ /* intentional fallthrough - handle pending exception. */
+/*
+ * On return from a runtime helper routine, we've found a pending exception.
+ * Can we handle it here - or need to bail out to caller?
+ *
+ */
+ .extern MterpHandleException
+MterpException:
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpHandleException # (self, shadow_frame)
+ beqzc v0, MterpExceptionReturn # no local catch, back to caller.
+ ld a0, OFF_FP_CODE_ITEM(rFP)
+ lwu a1, OFF_FP_DEX_PC(rFP)
+ REFRESH_IBASE
+ daddu rPC, a0, CODEITEM_INSNS_OFFSET
+ dlsa rPC, a1, rPC, 1 # generate new dex_pc_ptr
+ sd rPC, OFF_FP_DEX_PC_PTR(rFP)
+ /* resume execution at catch block */
+ FETCH_INST
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+ /* NOTE: no fallthrough */
+
+/*
+ * Check for suspend check request. Assumes rINST already loaded, rPC advanced and
+ * still needs to get the opcode and branch to it, and flags are in ra.
+ */
+ .extern MterpSuspendCheck
+MterpCheckSuspendAndContinue:
+ REFRESH_IBASE
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ bnez ra, check1
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+check1:
+ EXPORT_PC
+ move a0, rSELF
+ jal MterpSuspendCheck # (self)
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/*
+ * Bail out to reference interpreter.
+ */
+ .extern MterpLogFallback
+MterpFallback:
+ EXPORT_PC
+#if MTERP_LOGGING
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpLogFallback
+#endif
+MterpCommonFallback:
+ li v0, 0 # signal retry with reference interpreter.
+ b MterpDone
+
+/*
+ * We pushed some registers on the stack in ExecuteMterpImpl, then saved
+ * SP and RA. Here we restore SP, restore the registers, and then restore
+ * RA to PC.
+ *
+ * On entry:
+ * uint32_t* rFP (should still be live, pointer to base of vregs)
+ */
+MterpExceptionReturn:
+ li v0, 1 # signal return to caller.
+ b MterpDone
+/*
+ * Returned value is expected in a0 and if it's not 64-bit, the 32 most
+ * significant bits of a0 must be 0.
+ */
+MterpReturn:
+ ld a2, OFF_FP_RESULT_REGISTER(rFP)
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ sd a0, 0(a2)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, check2
+ jal MterpSuspendCheck # (self)
+check2:
+ li v0, 1 # signal return to caller.
+MterpDone:
+ ld s5, STACK_OFFSET_S5(sp)
+ .cfi_restore 21
+ ld s4, STACK_OFFSET_S4(sp)
+ .cfi_restore 20
+ ld s3, STACK_OFFSET_S3(sp)
+ .cfi_restore 19
+ ld s2, STACK_OFFSET_S2(sp)
+ .cfi_restore 18
+ ld s1, STACK_OFFSET_S1(sp)
+ .cfi_restore 17
+ ld s0, STACK_OFFSET_S0(sp)
+ .cfi_restore 16
+
+ ld ra, STACK_OFFSET_RA(sp)
+ .cfi_restore 31
+
+ ld t8, STACK_OFFSET_GP(sp)
+ .cpreturn
+ .cfi_restore 28
+
+ .set noreorder
+ jr ra
+ daddu sp, sp, STACK_SIZE
+ .cfi_adjust_cfa_offset -STACK_SIZE
+
+ .cfi_endproc
+ .size ExecuteMterpImpl, .-ExecuteMterpImpl
diff --git a/runtime/interpreter/mterp/mips64/header.S b/runtime/interpreter/mterp/mips64/header.S
new file mode 100644
index 0000000..4c3ca9e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/header.S
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <machine/regdef.h>
+
+/* TODO: add the missing file and use its FP register definitions. */
+/* #include <machine/fpregdef.h> */
+/* FP register definitions */
+#define f0 $$f0
+#define f1 $$f1
+#define f2 $$f2
+#define f3 $$f3
+#define f12 $$f12
+#define f13 $$f13
+
+/*
+ * It looks like the GNU assembler currently does not support the blec and bgtc
+ * idioms, which should translate into bgec and bltc respectively with swapped
+ * left and right register operands.
+ * TODO: remove these macros when the assembler is fixed.
+ */
+.macro blec lreg, rreg, target
+ bgec \rreg, \lreg, \target
+.endm
+.macro bgtc lreg, rreg, target
+ bltc \rreg, \lreg, \target
+.endm
+
+/*
+Mterp and MIPS64 notes:
+
+The following registers have fixed assignments:
+
+ reg nick purpose
+ s0 rPC interpreted program counter, used for fetching instructions
+ s1 rFP interpreted frame pointer, used for accessing locals and args
+ s2 rSELF self (Thread) pointer
+ s3 rINST first 16-bit code unit of current instruction
+ s4 rIBASE interpreted instruction base pointer, used for computed goto
+ s5 rREFS base of object references in shadow frame (ideally, we'll get rid of this later).
+*/
+
+/* During bringup, we'll use the shadow frame model instead of rFP */
+/* single-purpose registers, given names for clarity */
+#define rPC s0
+#define rFP s1
+#define rSELF s2
+#define rINST s3
+#define rIBASE s4
+#define rREFS s5
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "asm_support.h"
+
+/*
+ * Instead of holding a pointer to the shadow frame, we keep rFP at the base of the vregs. So,
+ * to access other shadow frame fields, we need to use a backwards offset. Define those here.
+ */
+#define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET)
+#define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET)
+#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET)
+#define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET)
+#define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET)
+#define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET)
+#define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET)
+#define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET)
+#define OFF_FP_SHADOWFRAME (-SHADOWFRAME_VREGS_OFFSET)
+
+/*
+ *
+ * The reference interpreter performs explicit suspect checks, which is somewhat wasteful.
+ * Dalvik's interpreter folded suspend checks into the jump table mechanism, and eventually
+ * mterp should do so as well.
+ */
+#define MTERP_SUSPEND 0
+
+#define MTERP_LOGGING 0
+
+/*
+ * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must
+ * be done *before* something throws.
+ *
+ * It's okay to do this more than once.
+ *
+ * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped
+ * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction
+ * offset into the code_items_[] array. For effiency, we will "export" the
+ * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC
+ * to convert to a dex pc when needed.
+ */
+.macro EXPORT_PC
+ sd rPC, OFF_FP_DEX_PC_PTR(rFP)
+.endm
+
+/*
+ * Refresh handler table.
+ */
+.macro REFRESH_IBASE
+ ld rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
+.endm
+
+/*
+ * Fetch the next instruction from rPC into rINST. Does not advance rPC.
+ */
+.macro FETCH_INST
+ lhu rINST, 0(rPC)
+.endm
+
+/* Advance rPC by some number of code units. */
+.macro ADVANCE count
+ daddu rPC, rPC, (\count) * 2
+.endm
+
+/*
+ * Fetch the next instruction from the specified offset. Advances rPC
+ * to point to the next instruction.
+ *
+ * This must come AFTER anything that can throw an exception, or the
+ * exception catch may miss. (This also implies that it must come after
+ * EXPORT_PC.)
+ */
+.macro FETCH_ADVANCE_INST count
+ ADVANCE \count
+ FETCH_INST
+.endm
+
+/*
+ * Similar to FETCH_ADVANCE_INST, but does not update rPC. Used to load
+ * rINST ahead of possible exception point. Be sure to manually advance rPC
+ * later.
+ */
+.macro PREFETCH_INST count
+ lhu rINST, ((\count) * 2)(rPC)
+.endm
+
+/*
+ * Put the instruction's opcode field into the specified register.
+ */
+.macro GET_INST_OPCODE reg
+ and \reg, rINST, 255
+.endm
+
+/*
+ * Begin executing the opcode in _reg.
+ */
+.macro GOTO_OPCODE reg
+ .set noat
+ sll AT, \reg, 7
+ daddu AT, rIBASE, AT
+ jic AT, 0
+ .set at
+.endm
+
+/*
+ * Get/set the 32-bit value from a Dalvik register.
+ * Note, GET_VREG does sign extension to 64 bits while
+ * GET_VREG_U does zero extension to 64 bits.
+ * One is useful for arithmetic while the other is
+ * useful for storing the result value as 64-bit.
+ */
+.macro GET_VREG reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lw \reg, 0(AT)
+ .set at
+.endm
+.macro GET_VREG_U reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lwu \reg, 0(AT)
+ .set at
+.endm
+.macro GET_VREG_FLOAT reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lwc1 \reg, 0(AT)
+ .set at
+.endm
+.macro SET_VREG reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ sw \reg, 0(AT)
+ dlsa AT, \vreg, rREFS, 2
+ sw zero, 0(AT)
+ .set at
+.endm
+.macro SET_VREG_OBJECT reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ sw \reg, 0(AT)
+ dlsa AT, \vreg, rREFS, 2
+ sw \reg, 0(AT)
+ .set at
+.endm
+.macro SET_VREG_FLOAT reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ swc1 \reg, 0(AT)
+ dlsa AT, \vreg, rREFS, 2
+ sw zero, 0(AT)
+ .set at
+.endm
+
+/*
+ * Get/set the 64-bit value from a Dalvik register.
+ * Avoid unaligned memory accesses.
+ * Note, SET_VREG_WIDE clobbers the register containing the value being stored.
+ * Note, SET_VREG_DOUBLE clobbers the register containing the Dalvik register number.
+ */
+.macro GET_VREG_WIDE reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lw \reg, 0(AT)
+ lw AT, 4(AT)
+ dinsu \reg, AT, 32, 32
+ .set at
+.endm
+.macro GET_VREG_DOUBLE reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lwc1 \reg, 0(AT)
+ lw AT, 4(AT)
+ mthc1 AT, \reg
+ .set at
+.endm
+.macro SET_VREG_WIDE reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ sw \reg, 0(AT)
+ drotr32 \reg, \reg, 0
+ sw \reg, 4(AT)
+ dlsa AT, \vreg, rREFS, 2
+ sw zero, 0(AT)
+ sw zero, 4(AT)
+ .set at
+.endm
+.macro SET_VREG_DOUBLE reg, vreg
+ .set noat
+ dlsa AT, \vreg, rREFS, 2
+ sw zero, 0(AT)
+ sw zero, 4(AT)
+ dlsa AT, \vreg, rFP, 2
+ swc1 \reg, 0(AT)
+ mfhc1 \vreg, \reg
+ sw \vreg, 4(AT)
+ .set at
+.endm
+
+/*
+ * On-stack offsets for spilling/unspilling callee-saved registers
+ * and the frame size.
+ */
+#define STACK_OFFSET_RA 0
+#define STACK_OFFSET_GP 8
+#define STACK_OFFSET_S0 16
+#define STACK_OFFSET_S1 24
+#define STACK_OFFSET_S2 32
+#define STACK_OFFSET_S3 40
+#define STACK_OFFSET_S4 48
+#define STACK_OFFSET_S5 56
+#define STACK_SIZE 64
+
+/* Constants for float/double_to_int/long conversions */
+#define INT_MIN 0x80000000
+#define INT_MIN_AS_FLOAT 0xCF000000
+#define INT_MIN_AS_DOUBLE 0xC1E0000000000000
+#define LONG_MIN 0x8000000000000000
+#define LONG_MIN_AS_FLOAT 0xDF000000
+#define LONG_MIN_AS_DOUBLE 0xC3E0000000000000
diff --git a/runtime/interpreter/mterp/mips64/invoke.S b/runtime/interpreter/mterp/mips64/invoke.S
new file mode 100644
index 0000000..4ae4fb1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/invoke.S
@@ -0,0 +1,17 @@
+%default { "helper":"UndefinedInvokeHandler" }
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern $helper
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal $helper
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
diff --git a/runtime/interpreter/mterp/mips64/op_add_double.S b/runtime/interpreter/mterp/mips64/op_add_double.S
new file mode 100644
index 0000000..1520e32
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_double.S
@@ -0,0 +1 @@
+%include "mips64/fbinopWide.S" {"instr":"add.d f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_add_double_2addr.S b/runtime/interpreter/mterp/mips64/op_add_double_2addr.S
new file mode 100644
index 0000000..c14382e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_double_2addr.S
@@ -0,0 +1 @@
+%include "mips64/fbinopWide2addr.S" {"instr":"add.d f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_add_float.S b/runtime/interpreter/mterp/mips64/op_add_float.S
new file mode 100644
index 0000000..c6ed558
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_float.S
@@ -0,0 +1 @@
+%include "mips64/fbinop.S" {"instr":"add.s f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_add_float_2addr.S b/runtime/interpreter/mterp/mips64/op_add_float_2addr.S
new file mode 100644
index 0000000..4c20547
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_float_2addr.S
@@ -0,0 +1 @@
+%include "mips64/fbinop2addr.S" {"instr":"add.s f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_add_int.S b/runtime/interpreter/mterp/mips64/op_add_int.S
new file mode 100644
index 0000000..6e569de
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"addu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_add_int_2addr.S b/runtime/interpreter/mterp/mips64/op_add_int_2addr.S
new file mode 100644
index 0000000..2a84124
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"addu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_add_int_lit16.S b/runtime/interpreter/mterp/mips64/op_add_int_lit16.S
new file mode 100644
index 0000000..94b053b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_int_lit16.S
@@ -0,0 +1 @@
+%include "mips64/binopLit16.S" {"instr":"addu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_add_int_lit8.S b/runtime/interpreter/mterp/mips64/op_add_int_lit8.S
new file mode 100644
index 0000000..3b6d734
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"addu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_add_long.S b/runtime/interpreter/mterp/mips64/op_add_long.S
new file mode 100644
index 0000000..c8d702f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"daddu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_add_long_2addr.S b/runtime/interpreter/mterp/mips64/op_add_long_2addr.S
new file mode 100644
index 0000000..928ff54
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_add_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"daddu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_aget.S b/runtime/interpreter/mterp/mips64/op_aget.S
new file mode 100644
index 0000000..0472a06
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aget.S
@@ -0,0 +1,29 @@
+%default { "load":"lw", "shift":"2", "data_offset":"MIRROR_INT_ARRAY_DATA_OFFSET" }
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if $shift
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, $shift # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ $load a2, $data_offset(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a2, a4 # vAA <- a2
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_aget_boolean.S b/runtime/interpreter/mterp/mips64/op_aget_boolean.S
new file mode 100644
index 0000000..d5be01b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aget_boolean.S
@@ -0,0 +1 @@
+%include "mips64/op_aget.S" { "load":"lbu", "shift":"0", "data_offset":"MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips64/op_aget_byte.S b/runtime/interpreter/mterp/mips64/op_aget_byte.S
new file mode 100644
index 0000000..084de8d
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aget_byte.S
@@ -0,0 +1 @@
+%include "mips64/op_aget.S" { "load":"lb", "shift":"0", "data_offset":"MIRROR_BYTE_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips64/op_aget_char.S b/runtime/interpreter/mterp/mips64/op_aget_char.S
new file mode 100644
index 0000000..6c99ed5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aget_char.S
@@ -0,0 +1 @@
+%include "mips64/op_aget.S" { "load":"lhu", "shift":"1", "data_offset":"MIRROR_CHAR_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips64/op_aget_object.S b/runtime/interpreter/mterp/mips64/op_aget_object.S
new file mode 100644
index 0000000..6374a05
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aget_object.S
@@ -0,0 +1,21 @@
+ /*
+ * Array object get. vAA <- vBB[vCC].
+ *
+ * for: aget-object
+ */
+ /* op vAA, vBB, vCC */
+ .extern artAGetObjectFromMterp
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ EXPORT_PC
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ jal artAGetObjectFromMterp # (array, index)
+ ld a1, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a4, rINST, 8 # a4 <- AA
+ PREFETCH_INST 2
+ bnez a1, MterpException
+ SET_VREG_OBJECT v0, a4 # vAA <- v0
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_aget_short.S b/runtime/interpreter/mterp/mips64/op_aget_short.S
new file mode 100644
index 0000000..0158b0a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aget_short.S
@@ -0,0 +1 @@
+%include "mips64/op_aget.S" { "load":"lh", "shift":"1", "data_offset":"MIRROR_SHORT_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips64/op_aget_wide.S b/runtime/interpreter/mterp/mips64/op_aget_wide.S
new file mode 100644
index 0000000..0945aca
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aget_wide.S
@@ -0,0 +1,21 @@
+ /*
+ * Array get, 64 bits. vAA <- vBB[vCC].
+ *
+ */
+ /* aget-wide vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ dlsa a0, a1, a0, 3 # a0 <- arrayObj + index*width
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ lw a2, MIRROR_WIDE_ARRAY_DATA_OFFSET(a0)
+ lw a3, (MIRROR_WIDE_ARRAY_DATA_OFFSET+4)(a0)
+ dinsu a2, a3, 32, 32 # a2 <- vBB[vCC]
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a2, a4 # vAA <- a2
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_and_int.S b/runtime/interpreter/mterp/mips64/op_and_int.S
new file mode 100644
index 0000000..f0792a8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_and_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_and_int_2addr.S b/runtime/interpreter/mterp/mips64/op_and_int_2addr.S
new file mode 100644
index 0000000..08dc615
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_and_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_and_int_lit16.S b/runtime/interpreter/mterp/mips64/op_and_int_lit16.S
new file mode 100644
index 0000000..65d28ad
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_and_int_lit16.S
@@ -0,0 +1 @@
+%include "mips64/binopLit16.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_and_int_lit8.S b/runtime/interpreter/mterp/mips64/op_and_int_lit8.S
new file mode 100644
index 0000000..ab84bb7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_and_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_and_long.S b/runtime/interpreter/mterp/mips64/op_and_long.S
new file mode 100644
index 0000000..e383ba0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_and_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_and_long_2addr.S b/runtime/interpreter/mterp/mips64/op_and_long_2addr.S
new file mode 100644
index 0000000..f863bb9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_and_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"and a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_aput.S b/runtime/interpreter/mterp/mips64/op_aput.S
new file mode 100644
index 0000000..9bfda97
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aput.S
@@ -0,0 +1,29 @@
+%default { "store":"sw", "shift":"2", "data_offset":"MIRROR_INT_ARRAY_DATA_OFFSET" }
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if $shift
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, $shift # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_VREG a2, a4 # a2 <- vAA
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ $store a2, $data_offset(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_aput_boolean.S b/runtime/interpreter/mterp/mips64/op_aput_boolean.S
new file mode 100644
index 0000000..6707a1f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aput_boolean.S
@@ -0,0 +1 @@
+%include "mips64/op_aput.S" { "store":"sb", "shift":"0", "data_offset":"MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips64/op_aput_byte.S b/runtime/interpreter/mterp/mips64/op_aput_byte.S
new file mode 100644
index 0000000..7b9ce48
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aput_byte.S
@@ -0,0 +1 @@
+%include "mips64/op_aput.S" { "store":"sb", "shift":"0", "data_offset":"MIRROR_BYTE_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips64/op_aput_char.S b/runtime/interpreter/mterp/mips64/op_aput_char.S
new file mode 100644
index 0000000..82bc8f7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aput_char.S
@@ -0,0 +1 @@
+%include "mips64/op_aput.S" { "store":"sh", "shift":"1", "data_offset":"MIRROR_CHAR_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips64/op_aput_object.S b/runtime/interpreter/mterp/mips64/op_aput_object.S
new file mode 100644
index 0000000..b132456
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aput_object.S
@@ -0,0 +1,14 @@
+ /*
+ * Store an object into an array. vBB[vCC] <- vAA.
+ */
+ /* op vAA, vBB, vCC */
+ .extern MterpAputObject
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ jal MterpAputObject
+ beqzc v0, MterpPossibleException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_aput_short.S b/runtime/interpreter/mterp/mips64/op_aput_short.S
new file mode 100644
index 0000000..a7af294
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aput_short.S
@@ -0,0 +1 @@
+%include "mips64/op_aput.S" { "store":"sh", "shift":"1", "data_offset":"MIRROR_SHORT_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/mips64/op_aput_wide.S b/runtime/interpreter/mterp/mips64/op_aput_wide.S
new file mode 100644
index 0000000..a1d7a3b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_aput_wide.S
@@ -0,0 +1,21 @@
+ /*
+ * Array put, 64 bits. vBB[vCC] <- vAA.
+ *
+ */
+ /* aput-wide vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ dlsa a0, a1, a0, 3 # a0 <- arrayObj + index*width
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ GET_VREG_WIDE a2, a4 # a2 <- vAA
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ sw a2, MIRROR_WIDE_ARRAY_DATA_OFFSET(a0)
+ dsrl32 a2, a2, 0
+ sw a2, (MIRROR_WIDE_ARRAY_DATA_OFFSET+4)(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_array_length.S b/runtime/interpreter/mterp/mips64/op_array_length.S
new file mode 100644
index 0000000..2d9e172
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_array_length.S
@@ -0,0 +1,12 @@
+ /*
+ * Return the length of an array.
+ */
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a0, a1 # a0 <- vB (object ref)
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a0, common_errNullObject # yup, fail
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- array length
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a3, a2 # vB <- length
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_check_cast.S b/runtime/interpreter/mterp/mips64/op_check_cast.S
new file mode 100644
index 0000000..472595d
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_check_cast.S
@@ -0,0 +1,17 @@
+ /*
+ * Check to see if a cast from one class to another is allowed.
+ */
+ /* check-cast vAA, class//BBBB */
+ .extern MterpCheckCast
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- BBBB
+ srl a1, rINST, 8 # a1 <- AA
+ dlsa a1, a1, rFP, 2 # a1 <- &object
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ jal MterpCheckCast # (index, &obj, method, self)
+ PREFETCH_INST 2
+ bnez v0, MterpPossibleException
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_cmp_long.S b/runtime/interpreter/mterp/mips64/op_cmp_long.S
new file mode 100644
index 0000000..6e9376c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_cmp_long.S
@@ -0,0 +1,13 @@
+ /* cmp-long vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ slt a2, a0, a1
+ slt a0, a1, a0
+ subu a0, a0, a2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- result
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_cmpg_double.S b/runtime/interpreter/mterp/mips64/op_cmpg_double.S
new file mode 100644
index 0000000..a8e2ef9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_cmpg_double.S
@@ -0,0 +1 @@
+%include "mips64/fcmpWide.S" {"gt_bias":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_cmpg_float.S b/runtime/interpreter/mterp/mips64/op_cmpg_float.S
new file mode 100644
index 0000000..0c93eac
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_cmpg_float.S
@@ -0,0 +1 @@
+%include "mips64/fcmp.S" {"gt_bias":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_cmpl_double.S b/runtime/interpreter/mterp/mips64/op_cmpl_double.S
new file mode 100644
index 0000000..9111b06
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_cmpl_double.S
@@ -0,0 +1 @@
+%include "mips64/fcmpWide.S" {"gt_bias":"0"}
diff --git a/runtime/interpreter/mterp/mips64/op_cmpl_float.S b/runtime/interpreter/mterp/mips64/op_cmpl_float.S
new file mode 100644
index 0000000..b047451
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_cmpl_float.S
@@ -0,0 +1 @@
+%include "mips64/fcmp.S" {"gt_bias":"0"}
diff --git a/runtime/interpreter/mterp/mips64/op_const.S b/runtime/interpreter/mterp/mips64/op_const.S
new file mode 100644
index 0000000..4b0d69b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const.S
@@ -0,0 +1,9 @@
+ /* const vAA, #+BBBBbbbb */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- bbbb (low)
+ lh a1, 4(rPC) # a1 <- BBBB (high)
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ ins a0, a1, 16, 16 # a0 = BBBBbbbb
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- +BBBBbbbb
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_16.S b/runtime/interpreter/mterp/mips64/op_const_16.S
new file mode 100644
index 0000000..51e68a7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_16.S
@@ -0,0 +1,7 @@
+ /* const/16 vAA, #+BBBB */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- sign-extended BBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- +BBBB
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_4.S b/runtime/interpreter/mterp/mips64/op_const_4.S
new file mode 100644
index 0000000..0a58bff
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_4.S
@@ -0,0 +1,8 @@
+ /* const/4 vA, #+B */
+ ext a2, rINST, 8, 4 # a2 <- A
+ seh a0, rINST # sign extend B in rINST
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ sra a0, a0, 12 # shift B into its final position
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- +B
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_class.S b/runtime/interpreter/mterp/mips64/op_const_class.S
new file mode 100644
index 0000000..adf79df3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_class.S
@@ -0,0 +1,13 @@
+ /* const/class vAA, Class//BBBB */
+ .extern MterpConstClass
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- BBBB
+ srl a1, rINST, 8 # a1 <- AA
+ daddu a2, rFP, OFF_FP_SHADOWFRAME
+ move a3, rSELF
+ jal MterpConstClass # (index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST 2 # load rINST
+ bnez v0, MterpPossibleException # let reference interpreter deal with it.
+ ADVANCE 2 # advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_high16.S b/runtime/interpreter/mterp/mips64/op_const_high16.S
new file mode 100644
index 0000000..43effb6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_high16.S
@@ -0,0 +1,8 @@
+ /* const/high16 vAA, #+BBBB0000 */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- BBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ sll a0, a0, 16 # a0 <- BBBB0000
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- +BBBB0000
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_string.S b/runtime/interpreter/mterp/mips64/op_const_string.S
new file mode 100644
index 0000000..4684c11
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_string.S
@@ -0,0 +1,13 @@
+ /* const/string vAA, String//BBBB */
+ .extern MterpConstString
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- BBBB
+ srl a1, rINST, 8 # a1 <- AA
+ daddu a2, rFP, OFF_FP_SHADOWFRAME
+ move a3, rSELF
+ jal MterpConstString # (index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST 2 # load rINST
+ bnez v0, MterpPossibleException # let reference interpreter deal with it.
+ ADVANCE 2 # advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_string_jumbo.S b/runtime/interpreter/mterp/mips64/op_const_string_jumbo.S
new file mode 100644
index 0000000..47f2101
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_string_jumbo.S
@@ -0,0 +1,15 @@
+ /* const/string vAA, String//BBBBBBBB */
+ .extern MterpConstString
+ EXPORT_PC
+ lh a0, 2(rPC) # a0 <- bbbb (low)
+ lh a4, 4(rPC) # a4 <- BBBB (high)
+ srl a1, rINST, 8 # a1 <- AA
+ ins a0, a4, 16, 16 # a0 <- BBBBbbbb
+ daddu a2, rFP, OFF_FP_SHADOWFRAME
+ move a3, rSELF
+ jal MterpConstString # (index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST 3 # load rINST
+ bnez v0, MterpPossibleException # let reference interpreter deal with it.
+ ADVANCE 3 # advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_wide.S b/runtime/interpreter/mterp/mips64/op_const_wide.S
new file mode 100644
index 0000000..f7eaf7c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_wide.S
@@ -0,0 +1,13 @@
+ /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
+ srl a4, rINST, 8 # a4 <- AA
+ lh a0, 2(rPC) # a0 <- bbbb (low)
+ lh a1, 4(rPC) # a1 <- BBBB (low middle)
+ lh a2, 6(rPC) # a2 <- hhhh (high middle)
+ lh a3, 8(rPC) # a3 <- HHHH (high)
+ FETCH_ADVANCE_INST 5 # advance rPC, load rINST
+ ins a0, a1, 16, 16 # a0 = BBBBbbbb
+ ins a2, a3, 16, 16 # a2 = HHHHhhhh
+ dinsu a0, a2, 32, 32 # a0 = HHHHhhhhBBBBbbbb
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- +HHHHhhhhBBBBbbbb
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_wide_16.S b/runtime/interpreter/mterp/mips64/op_const_wide_16.S
new file mode 100644
index 0000000..3a70937
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_wide_16.S
@@ -0,0 +1,7 @@
+ /* const-wide/16 vAA, #+BBBB */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- sign-extended BBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- +BBBB
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_wide_32.S b/runtime/interpreter/mterp/mips64/op_const_wide_32.S
new file mode 100644
index 0000000..867197c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_wide_32.S
@@ -0,0 +1,9 @@
+ /* const-wide/32 vAA, #+BBBBbbbb */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- bbbb (low)
+ lh a1, 4(rPC) # a1 <- BBBB (high)
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ ins a0, a1, 16, 16 # a0 = BBBBbbbb
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- +BBBBbbbb
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_const_wide_high16.S b/runtime/interpreter/mterp/mips64/op_const_wide_high16.S
new file mode 100644
index 0000000..d741631
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_const_wide_high16.S
@@ -0,0 +1,8 @@
+ /* const-wide/high16 vAA, #+BBBB000000000000 */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- BBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ dsll32 a0, a0, 16 # a0 <- BBBB000000000000
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- +BBBB000000000000
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_div_double.S b/runtime/interpreter/mterp/mips64/op_div_double.S
new file mode 100644
index 0000000..44998f0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_double.S
@@ -0,0 +1 @@
+%include "mips64/fbinopWide.S" {"instr":"div.d f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_div_double_2addr.S b/runtime/interpreter/mterp/mips64/op_div_double_2addr.S
new file mode 100644
index 0000000..396af79
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_double_2addr.S
@@ -0,0 +1 @@
+%include "mips64/fbinopWide2addr.S" {"instr":"div.d f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_div_float.S b/runtime/interpreter/mterp/mips64/op_div_float.S
new file mode 100644
index 0000000..7b09d52
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_float.S
@@ -0,0 +1 @@
+%include "mips64/fbinop.S" {"instr":"div.s f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_div_float_2addr.S b/runtime/interpreter/mterp/mips64/op_div_float_2addr.S
new file mode 100644
index 0000000..e74fdda
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_float_2addr.S
@@ -0,0 +1 @@
+%include "mips64/fbinop2addr.S" {"instr":"div.s f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_div_int.S b/runtime/interpreter/mterp/mips64/op_div_int.S
new file mode 100644
index 0000000..fb04acb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"div a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_div_int_2addr.S b/runtime/interpreter/mterp/mips64/op_div_int_2addr.S
new file mode 100644
index 0000000..db29b84
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"div a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_div_int_lit16.S b/runtime/interpreter/mterp/mips64/op_div_int_lit16.S
new file mode 100644
index 0000000..e903dde
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_int_lit16.S
@@ -0,0 +1 @@
+%include "mips64/binopLit16.S" {"instr":"div a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_div_int_lit8.S b/runtime/interpreter/mterp/mips64/op_div_int_lit8.S
new file mode 100644
index 0000000..0559605
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"div a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_div_long.S b/runtime/interpreter/mterp/mips64/op_div_long.S
new file mode 100644
index 0000000..01fc2b2
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"ddiv a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_div_long_2addr.S b/runtime/interpreter/mterp/mips64/op_div_long_2addr.S
new file mode 100644
index 0000000..9627ab8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_div_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"ddiv a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_double_to_float.S b/runtime/interpreter/mterp/mips64/op_double_to_float.S
new file mode 100644
index 0000000..2b2acee
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_double_to_float.S
@@ -0,0 +1,8 @@
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+%include "mips64/fcvtHeader.S" { "suffix":"_DOUBLE", "valreg":"f0" }
+ cvt.s.d f0, f0
+%include "mips64/fcvtFooter.S" { "suffix":"_FLOAT", "valreg":"f0" }
diff --git a/runtime/interpreter/mterp/mips64/op_double_to_int.S b/runtime/interpreter/mterp/mips64/op_double_to_int.S
new file mode 100644
index 0000000..aa2cbca
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_double_to_int.S
@@ -0,0 +1,23 @@
+%include "mips64/fcvtHeader.S" { "suffix":"_DOUBLE", "valreg":"f0" }
+ /*
+ * TODO: simplify this when the MIPS64R6 emulator
+ * supports NAN2008=1.
+ */
+ dli t0, INT_MIN_AS_DOUBLE
+ dmtc1 t0, f1
+ cmp.le.d f1, f1, f0
+ bc1nez f1, .L${opcode}_trunc
+ cmp.eq.d f1, f0, f0
+ li t0, INT_MIN
+ mfc1 t1, f1
+ and t0, t0, t1
+ b .L${opcode}_done
+%break
+.L${opcode}_trunc:
+ trunc.w.d f0, f0
+ mfc1 t0, f0
+.L${opcode}_done:
+ /* Can't include fcvtFooter.S after break */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG t0, a1
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_double_to_long.S b/runtime/interpreter/mterp/mips64/op_double_to_long.S
new file mode 100644
index 0000000..777cfeb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_double_to_long.S
@@ -0,0 +1,23 @@
+%include "mips64/fcvtHeader.S" { "suffix":"_DOUBLE", "valreg":"f0" }
+ /*
+ * TODO: simplify this when the MIPS64R6 emulator
+ * supports NAN2008=1.
+ */
+ dli t0, LONG_MIN_AS_DOUBLE
+ dmtc1 t0, f1
+ cmp.le.d f1, f1, f0
+ bc1nez f1, .L${opcode}_trunc
+ cmp.eq.d f1, f0, f0
+ dli t0, LONG_MIN
+ mfc1 t1, f1
+ and t0, t0, t1
+ b .L${opcode}_done
+%break
+.L${opcode}_trunc:
+ trunc.l.d f0, f0
+ dmfc1 t0, f0
+.L${opcode}_done:
+ /* Can't include fcvtFooter.S after break */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE t0, a1
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_fill_array_data.S b/runtime/interpreter/mterp/mips64/op_fill_array_data.S
new file mode 100644
index 0000000..c90f0b9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_fill_array_data.S
@@ -0,0 +1,14 @@
+ /* fill-array-data vAA, +BBBBBBBB */
+ .extern MterpFillArrayData
+ EXPORT_PC
+ lh a1, 2(rPC) # a1 <- bbbb (lo)
+ lh a0, 4(rPC) # a0 <- BBBB (hi)
+ srl a3, rINST, 8 # a3 <- AA
+ ins a1, a0, 16, 16 # a1 <- BBBBbbbb
+ GET_VREG_U a0, a3 # a0 <- vAA (array object)
+ dlsa a1, a1, rPC, 1 # a1 <- PC + BBBBbbbb*2 (array data off.)
+ jal MterpFillArrayData # (obj, payload)
+ beqzc v0, MterpPossibleException # exception?
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_filled_new_array.S b/runtime/interpreter/mterp/mips64/op_filled_new_array.S
new file mode 100644
index 0000000..35f55c2
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_filled_new_array.S
@@ -0,0 +1,18 @@
+%default { "helper":"MterpFilledNewArray" }
+ /*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class//CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, type//BBBB */
+ .extern $helper
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rSELF
+ jal $helper
+ beqzc v0, MterpPossibleException
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_filled_new_array_range.S b/runtime/interpreter/mterp/mips64/op_filled_new_array_range.S
new file mode 100644
index 0000000..a4e18f6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_filled_new_array_range.S
@@ -0,0 +1 @@
+%include "mips64/op_filled_new_array.S" { "helper":"MterpFilledNewArrayRange" }
diff --git a/runtime/interpreter/mterp/mips64/op_float_to_double.S b/runtime/interpreter/mterp/mips64/op_float_to_double.S
new file mode 100644
index 0000000..6accfee
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_float_to_double.S
@@ -0,0 +1,8 @@
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+%include "mips64/fcvtHeader.S" { "suffix":"_FLOAT", "valreg":"f0" }
+ cvt.d.s f0, f0
+%include "mips64/fcvtFooter.S" { "suffix":"_DOUBLE", "valreg":"f0" }
diff --git a/runtime/interpreter/mterp/mips64/op_float_to_int.S b/runtime/interpreter/mterp/mips64/op_float_to_int.S
new file mode 100644
index 0000000..d957540
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_float_to_int.S
@@ -0,0 +1,23 @@
+%include "mips64/fcvtHeader.S" { "suffix":"_FLOAT", "valreg":"f0" }
+ /*
+ * TODO: simplify this when the MIPS64R6 emulator
+ * supports NAN2008=1.
+ */
+ li t0, INT_MIN_AS_FLOAT
+ mtc1 t0, f1
+ cmp.le.s f1, f1, f0
+ bc1nez f1, .L${opcode}_trunc
+ cmp.eq.s f1, f0, f0
+ li t0, INT_MIN
+ mfc1 t1, f1
+ and t0, t0, t1
+ b .L${opcode}_done
+%break
+.L${opcode}_trunc:
+ trunc.w.s f0, f0
+ mfc1 t0, f0
+.L${opcode}_done:
+ /* Can't include fcvtFooter.S after break */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG t0, a1
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_float_to_long.S b/runtime/interpreter/mterp/mips64/op_float_to_long.S
new file mode 100644
index 0000000..5d036c8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_float_to_long.S
@@ -0,0 +1,23 @@
+%include "mips64/fcvtHeader.S" { "suffix":"_FLOAT", "valreg":"f0" }
+ /*
+ * TODO: simplify this when the MIPS64R6 emulator
+ * supports NAN2008=1.
+ */
+ li t0, LONG_MIN_AS_FLOAT
+ mtc1 t0, f1
+ cmp.le.s f1, f1, f0
+ bc1nez f1, .L${opcode}_trunc
+ cmp.eq.s f1, f0, f0
+ dli t0, LONG_MIN
+ mfc1 t1, f1
+ and t0, t0, t1
+ b .L${opcode}_done
+%break
+.L${opcode}_trunc:
+ trunc.l.s f0, f0
+ dmfc1 t0, f0
+.L${opcode}_done:
+ /* Can't include fcvtFooter.S after break */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE t0, a1
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_goto.S b/runtime/interpreter/mterp/mips64/op_goto.S
new file mode 100644
index 0000000..f2df3e4
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_goto.S
@@ -0,0 +1,23 @@
+ /*
+ * Unconditional branch, 8-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto +AA */
+ srl a0, rINST, 8
+ seb a0, a0 # a0 <- sign-extended AA
+ dlsa rPC, a0, rPC, 1 # rPC <- rPC + AA * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a0, 1f # AA * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+1:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a0, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_goto_16.S b/runtime/interpreter/mterp/mips64/op_goto_16.S
new file mode 100644
index 0000000..cbf8cf2
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_goto_16.S
@@ -0,0 +1,22 @@
+ /*
+ * Unconditional branch, 16-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto/16 +AAAA */
+ lh a0, 2(rPC) # a0 <- sign-extended AAAA
+ dlsa rPC, a0, rPC, 1 # rPC <- rPC + AAAA * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a0, 1f # AA * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+1:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a0, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_goto_32.S b/runtime/interpreter/mterp/mips64/op_goto_32.S
new file mode 100644
index 0000000..4a1feac
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_goto_32.S
@@ -0,0 +1,27 @@
+ /*
+ * Unconditional branch, 32-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ *
+ * Unlike most opcodes, this one is allowed to branch to itself, so
+ * our "backward branch" test must be "<=0" instead of "<0".
+ */
+ /* goto/32 +AAAAAAAA */
+ lh a0, 2(rPC) # a0 <- aaaa (low)
+ lh a1, 4(rPC) # a1 <- AAAA (high)
+ ins a0, a1, 16, 16 # a0 = sign-extended AAAAaaaa
+ dlsa rPC, a0, rPC, 1 # rPC <- rPC + AAAAAAAA * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgtz a0, 1f # AA * 2 > 0 => no suspend check
+ REFRESH_IBASE
+1:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ blez a0, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_if_eq.S b/runtime/interpreter/mterp/mips64/op_if_eq.S
new file mode 100644
index 0000000..aa35cad
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_eq.S
@@ -0,0 +1 @@
+%include "mips64/bincmp.S" { "condition":"eq" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_eqz.S b/runtime/interpreter/mterp/mips64/op_if_eqz.S
new file mode 100644
index 0000000..0fe3418
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_eqz.S
@@ -0,0 +1 @@
+%include "mips64/zcmp.S" { "condition":"eq" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_ge.S b/runtime/interpreter/mterp/mips64/op_if_ge.S
new file mode 100644
index 0000000..59fdcc5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_ge.S
@@ -0,0 +1 @@
+%include "mips64/bincmp.S" { "condition":"ge" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_gez.S b/runtime/interpreter/mterp/mips64/op_if_gez.S
new file mode 100644
index 0000000..57f1f66
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_gez.S
@@ -0,0 +1 @@
+%include "mips64/zcmp.S" { "condition":"ge" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_gt.S b/runtime/interpreter/mterp/mips64/op_if_gt.S
new file mode 100644
index 0000000..26cc119
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_gt.S
@@ -0,0 +1 @@
+%include "mips64/bincmp.S" { "condition":"gt" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_gtz.S b/runtime/interpreter/mterp/mips64/op_if_gtz.S
new file mode 100644
index 0000000..69fcacb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_gtz.S
@@ -0,0 +1 @@
+%include "mips64/zcmp.S" { "condition":"gt" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_le.S b/runtime/interpreter/mterp/mips64/op_if_le.S
new file mode 100644
index 0000000..a7fce17
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_le.S
@@ -0,0 +1 @@
+%include "mips64/bincmp.S" { "condition":"le" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_lez.S b/runtime/interpreter/mterp/mips64/op_if_lez.S
new file mode 100644
index 0000000..f3edcc6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_lez.S
@@ -0,0 +1 @@
+%include "mips64/zcmp.S" { "condition":"le" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_lt.S b/runtime/interpreter/mterp/mips64/op_if_lt.S
new file mode 100644
index 0000000..a975a31
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_lt.S
@@ -0,0 +1 @@
+%include "mips64/bincmp.S" { "condition":"lt" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_ltz.S b/runtime/interpreter/mterp/mips64/op_if_ltz.S
new file mode 100644
index 0000000..c1d730d
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_ltz.S
@@ -0,0 +1 @@
+%include "mips64/zcmp.S" { "condition":"lt" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_ne.S b/runtime/interpreter/mterp/mips64/op_if_ne.S
new file mode 100644
index 0000000..f143ee9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_ne.S
@@ -0,0 +1 @@
+%include "mips64/bincmp.S" { "condition":"ne" }
diff --git a/runtime/interpreter/mterp/mips64/op_if_nez.S b/runtime/interpreter/mterp/mips64/op_if_nez.S
new file mode 100644
index 0000000..1856b96
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_if_nez.S
@@ -0,0 +1 @@
+%include "mips64/zcmp.S" { "condition":"ne" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget.S b/runtime/interpreter/mterp/mips64/op_iget.S
new file mode 100644
index 0000000..ade4b31
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget.S
@@ -0,0 +1,26 @@
+%default { "is_object":"0", "helper":"artGet32InstanceFromCode"}
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ .extern $helper
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ jal $helper
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ .if $is_object
+ SET_VREG_OBJECT v0, a2 # fp[A] <- v0
+ .else
+ SET_VREG v0, a2 # fp[A] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_iget_boolean.S b/runtime/interpreter/mterp/mips64/op_iget_boolean.S
new file mode 100644
index 0000000..cb2c8be
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_boolean.S
@@ -0,0 +1 @@
+%include "mips64/op_iget.S" { "helper":"artGetBooleanInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget_boolean_quick.S b/runtime/interpreter/mterp/mips64/op_iget_boolean_quick.S
new file mode 100644
index 0000000..979dc70
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_boolean_quick.S
@@ -0,0 +1 @@
+%include "mips64/op_iget_quick.S" { "load":"lbu" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget_byte.S b/runtime/interpreter/mterp/mips64/op_iget_byte.S
new file mode 100644
index 0000000..099d8d0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_byte.S
@@ -0,0 +1 @@
+%include "mips64/op_iget.S" { "helper":"artGetByteInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget_byte_quick.S b/runtime/interpreter/mterp/mips64/op_iget_byte_quick.S
new file mode 100644
index 0000000..cb35556
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_byte_quick.S
@@ -0,0 +1 @@
+%include "mips64/op_iget_quick.S" { "load":"lb" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget_char.S b/runtime/interpreter/mterp/mips64/op_iget_char.S
new file mode 100644
index 0000000..927b7af
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_char.S
@@ -0,0 +1 @@
+%include "mips64/op_iget.S" { "helper":"artGetCharInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget_char_quick.S b/runtime/interpreter/mterp/mips64/op_iget_char_quick.S
new file mode 100644
index 0000000..6034567
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_char_quick.S
@@ -0,0 +1 @@
+%include "mips64/op_iget_quick.S" { "load":"lhu" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget_object.S b/runtime/interpreter/mterp/mips64/op_iget_object.S
new file mode 100644
index 0000000..c658556
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_object.S
@@ -0,0 +1 @@
+%include "mips64/op_iget.S" { "is_object":"1", "helper":"artGetObjInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget_object_quick.S b/runtime/interpreter/mterp/mips64/op_iget_object_quick.S
new file mode 100644
index 0000000..171d543
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_object_quick.S
@@ -0,0 +1,16 @@
+ /* For: iget-object-quick */
+ /* op vA, vB, offset//CCCC */
+ .extern artIGetObjectFromMterp
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ EXPORT_PC
+ GET_VREG_U a0, a2 # a0 <- object we're operating on
+ jal artIGetObjectFromMterp # (obj, offset)
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ SET_VREG_OBJECT v0, a2 # fp[A] <- v0
+ ADVANCE 2 # advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_iget_quick.S b/runtime/interpreter/mterp/mips64/op_iget_quick.S
new file mode 100644
index 0000000..fee6ab7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_quick.S
@@ -0,0 +1,14 @@
+%default { "load":"lw" }
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- object we're operating on
+ ext a4, rINST, 8, 4 # a4 <- A
+ daddu a1, a1, a3
+ beqz a3, common_errNullObject # object was null
+ $load a0, 0(a1) # a0 <- obj.field
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG a0, a4 # fp[A] <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_iget_short.S b/runtime/interpreter/mterp/mips64/op_iget_short.S
new file mode 100644
index 0000000..28b5093
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_short.S
@@ -0,0 +1 @@
+%include "mips64/op_iget.S" { "helper":"artGetShortInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget_short_quick.S b/runtime/interpreter/mterp/mips64/op_iget_short_quick.S
new file mode 100644
index 0000000..6e152db
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_short_quick.S
@@ -0,0 +1 @@
+%include "mips64/op_iget_quick.S" { "load":"lh" }
diff --git a/runtime/interpreter/mterp/mips64/op_iget_wide.S b/runtime/interpreter/mterp/mips64/op_iget_wide.S
new file mode 100644
index 0000000..85cf670
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_wide.S
@@ -0,0 +1,21 @@
+ /*
+ * 64-bit instance field get.
+ *
+ * for: iget-wide
+ */
+ .extern artGet64InstanceFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ jal artGet64InstanceFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ SET_VREG_WIDE v0, a2 # fp[A] <- v0
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_iget_wide_quick.S b/runtime/interpreter/mterp/mips64/op_iget_wide_quick.S
new file mode 100644
index 0000000..2adc6ad
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iget_wide_quick.S
@@ -0,0 +1,14 @@
+ /* iget-wide-quick vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a4, 2(rPC) # a4 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- object we're operating on
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a3, common_errNullObject # object was null
+ daddu a4, a3, a4 # create direct pointer
+ lw a0, 0(a4)
+ lw a1, 4(a4)
+ dinsu a0, a1, 32, 32
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG_WIDE a0, a2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_instance_of.S b/runtime/interpreter/mterp/mips64/op_instance_of.S
new file mode 100644
index 0000000..39a5dc7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_instance_of.S
@@ -0,0 +1,23 @@
+ /*
+ * Check to see if an object reference is an instance of a class.
+ *
+ * Most common situation is a non-null object, being compared against
+ * an already-resolved class.
+ */
+ /* instance-of vA, vB, class//CCCC */
+ .extern MterpInstanceOf
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- CCCC
+ srl a1, rINST, 12 # a1 <- B
+ dlsa a1, a1, rFP, 2 # a1 <- &object
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ jal MterpInstanceOf # (index, &obj, method, self)
+ ld a1, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a1, MterpException
+ ADVANCE 2 # advance rPC
+ SET_VREG v0, a2 # vA <- v0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_int_to_byte.S b/runtime/interpreter/mterp/mips64/op_int_to_byte.S
new file mode 100644
index 0000000..1993e07
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_int_to_byte.S
@@ -0,0 +1 @@
+%include "mips64/unop.S" {"instr":"seb a0, a0"}
diff --git a/runtime/interpreter/mterp/mips64/op_int_to_char.S b/runtime/interpreter/mterp/mips64/op_int_to_char.S
new file mode 100644
index 0000000..8f03acd
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_int_to_char.S
@@ -0,0 +1 @@
+%include "mips64/unop.S" {"instr":"and a0, a0, 0xffff"}
diff --git a/runtime/interpreter/mterp/mips64/op_int_to_double.S b/runtime/interpreter/mterp/mips64/op_int_to_double.S
new file mode 100644
index 0000000..6df71be
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_int_to_double.S
@@ -0,0 +1,8 @@
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+%include "mips64/fcvtHeader.S" { "suffix":"_FLOAT", "valreg":"f0" }
+ cvt.d.w f0, f0
+%include "mips64/fcvtFooter.S" { "suffix":"_DOUBLE", "valreg":"f0" }
diff --git a/runtime/interpreter/mterp/mips64/op_int_to_float.S b/runtime/interpreter/mterp/mips64/op_int_to_float.S
new file mode 100644
index 0000000..77e9eba
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_int_to_float.S
@@ -0,0 +1,8 @@
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+%include "mips64/fcvtHeader.S" { "suffix":"_FLOAT", "valreg":"f0" }
+ cvt.s.w f0, f0
+%include "mips64/fcvtFooter.S" { "suffix":"_FLOAT", "valreg":"f0" }
diff --git a/runtime/interpreter/mterp/mips64/op_int_to_long.S b/runtime/interpreter/mterp/mips64/op_int_to_long.S
new file mode 100644
index 0000000..7b9ad86
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_int_to_long.S
@@ -0,0 +1,8 @@
+ /* int-to-long vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB (sign-extended to 64 bits)
+ ext a2, rINST, 8, 4 # a2 <- A
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- vB
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_int_to_short.S b/runtime/interpreter/mterp/mips64/op_int_to_short.S
new file mode 100644
index 0000000..4a3f234
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_int_to_short.S
@@ -0,0 +1 @@
+%include "mips64/unop.S" {"instr":"seh a0, a0"}
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_direct.S b/runtime/interpreter/mterp/mips64/op_invoke_direct.S
new file mode 100644
index 0000000..5047118
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_direct.S
@@ -0,0 +1 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeDirect" }
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_direct_range.S b/runtime/interpreter/mterp/mips64/op_invoke_direct_range.S
new file mode 100644
index 0000000..5c9b95f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_direct_range.S
@@ -0,0 +1 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeDirectRange" }
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_interface.S b/runtime/interpreter/mterp/mips64/op_invoke_interface.S
new file mode 100644
index 0000000..ed148ad
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_interface.S
@@ -0,0 +1,8 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeInterface" }
+ /*
+ * Handle an interface method call.
+ *
+ * for: invoke-interface, invoke-interface/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_interface_range.S b/runtime/interpreter/mterp/mips64/op_invoke_interface_range.S
new file mode 100644
index 0000000..91c231e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_interface_range.S
@@ -0,0 +1 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeInterfaceRange" }
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_static.S b/runtime/interpreter/mterp/mips64/op_invoke_static.S
new file mode 100644
index 0000000..44f5cb7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_static.S
@@ -0,0 +1 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeStatic" }
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_static_range.S b/runtime/interpreter/mterp/mips64/op_invoke_static_range.S
new file mode 100644
index 0000000..289e5aa
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_static_range.S
@@ -0,0 +1 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeStaticRange" }
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_super.S b/runtime/interpreter/mterp/mips64/op_invoke_super.S
new file mode 100644
index 0000000..b13fffe
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_super.S
@@ -0,0 +1,8 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeSuper" }
+ /*
+ * Handle a "super" method call.
+ *
+ * for: invoke-super, invoke-super/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_super_range.S b/runtime/interpreter/mterp/mips64/op_invoke_super_range.S
new file mode 100644
index 0000000..350b975
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_super_range.S
@@ -0,0 +1 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeSuperRange" }
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_virtual.S b/runtime/interpreter/mterp/mips64/op_invoke_virtual.S
new file mode 100644
index 0000000..0d26cda
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_virtual.S
@@ -0,0 +1,8 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeVirtual" }
+ /*
+ * Handle a virtual method call.
+ *
+ * for: invoke-virtual, invoke-virtual/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_virtual_quick.S b/runtime/interpreter/mterp/mips64/op_invoke_virtual_quick.S
new file mode 100644
index 0000000..f39562c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_virtual_quick.S
@@ -0,0 +1 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeVirtualQuick" }
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_virtual_range.S b/runtime/interpreter/mterp/mips64/op_invoke_virtual_range.S
new file mode 100644
index 0000000..0bb43f8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_virtual_range.S
@@ -0,0 +1 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeVirtualRange" }
diff --git a/runtime/interpreter/mterp/mips64/op_invoke_virtual_range_quick.S b/runtime/interpreter/mterp/mips64/op_invoke_virtual_range_quick.S
new file mode 100644
index 0000000..c448851
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_invoke_virtual_range_quick.S
@@ -0,0 +1 @@
+%include "mips64/invoke.S" { "helper":"MterpInvokeVirtualQuickRange" }
diff --git a/runtime/interpreter/mterp/mips64/op_iput.S b/runtime/interpreter/mterp/mips64/op_iput.S
new file mode 100644
index 0000000..a906a0f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput.S
@@ -0,0 +1,21 @@
+%default { "helper":"artSet32InstanceFromMterp" }
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field//CCCC */
+ .extern $helper
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ GET_VREG a2, a2 # a2 <- fp[A]
+ ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST 2
+ jal $helper
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_iput_boolean.S b/runtime/interpreter/mterp/mips64/op_iput_boolean.S
new file mode 100644
index 0000000..3034fa5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_boolean.S
@@ -0,0 +1 @@
+%include "mips64/op_iput.S" { "helper":"artSet8InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/mips64/op_iput_boolean_quick.S b/runtime/interpreter/mterp/mips64/op_iput_boolean_quick.S
new file mode 100644
index 0000000..df99948
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_boolean_quick.S
@@ -0,0 +1 @@
+%include "mips64/op_iput_quick.S" { "store":"sb" }
diff --git a/runtime/interpreter/mterp/mips64/op_iput_byte.S b/runtime/interpreter/mterp/mips64/op_iput_byte.S
new file mode 100644
index 0000000..3034fa5
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_byte.S
@@ -0,0 +1 @@
+%include "mips64/op_iput.S" { "helper":"artSet8InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/mips64/op_iput_byte_quick.S b/runtime/interpreter/mterp/mips64/op_iput_byte_quick.S
new file mode 100644
index 0000000..df99948
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_byte_quick.S
@@ -0,0 +1 @@
+%include "mips64/op_iput_quick.S" { "store":"sb" }
diff --git a/runtime/interpreter/mterp/mips64/op_iput_char.S b/runtime/interpreter/mterp/mips64/op_iput_char.S
new file mode 100644
index 0000000..4c2fa28
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_char.S
@@ -0,0 +1 @@
+%include "mips64/op_iput.S" { "helper":"artSet16InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/mips64/op_iput_char_quick.S b/runtime/interpreter/mterp/mips64/op_iput_char_quick.S
new file mode 100644
index 0000000..a6286b7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_char_quick.S
@@ -0,0 +1 @@
+%include "mips64/op_iput_quick.S" { "store":"sh" }
diff --git a/runtime/interpreter/mterp/mips64/op_iput_object.S b/runtime/interpreter/mterp/mips64/op_iput_object.S
new file mode 100644
index 0000000..9a42f54
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_object.S
@@ -0,0 +1,11 @@
+ .extern MterpIputObject
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ jal MterpIputObject
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_iput_object_quick.S b/runtime/interpreter/mterp/mips64/op_iput_object_quick.S
new file mode 100644
index 0000000..658ef42
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_object_quick.S
@@ -0,0 +1,10 @@
+ .extern MterpIputObjectQuick
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ jal MterpIputObjectQuick
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_iput_quick.S b/runtime/interpreter/mterp/mips64/op_iput_quick.S
new file mode 100644
index 0000000..b95adfc
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_quick.S
@@ -0,0 +1,14 @@
+%default { "store":"sw" }
+ /* For: iput-quick, iput-boolean-quick, iput-byte-quick, iput-char-quick, iput-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a3, common_errNullObject # object was null
+ GET_VREG a0, a2 # a0 <- fp[A]
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ daddu a1, a1, a3
+ $store a0, 0(a1) # obj.field <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_iput_short.S b/runtime/interpreter/mterp/mips64/op_iput_short.S
new file mode 100644
index 0000000..4c2fa28
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_short.S
@@ -0,0 +1 @@
+%include "mips64/op_iput.S" { "helper":"artSet16InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/mips64/op_iput_short_quick.S b/runtime/interpreter/mterp/mips64/op_iput_short_quick.S
new file mode 100644
index 0000000..a6286b7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_short_quick.S
@@ -0,0 +1 @@
+%include "mips64/op_iput_quick.S" { "store":"sh" }
diff --git a/runtime/interpreter/mterp/mips64/op_iput_wide.S b/runtime/interpreter/mterp/mips64/op_iput_wide.S
new file mode 100644
index 0000000..9b790f8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_wide.S
@@ -0,0 +1,15 @@
+ /* iput-wide vA, vB, field//CCCC */
+ .extern artSet64InstanceFromMterp
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ dlsa a2, a2, rFP, 2 # a2 <- &fp[A]
+ ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST 2
+ jal artSet64InstanceFromMterp
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_iput_wide_quick.S b/runtime/interpreter/mterp/mips64/op_iput_wide_quick.S
new file mode 100644
index 0000000..95a8ad8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_iput_wide_quick.S
@@ -0,0 +1,14 @@
+ /* iput-wide-quick vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a3, 2(rPC) # a3 <- field byte offset
+ GET_VREG_U a2, a2 # a2 <- fp[B], the object pointer
+ ext a0, rINST, 8, 4 # a0 <- A
+ beqz a2, common_errNullObject # object was null
+ GET_VREG_WIDE a0, a0 # a0 <- fp[A]
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ daddu a1, a2, a3 # create a direct pointer
+ sw a0, 0(a1)
+ dsrl32 a0, a0, 0
+ sw a0, 4(a1)
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_long_to_double.S b/runtime/interpreter/mterp/mips64/op_long_to_double.S
new file mode 100644
index 0000000..8503e76
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_long_to_double.S
@@ -0,0 +1,8 @@
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+%include "mips64/fcvtHeader.S" { "suffix":"_DOUBLE", "valreg":"f0" }
+ cvt.d.l f0, f0
+%include "mips64/fcvtFooter.S" { "suffix":"_DOUBLE", "valreg":"f0" }
diff --git a/runtime/interpreter/mterp/mips64/op_long_to_float.S b/runtime/interpreter/mterp/mips64/op_long_to_float.S
new file mode 100644
index 0000000..31f5c0e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_long_to_float.S
@@ -0,0 +1,8 @@
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+%include "mips64/fcvtHeader.S" { "suffix":"_DOUBLE", "valreg":"f0" }
+ cvt.s.l f0, f0
+%include "mips64/fcvtFooter.S" { "suffix":"_FLOAT", "valreg":"f0" }
diff --git a/runtime/interpreter/mterp/mips64/op_long_to_int.S b/runtime/interpreter/mterp/mips64/op_long_to_int.S
new file mode 100644
index 0000000..4ef4b51
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_long_to_int.S
@@ -0,0 +1,2 @@
+/* we ignore the high word, making this equivalent to a 32-bit reg move */
+%include "mips64/op_move.S"
diff --git a/runtime/interpreter/mterp/mips64/op_monitor_enter.S b/runtime/interpreter/mterp/mips64/op_monitor_enter.S
new file mode 100644
index 0000000..36ae503
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_monitor_enter.S
@@ -0,0 +1,14 @@
+ /*
+ * Synchronize on an object.
+ */
+ /* monitor-enter vAA */
+ .extern artLockObjectFromCode
+ EXPORT_PC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_U a0, a2 # a0 <- vAA (object)
+ move a1, rSELF # a1 <- self
+ jal artLockObjectFromCode
+ bnezc v0, MterpException
+ FETCH_ADVANCE_INST 1
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_monitor_exit.S b/runtime/interpreter/mterp/mips64/op_monitor_exit.S
new file mode 100644
index 0000000..9945952
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_monitor_exit.S
@@ -0,0 +1,18 @@
+ /*
+ * Unlock an object.
+ *
+ * Exceptions that occur when unlocking a monitor need to appear as
+ * if they happened at the following instruction. See the Dalvik
+ * instruction spec.
+ */
+ /* monitor-exit vAA */
+ .extern artUnlockObjectFromCode
+ EXPORT_PC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_U a0, a2 # a0 <- vAA (object)
+ move a1, rSELF # a1 <- self
+ jal artUnlockObjectFromCode # v0 <- success for unlock(self, obj)
+ bnezc v0, MterpException
+ FETCH_ADVANCE_INST 1 # before throw: advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_move.S b/runtime/interpreter/mterp/mips64/op_move.S
new file mode 100644
index 0000000..c79f6cd
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move.S
@@ -0,0 +1,14 @@
+%default { "is_object":"0" }
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if $is_object
+ SET_VREG_OBJECT a0, a2 # vA <- vB
+ .else
+ SET_VREG a0, a2 # vA <- vB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_move_16.S b/runtime/interpreter/mterp/mips64/op_move_16.S
new file mode 100644
index 0000000..9d5c4dc
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_16.S
@@ -0,0 +1,14 @@
+%default { "is_object":"0" }
+ /* for: move/16, move-object/16 */
+ /* op vAAAA, vBBBB */
+ lhu a3, 4(rPC) # a3 <- BBBB
+ lhu a2, 2(rPC) # a2 <- AAAA
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vBBBB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if $is_object
+ SET_VREG_OBJECT a0, a2 # vAAAA <- vBBBB
+ .else
+ SET_VREG a0, a2 # vAAAA <- vBBBB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_move_exception.S b/runtime/interpreter/mterp/mips64/op_move_exception.S
new file mode 100644
index 0000000..d226718
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_exception.S
@@ -0,0 +1,8 @@
+ /* move-exception vAA */
+ srl a2, rINST, 8 # a2 <- AA
+ ld a0, THREAD_EXCEPTION_OFFSET(rSELF) # load exception obj
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ SET_VREG_OBJECT a0, a2 # vAA <- exception obj
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ sd zero, THREAD_EXCEPTION_OFFSET(rSELF) # clear exception
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_move_from16.S b/runtime/interpreter/mterp/mips64/op_move_from16.S
new file mode 100644
index 0000000..6d6bde0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_from16.S
@@ -0,0 +1,14 @@
+%default { "is_object":"0" }
+ /* for: move/from16, move-object/from16 */
+ /* op vAA, vBBBB */
+ lhu a3, 2(rPC) # a3 <- BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vBBBB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if $is_object
+ SET_VREG_OBJECT a0, a2 # vAA <- vBBBB
+ .else
+ SET_VREG a0, a2 # vAA <- vBBBB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_move_object.S b/runtime/interpreter/mterp/mips64/op_move_object.S
new file mode 100644
index 0000000..47e0272
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_object.S
@@ -0,0 +1 @@
+%include "mips64/op_move.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_move_object_16.S b/runtime/interpreter/mterp/mips64/op_move_object_16.S
new file mode 100644
index 0000000..a777dcd
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_object_16.S
@@ -0,0 +1 @@
+%include "mips64/op_move_16.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_move_object_from16.S b/runtime/interpreter/mterp/mips64/op_move_object_from16.S
new file mode 100644
index 0000000..ab55ebd
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_object_from16.S
@@ -0,0 +1 @@
+%include "mips64/op_move_from16.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_move_result.S b/runtime/interpreter/mterp/mips64/op_move_result.S
new file mode 100644
index 0000000..1ec28cb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_result.S
@@ -0,0 +1,14 @@
+%default { "is_object":"0" }
+ /* for: move-result, move-result-object */
+ /* op vAA */
+ srl a2, rINST, 8 # a2 <- AA
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ ld a0, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ lw a0, 0(a0) # a0 <- result.i
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if $is_object
+ SET_VREG_OBJECT a0, a2 # vAA <- result
+ .else
+ SET_VREG a0, a2 # vAA <- result
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_move_result_object.S b/runtime/interpreter/mterp/mips64/op_move_result_object.S
new file mode 100644
index 0000000..e76bc22
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_result_object.S
@@ -0,0 +1 @@
+%include "mips64/op_move_result.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_move_result_wide.S b/runtime/interpreter/mterp/mips64/op_move_result_wide.S
new file mode 100644
index 0000000..3ba0d72
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_result_wide.S
@@ -0,0 +1,9 @@
+ /* for: move-result-wide */
+ /* op vAA */
+ srl a2, rINST, 8 # a2 <- AA
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ ld a0, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ ld a0, 0(a0) # a0 <- result.j
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- result
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_move_wide.S b/runtime/interpreter/mterp/mips64/op_move_wide.S
new file mode 100644
index 0000000..ea23f87
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_wide.S
@@ -0,0 +1,9 @@
+ /* move-wide vA, vB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ ext a3, rINST, 12, 4 # a3 <- B
+ ext a2, rINST, 8, 4 # a2 <- A
+ GET_VREG_WIDE a0, a3 # a0 <- vB
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- vB
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_move_wide_16.S b/runtime/interpreter/mterp/mips64/op_move_wide_16.S
new file mode 100644
index 0000000..8ec6068
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_wide_16.S
@@ -0,0 +1,9 @@
+ /* move-wide/16 vAAAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ lhu a3, 4(rPC) # a3 <- BBBB
+ lhu a2, 2(rPC) # a2 <- AAAA
+ GET_VREG_WIDE a0, a3 # a0 <- vBBBB
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAAAA <- vBBBB
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_move_wide_from16.S b/runtime/interpreter/mterp/mips64/op_move_wide_from16.S
new file mode 100644
index 0000000..11d5603
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_move_wide_from16.S
@@ -0,0 +1,9 @@
+ /* move-wide/from16 vAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ lhu a3, 2(rPC) # a3 <- BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_WIDE a0, a3 # a0 <- vBBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- vBBBB
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_mul_double.S b/runtime/interpreter/mterp/mips64/op_mul_double.S
new file mode 100644
index 0000000..e7e17f7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_double.S
@@ -0,0 +1 @@
+%include "mips64/fbinopWide.S" {"instr":"mul.d f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_mul_double_2addr.S b/runtime/interpreter/mterp/mips64/op_mul_double_2addr.S
new file mode 100644
index 0000000..f404d46
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_double_2addr.S
@@ -0,0 +1 @@
+%include "mips64/fbinopWide2addr.S" {"instr":"mul.d f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_mul_float.S b/runtime/interpreter/mterp/mips64/op_mul_float.S
new file mode 100644
index 0000000..9a695fc
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_float.S
@@ -0,0 +1 @@
+%include "mips64/fbinop.S" {"instr":"mul.s f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_mul_float_2addr.S b/runtime/interpreter/mterp/mips64/op_mul_float_2addr.S
new file mode 100644
index 0000000..a134a34
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_float_2addr.S
@@ -0,0 +1 @@
+%include "mips64/fbinop2addr.S" {"instr":"mul.s f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_mul_int.S b/runtime/interpreter/mterp/mips64/op_mul_int.S
new file mode 100644
index 0000000..e1b90ff
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"mul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_mul_int_2addr.S b/runtime/interpreter/mterp/mips64/op_mul_int_2addr.S
new file mode 100644
index 0000000..c0c4063
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"mul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_mul_int_lit16.S b/runtime/interpreter/mterp/mips64/op_mul_int_lit16.S
new file mode 100644
index 0000000..bb4fff8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_int_lit16.S
@@ -0,0 +1 @@
+%include "mips64/binopLit16.S" {"instr":"mul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_mul_int_lit8.S b/runtime/interpreter/mterp/mips64/op_mul_int_lit8.S
new file mode 100644
index 0000000..da11ea9
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"mul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_mul_long.S b/runtime/interpreter/mterp/mips64/op_mul_long.S
new file mode 100644
index 0000000..ec32850
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"dmul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_mul_long_2addr.S b/runtime/interpreter/mterp/mips64/op_mul_long_2addr.S
new file mode 100644
index 0000000..eb50cda
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_mul_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"dmul a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_neg_double.S b/runtime/interpreter/mterp/mips64/op_neg_double.S
new file mode 100644
index 0000000..a135d61
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_neg_double.S
@@ -0,0 +1,3 @@
+%include "mips64/fcvtHeader.S" { "suffix":"_DOUBLE", "valreg":"f0" }
+ neg.d f0, f0
+%include "mips64/fcvtFooter.S" { "suffix":"_DOUBLE", "valreg":"f0" }
diff --git a/runtime/interpreter/mterp/mips64/op_neg_float.S b/runtime/interpreter/mterp/mips64/op_neg_float.S
new file mode 100644
index 0000000..78019f0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_neg_float.S
@@ -0,0 +1,3 @@
+%include "mips64/fcvtHeader.S" { "suffix":"_FLOAT", "valreg":"f0" }
+ neg.s f0, f0
+%include "mips64/fcvtFooter.S" { "suffix":"_FLOAT", "valreg":"f0" }
diff --git a/runtime/interpreter/mterp/mips64/op_neg_int.S b/runtime/interpreter/mterp/mips64/op_neg_int.S
new file mode 100644
index 0000000..31538c0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_neg_int.S
@@ -0,0 +1 @@
+%include "mips64/unop.S" {"instr":"subu a0, zero, a0"}
diff --git a/runtime/interpreter/mterp/mips64/op_neg_long.S b/runtime/interpreter/mterp/mips64/op_neg_long.S
new file mode 100644
index 0000000..bc80d06
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_neg_long.S
@@ -0,0 +1 @@
+%include "mips64/unopWide.S" {"instr":"dsubu a0, zero, a0"}
diff --git a/runtime/interpreter/mterp/mips64/op_new_array.S b/runtime/interpreter/mterp/mips64/op_new_array.S
new file mode 100644
index 0000000..d78b4ac
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_new_array.S
@@ -0,0 +1,19 @@
+ /*
+ * Allocate an array of objects, specified with the array class
+ * and a count.
+ *
+ * The verifier guarantees that this is an array class, so we don't
+ * check for it here.
+ */
+ /* new-array vA, vB, class//CCCC */
+ .extern MterpNewArray
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ jal MterpNewArray
+ beqzc v0, MterpPossibleException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_new_instance.S b/runtime/interpreter/mterp/mips64/op_new_instance.S
new file mode 100644
index 0000000..cc5e13e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_new_instance.S
@@ -0,0 +1,14 @@
+ /*
+ * Create a new instance of a class.
+ */
+ /* new-instance vAA, class//BBBB */
+ .extern MterpNewInstance
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rSELF
+ move a2, rINST
+ jal MterpNewInstance # (shadow_frame, self, inst_data)
+ beqzc v0, MterpPossibleException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_nop.S b/runtime/interpreter/mterp/mips64/op_nop.S
new file mode 100644
index 0000000..cc803a7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_nop.S
@@ -0,0 +1,3 @@
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_not_int.S b/runtime/interpreter/mterp/mips64/op_not_int.S
new file mode 100644
index 0000000..5954095
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_not_int.S
@@ -0,0 +1 @@
+%include "mips64/unop.S" {"instr":"nor a0, zero, a0"}
diff --git a/runtime/interpreter/mterp/mips64/op_not_long.S b/runtime/interpreter/mterp/mips64/op_not_long.S
new file mode 100644
index 0000000..c8f5da7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_not_long.S
@@ -0,0 +1 @@
+%include "mips64/unopWide.S" {"instr":"nor a0, zero, a0"}
diff --git a/runtime/interpreter/mterp/mips64/op_or_int.S b/runtime/interpreter/mterp/mips64/op_or_int.S
new file mode 100644
index 0000000..0102355
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_or_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_or_int_2addr.S b/runtime/interpreter/mterp/mips64/op_or_int_2addr.S
new file mode 100644
index 0000000..eed8900
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_or_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_or_int_lit16.S b/runtime/interpreter/mterp/mips64/op_or_int_lit16.S
new file mode 100644
index 0000000..16a0f3e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_or_int_lit16.S
@@ -0,0 +1 @@
+%include "mips64/binopLit16.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_or_int_lit8.S b/runtime/interpreter/mterp/mips64/op_or_int_lit8.S
new file mode 100644
index 0000000..dbbf790
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_or_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_or_long.S b/runtime/interpreter/mterp/mips64/op_or_long.S
new file mode 100644
index 0000000..e6f8639
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_or_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_or_long_2addr.S b/runtime/interpreter/mterp/mips64/op_or_long_2addr.S
new file mode 100644
index 0000000..ad5e6c8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_or_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"or a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_packed_switch.S b/runtime/interpreter/mterp/mips64/op_packed_switch.S
new file mode 100644
index 0000000..cdbdf75
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_packed_switch.S
@@ -0,0 +1,31 @@
+%default { "func":"MterpDoPackedSwitch" }
+ /*
+ * Handle a packed-switch or sparse-switch instruction. In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+ /* op vAA, +BBBBBBBB */
+ .extern $func
+ lh a0, 2(rPC) # a0 <- bbbb (lo)
+ lh a1, 4(rPC) # a1 <- BBBB (hi)
+ srl a3, rINST, 8 # a3 <- AA
+ ins a0, a1, 16, 16 # a0 <- BBBBbbbb
+ GET_VREG a1, a3 # a1 <- vAA
+ dlsa a0, a0, rPC, 1 # a0 <- PC + BBBBbbbb*2
+ jal $func # v0 <- code-unit branch offset
+ dlsa rPC, v0, rPC, 1 # rPC <- rPC + offset * 2
+ FETCH_INST # load rINST
+#if MTERP_SUSPEND
+ bgtz v0, 1f # offset * 2 > 0 => no suspend check
+ REFRESH_IBASE
+1:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ blez v0, MterpCheckSuspendAndContinue
+#endif
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_rem_double.S b/runtime/interpreter/mterp/mips64/op_rem_double.S
new file mode 100644
index 0000000..ba61cfd
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_double.S
@@ -0,0 +1,12 @@
+ /* rem-double vAA, vBB, vCC */
+ .extern fmod
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f12, a2 # f12 <- vBB
+ GET_VREG_DOUBLE f13, a3 # f13 <- vCC
+ jal fmod # f0 <- f12 op f13
+ srl a4, rINST, 8 # a4 <- AA
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_rem_double_2addr.S b/runtime/interpreter/mterp/mips64/op_rem_double_2addr.S
new file mode 100644
index 0000000..c649f0d
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_double_2addr.S
@@ -0,0 +1,12 @@
+ /* rem-double/2addr vA, vB */
+ .extern fmod
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_DOUBLE f12, a2 # f12 <- vA
+ GET_VREG_DOUBLE f13, a3 # f13 <- vB
+ jal fmod # f0 <- f12 op f13
+ ext a2, rINST, 8, 4 # a2 <- A
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_rem_float.S b/runtime/interpreter/mterp/mips64/op_rem_float.S
new file mode 100644
index 0000000..3967b0b
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_float.S
@@ -0,0 +1,12 @@
+ /* rem-float vAA, vBB, vCC */
+ .extern fmodf
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f12, a2 # f12 <- vBB
+ GET_VREG_FLOAT f13, a3 # f13 <- vCC
+ jal fmodf # f0 <- f12 op f13
+ srl a4, rINST, 8 # a4 <- AA
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_rem_float_2addr.S b/runtime/interpreter/mterp/mips64/op_rem_float_2addr.S
new file mode 100644
index 0000000..3fed41e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_float_2addr.S
@@ -0,0 +1,12 @@
+ /* rem-float/2addr vA, vB */
+ .extern fmodf
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_FLOAT f12, a2 # f12 <- vA
+ GET_VREG_FLOAT f13, a3 # f13 <- vB
+ jal fmodf # f0 <- f12 op f13
+ ext a2, rINST, 8, 4 # a2 <- A
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_rem_int.S b/runtime/interpreter/mterp/mips64/op_rem_int.S
new file mode 100644
index 0000000..c05e9c4
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"mod a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_rem_int_2addr.S b/runtime/interpreter/mterp/mips64/op_rem_int_2addr.S
new file mode 100644
index 0000000..a4e162d
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"mod a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_rem_int_lit16.S b/runtime/interpreter/mterp/mips64/op_rem_int_lit16.S
new file mode 100644
index 0000000..3284f14
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_int_lit16.S
@@ -0,0 +1 @@
+%include "mips64/binopLit16.S" {"instr":"mod a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_rem_int_lit8.S b/runtime/interpreter/mterp/mips64/op_rem_int_lit8.S
new file mode 100644
index 0000000..1e6a584
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"mod a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_rem_long.S b/runtime/interpreter/mterp/mips64/op_rem_long.S
new file mode 100644
index 0000000..32b2d19
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"dmod a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_rem_long_2addr.S b/runtime/interpreter/mterp/mips64/op_rem_long_2addr.S
new file mode 100644
index 0000000..ad658e1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rem_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"dmod a0, a0, a1", "chkzero":"1"}
diff --git a/runtime/interpreter/mterp/mips64/op_return.S b/runtime/interpreter/mterp/mips64/op_return.S
new file mode 100644
index 0000000..ec986b8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_return.S
@@ -0,0 +1,18 @@
+ /*
+ * Return a 32-bit value.
+ *
+ * for: return, return-object
+ */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ .extern MterpSuspendCheck
+ jal MterpThreadFenceForConstructor
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, 1f
+ jal MterpSuspendCheck # (self)
+1:
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_U a0, a2 # a0 <- vAA
+ b MterpReturn
diff --git a/runtime/interpreter/mterp/mips64/op_return_object.S b/runtime/interpreter/mterp/mips64/op_return_object.S
new file mode 100644
index 0000000..67f1871
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_return_object.S
@@ -0,0 +1 @@
+%include "mips64/op_return.S"
diff --git a/runtime/interpreter/mterp/mips64/op_return_void.S b/runtime/interpreter/mterp/mips64/op_return_void.S
new file mode 100644
index 0000000..05253ae
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_return_void.S
@@ -0,0 +1,11 @@
+ .extern MterpThreadFenceForConstructor
+ .extern MterpSuspendCheck
+ jal MterpThreadFenceForConstructor
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, 1f
+ jal MterpSuspendCheck # (self)
+1:
+ li a0, 0
+ b MterpReturn
diff --git a/runtime/interpreter/mterp/mips64/op_return_void_no_barrier.S b/runtime/interpreter/mterp/mips64/op_return_void_no_barrier.S
new file mode 100644
index 0000000..f67e811
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_return_void_no_barrier.S
@@ -0,0 +1,9 @@
+ .extern MterpSuspendCheck
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, 1f
+ jal MterpSuspendCheck # (self)
+1:
+ li a0, 0
+ b MterpReturn
diff --git a/runtime/interpreter/mterp/mips64/op_return_wide.S b/runtime/interpreter/mterp/mips64/op_return_wide.S
new file mode 100644
index 0000000..544e027
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_return_wide.S
@@ -0,0 +1,17 @@
+ /*
+ * Return a 64-bit value.
+ */
+ /* return-wide vAA */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ .extern MterpSuspendCheck
+ jal MterpThreadFenceForConstructor
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, 1f
+ jal MterpSuspendCheck # (self)
+1:
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_WIDE a0, a2 # a0 <- vAA
+ b MterpReturn
diff --git a/runtime/interpreter/mterp/mips64/op_rsub_int.S b/runtime/interpreter/mterp/mips64/op_rsub_int.S
new file mode 100644
index 0000000..fa31a0a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rsub_int.S
@@ -0,0 +1 @@
+%include "mips64/binopLit16.S" {"instr":"subu a0, a1, a0"}
diff --git a/runtime/interpreter/mterp/mips64/op_rsub_int_lit8.S b/runtime/interpreter/mterp/mips64/op_rsub_int_lit8.S
new file mode 100644
index 0000000..c31ff32
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_rsub_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"subu a0, a1, a0"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget.S b/runtime/interpreter/mterp/mips64/op_sget.S
new file mode 100644
index 0000000..bd2cfe3
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sget.S
@@ -0,0 +1,26 @@
+%default { "is_object":"0", "helper":"artGet32StaticFromCode", "extend":"" }
+ /*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ /* op vAA, field//BBBB */
+ .extern $helper
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ move a2, rSELF
+ jal $helper
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a2, rINST, 8 # a2 <- AA
+ $extend
+ PREFETCH_INST 2
+ bnez a3, MterpException # bail out
+ .if $is_object
+ SET_VREG_OBJECT v0, a2 # fp[AA] <- v0
+ .else
+ SET_VREG v0, a2 # fp[AA] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0
diff --git a/runtime/interpreter/mterp/mips64/op_sget_boolean.S b/runtime/interpreter/mterp/mips64/op_sget_boolean.S
new file mode 100644
index 0000000..e7b1844
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sget_boolean.S
@@ -0,0 +1 @@
+%include "mips64/op_sget.S" {"helper":"artGetBooleanStaticFromCode", "extend":"and v0, v0, 0xff"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_byte.S b/runtime/interpreter/mterp/mips64/op_sget_byte.S
new file mode 100644
index 0000000..52a2e4a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sget_byte.S
@@ -0,0 +1 @@
+%include "mips64/op_sget.S" {"helper":"artGetByteStaticFromCode", "extend":"seb v0, v0"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_char.S b/runtime/interpreter/mterp/mips64/op_sget_char.S
new file mode 100644
index 0000000..873d82a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sget_char.S
@@ -0,0 +1 @@
+%include "mips64/op_sget.S" {"helper":"artGetCharStaticFromCode", "extend":"and v0, v0, 0xffff"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_object.S b/runtime/interpreter/mterp/mips64/op_sget_object.S
new file mode 100644
index 0000000..3108417
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sget_object.S
@@ -0,0 +1 @@
+%include "mips64/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_short.S b/runtime/interpreter/mterp/mips64/op_sget_short.S
new file mode 100644
index 0000000..fed4e76
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sget_short.S
@@ -0,0 +1 @@
+%include "mips64/op_sget.S" {"helper":"artGetShortStaticFromCode", "extend":"seh v0, v0"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_wide.S b/runtime/interpreter/mterp/mips64/op_sget_wide.S
new file mode 100644
index 0000000..77124d1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sget_wide.S
@@ -0,0 +1,18 @@
+ /*
+ * SGET_WIDE handler wrapper.
+ *
+ */
+ /* sget-wide vAA, field//BBBB */
+ .extern artGet64StaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ move a2, rSELF
+ jal artGet64StaticFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a4, rINST, 8 # a4 <- AA
+ bnez a3, MterpException # bail out
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG_WIDE v0, a4
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_shl_int.S b/runtime/interpreter/mterp/mips64/op_shl_int.S
new file mode 100644
index 0000000..784481f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shl_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"sll a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_shl_int_2addr.S b/runtime/interpreter/mterp/mips64/op_shl_int_2addr.S
new file mode 100644
index 0000000..a6c8a78
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shl_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"sll a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_shl_int_lit8.S b/runtime/interpreter/mterp/mips64/op_shl_int_lit8.S
new file mode 100644
index 0000000..36ef207
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shl_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"sll a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_shl_long.S b/runtime/interpreter/mterp/mips64/op_shl_long.S
new file mode 100644
index 0000000..225a2cb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shl_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"dsll a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_shl_long_2addr.S b/runtime/interpreter/mterp/mips64/op_shl_long_2addr.S
new file mode 100644
index 0000000..c04d882
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shl_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"dsll a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_shr_int.S b/runtime/interpreter/mterp/mips64/op_shr_int.S
new file mode 100644
index 0000000..eded037
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shr_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"sra a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_shr_int_2addr.S b/runtime/interpreter/mterp/mips64/op_shr_int_2addr.S
new file mode 100644
index 0000000..5b4d96f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shr_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"sra a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_shr_int_lit8.S b/runtime/interpreter/mterp/mips64/op_shr_int_lit8.S
new file mode 100644
index 0000000..175eb86
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shr_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"sra a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_shr_long.S b/runtime/interpreter/mterp/mips64/op_shr_long.S
new file mode 100644
index 0000000..0db38c8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shr_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"dsra a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_shr_long_2addr.S b/runtime/interpreter/mterp/mips64/op_shr_long_2addr.S
new file mode 100644
index 0000000..48131ad
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_shr_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"dsra a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_sparse_switch.S b/runtime/interpreter/mterp/mips64/op_sparse_switch.S
new file mode 100644
index 0000000..b065aaa
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sparse_switch.S
@@ -0,0 +1 @@
+%include "mips64/op_packed_switch.S" { "func":"MterpDoSparseSwitch" }
diff --git a/runtime/interpreter/mterp/mips64/op_sput.S b/runtime/interpreter/mterp/mips64/op_sput.S
new file mode 100644
index 0000000..142f18f
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sput.S
@@ -0,0 +1,20 @@
+%default { "helper":"artSet32StaticFromCode" }
+ /*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field//BBBB */
+ .extern $helper
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ srl a3, rINST, 8 # a3 <- AA
+ GET_VREG a1, a3 # a1 <- fp[AA]
+ ld a2, OFF_FP_METHOD(rFP)
+ move a3, rSELF
+ PREFETCH_INST 2 # Get next inst, but don't advance rPC
+ jal $helper
+ bnezc v0, MterpException # 0 on success
+ ADVANCE 2 # Past exception point - now advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_sput_boolean.S b/runtime/interpreter/mterp/mips64/op_sput_boolean.S
new file mode 100644
index 0000000..f5b8dbf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sput_boolean.S
@@ -0,0 +1 @@
+%include "mips64/op_sput.S" {"helper":"artSet8StaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips64/op_sput_byte.S b/runtime/interpreter/mterp/mips64/op_sput_byte.S
new file mode 100644
index 0000000..f5b8dbf
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sput_byte.S
@@ -0,0 +1 @@
+%include "mips64/op_sput.S" {"helper":"artSet8StaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips64/op_sput_char.S b/runtime/interpreter/mterp/mips64/op_sput_char.S
new file mode 100644
index 0000000..c4d195c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sput_char.S
@@ -0,0 +1 @@
+%include "mips64/op_sput.S" {"helper":"artSet16StaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips64/op_sput_object.S b/runtime/interpreter/mterp/mips64/op_sput_object.S
new file mode 100644
index 0000000..ef4c685
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sput_object.S
@@ -0,0 +1,11 @@
+ .extern MterpSputObject
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ jal MterpSputObject
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_sput_short.S b/runtime/interpreter/mterp/mips64/op_sput_short.S
new file mode 100644
index 0000000..c4d195c
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sput_short.S
@@ -0,0 +1 @@
+%include "mips64/op_sput.S" {"helper":"artSet16StaticFromCode"}
diff --git a/runtime/interpreter/mterp/mips64/op_sput_wide.S b/runtime/interpreter/mterp/mips64/op_sput_wide.S
new file mode 100644
index 0000000..828ddc1
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sput_wide.S
@@ -0,0 +1,18 @@
+ /*
+ * SPUT_WIDE handler wrapper.
+ *
+ */
+ /* sput-wide vAA, field//BBBB */
+ .extern artSet64IndirectStaticFromMterp
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ srl a2, rINST, 8 # a2 <- AA
+ dlsa a2, a2, rFP, 2
+ move a3, rSELF
+ PREFETCH_INST 2 # Get next inst, but don't advance rPC
+ jal artSet64IndirectStaticFromMterp
+ bnezc v0, MterpException # 0 on success, -1 on failure
+ ADVANCE 2 # Past exception point - now advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/op_sub_double.S b/runtime/interpreter/mterp/mips64/op_sub_double.S
new file mode 100644
index 0000000..40a6c89
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sub_double.S
@@ -0,0 +1 @@
+%include "mips64/fbinopWide.S" {"instr":"sub.d f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_sub_double_2addr.S b/runtime/interpreter/mterp/mips64/op_sub_double_2addr.S
new file mode 100644
index 0000000..984737e
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sub_double_2addr.S
@@ -0,0 +1 @@
+%include "mips64/fbinopWide2addr.S" {"instr":"sub.d f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_sub_float.S b/runtime/interpreter/mterp/mips64/op_sub_float.S
new file mode 100644
index 0000000..9010592
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sub_float.S
@@ -0,0 +1 @@
+%include "mips64/fbinop.S" {"instr":"sub.s f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_sub_float_2addr.S b/runtime/interpreter/mterp/mips64/op_sub_float_2addr.S
new file mode 100644
index 0000000..e7d4ffe
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sub_float_2addr.S
@@ -0,0 +1 @@
+%include "mips64/fbinop2addr.S" {"instr":"sub.s f0, f0, f1"}
diff --git a/runtime/interpreter/mterp/mips64/op_sub_int.S b/runtime/interpreter/mterp/mips64/op_sub_int.S
new file mode 100644
index 0000000..609ea05
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sub_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"subu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_sub_int_2addr.S b/runtime/interpreter/mterp/mips64/op_sub_int_2addr.S
new file mode 100644
index 0000000..ba2f1e8
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sub_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"subu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_sub_long.S b/runtime/interpreter/mterp/mips64/op_sub_long.S
new file mode 100644
index 0000000..09a6afd
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sub_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"dsubu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_sub_long_2addr.S b/runtime/interpreter/mterp/mips64/op_sub_long_2addr.S
new file mode 100644
index 0000000..b9ec82a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_sub_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"dsubu a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_throw.S b/runtime/interpreter/mterp/mips64/op_throw.S
new file mode 100644
index 0000000..6418d57
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_throw.S
@@ -0,0 +1,10 @@
+ /*
+ * Throw an exception object in the current thread.
+ */
+ /* throw vAA */
+ EXPORT_PC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_U a0, a2 # a0 <- vAA (exception object)
+ beqzc a0, common_errNullObject
+ sd a0, THREAD_EXCEPTION_OFFSET(rSELF) # thread->exception <- obj
+ b MterpException
diff --git a/runtime/interpreter/mterp/mips64/op_unused_3e.S b/runtime/interpreter/mterp/mips64/op_unused_3e.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_3e.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_3f.S b/runtime/interpreter/mterp/mips64/op_unused_3f.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_3f.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_40.S b/runtime/interpreter/mterp/mips64/op_unused_40.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_40.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_41.S b/runtime/interpreter/mterp/mips64/op_unused_41.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_41.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_42.S b/runtime/interpreter/mterp/mips64/op_unused_42.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_42.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_43.S b/runtime/interpreter/mterp/mips64/op_unused_43.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_43.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_79.S b/runtime/interpreter/mterp/mips64/op_unused_79.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_79.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_7a.S b/runtime/interpreter/mterp/mips64/op_unused_7a.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_7a.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_f4.S b/runtime/interpreter/mterp/mips64/op_unused_f4.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_f4.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_fa.S b/runtime/interpreter/mterp/mips64/op_unused_fa.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_fa.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_fb.S b/runtime/interpreter/mterp/mips64/op_unused_fb.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_fb.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_fc.S b/runtime/interpreter/mterp/mips64/op_unused_fc.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_fc.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_fd.S b/runtime/interpreter/mterp/mips64/op_unused_fd.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_fd.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_fe.S b/runtime/interpreter/mterp/mips64/op_unused_fe.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_fe.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_unused_ff.S b/runtime/interpreter/mterp/mips64/op_unused_ff.S
new file mode 100644
index 0000000..29463d7
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_unused_ff.S
@@ -0,0 +1 @@
+%include "mips64/unused.S"
diff --git a/runtime/interpreter/mterp/mips64/op_ushr_int.S b/runtime/interpreter/mterp/mips64/op_ushr_int.S
new file mode 100644
index 0000000..37c90cb
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_ushr_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"srl a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_ushr_int_2addr.S b/runtime/interpreter/mterp/mips64/op_ushr_int_2addr.S
new file mode 100644
index 0000000..d6bf413
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_ushr_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"srl a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_ushr_int_lit8.S b/runtime/interpreter/mterp/mips64/op_ushr_int_lit8.S
new file mode 100644
index 0000000..2a2d843
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_ushr_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"srl a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_ushr_long.S b/runtime/interpreter/mterp/mips64/op_ushr_long.S
new file mode 100644
index 0000000..e724405
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_ushr_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"dsrl a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_ushr_long_2addr.S b/runtime/interpreter/mterp/mips64/op_ushr_long_2addr.S
new file mode 100644
index 0000000..d2cf135
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_ushr_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"dsrl a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_xor_int.S b/runtime/interpreter/mterp/mips64/op_xor_int.S
new file mode 100644
index 0000000..ee25ebc
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_xor_int.S
@@ -0,0 +1 @@
+%include "mips64/binop.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_xor_int_2addr.S b/runtime/interpreter/mterp/mips64/op_xor_int_2addr.S
new file mode 100644
index 0000000..0f04967
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_xor_int_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binop2addr.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_xor_int_lit16.S b/runtime/interpreter/mterp/mips64/op_xor_int_lit16.S
new file mode 100644
index 0000000..ecb21ae
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_xor_int_lit16.S
@@ -0,0 +1 @@
+%include "mips64/binopLit16.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_xor_int_lit8.S b/runtime/interpreter/mterp/mips64/op_xor_int_lit8.S
new file mode 100644
index 0000000..115ae99
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_xor_int_lit8.S
@@ -0,0 +1 @@
+%include "mips64/binopLit8.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_xor_long.S b/runtime/interpreter/mterp/mips64/op_xor_long.S
new file mode 100644
index 0000000..7ebabc2
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_xor_long.S
@@ -0,0 +1 @@
+%include "mips64/binopWide.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/op_xor_long_2addr.S b/runtime/interpreter/mterp/mips64/op_xor_long_2addr.S
new file mode 100644
index 0000000..0f1919a
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/op_xor_long_2addr.S
@@ -0,0 +1 @@
+%include "mips64/binopWide2addr.S" {"instr":"xor a0, a0, a1"}
diff --git a/runtime/interpreter/mterp/mips64/unop.S b/runtime/interpreter/mterp/mips64/unop.S
new file mode 100644
index 0000000..e3f7ea0
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/unop.S
@@ -0,0 +1,18 @@
+%default {"preinstr":""}
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "a0 = op a0".
+ *
+ * for: int-to-byte, int-to-char, int-to-short,
+ * not-int, neg-int
+ */
+ /* unop vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ ext a2, rINST, 8, 4 # a2 <- A
+ $preinstr # optional op
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ $instr # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/unopWide.S b/runtime/interpreter/mterp/mips64/unopWide.S
new file mode 100644
index 0000000..c0dd1aa
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/unopWide.S
@@ -0,0 +1,17 @@
+%default {"preinstr":""}
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "a0 = op a0".
+ *
+ * For: not-long, neg-long
+ */
+ /* unop vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a3 # a0 <- vB
+ ext a2, rINST, 8, 4 # a2 <- A
+ $preinstr # optional op
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ $instr # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mips64/unused.S b/runtime/interpreter/mterp/mips64/unused.S
new file mode 100644
index 0000000..30d38bd6
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/unused.S
@@ -0,0 +1,4 @@
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
diff --git a/runtime/interpreter/mterp/mips64/zcmp.S b/runtime/interpreter/mterp/mips64/zcmp.S
new file mode 100644
index 0000000..d7ad894
--- /dev/null
+++ b/runtime/interpreter/mterp/mips64/zcmp.S
@@ -0,0 +1,30 @@
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-lez" you would use "le".
+ *
+ * For: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ lh a4, 2(rPC) # a4 <- sign-extended BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a2 # a0 <- vAA
+
+ b${condition}zc a0, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + BBBB * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # BBBB * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index b443c69..ca727f4 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -149,7 +149,9 @@
Runtime::Current()->GetInstrumentation();
bool unhandled_instrumentation;
// TODO: enable for other targets after more extensive testing.
- if ((kRuntimeISA == kArm64) || (kRuntimeISA == kArm) || (kRuntimeISA == kX86)) {
+ if ((kRuntimeISA == kArm64) || (kRuntimeISA == kArm) ||
+ (kRuntimeISA == kX86_64) || (kRuntimeISA == kX86) ||
+ (kRuntimeISA == kMips)) {
unhandled_instrumentation = instrumentation->NonJitProfilingActive();
} else {
unhandled_instrumentation = instrumentation->IsActive();
diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S
index 2b74d4c..b26a63a 100644
--- a/runtime/interpreter/mterp/out/mterp_arm.S
+++ b/runtime/interpreter/mterp/out/mterp_arm.S
@@ -1353,7 +1353,7 @@
VREG_INDEX_TO_ADDR r3, r3 @ r3<- &vCC
flds s0, [r2] @ s0<- vBB
flds s1, [r3] @ s1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ vcmpe.f32 s0, s1 @ compare (vBB, vCC)
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
mvn r0, #0 @ r0<- -1 (default)
GET_INST_OPCODE ip @ extract opcode from rINST
@@ -1392,7 +1392,7 @@
VREG_INDEX_TO_ADDR r3, r3 @ r3<- &vCC
flds s0, [r2] @ s0<- vBB
flds s1, [r3] @ s1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ vcmpe.f32 s0, s1 @ compare (vBB, vCC)
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
mov r0, #1 @ r0<- 1 (default)
GET_INST_OPCODE ip @ extract opcode from rINST
@@ -1431,7 +1431,7 @@
VREG_INDEX_TO_ADDR r3, r3 @ r3<- &vCC
fldd d0, [r2] @ d0<- vBB
fldd d1, [r3] @ d1<- vCC
- fcmped d0, d1 @ compare (vBB, vCC)
+ vcmpe.f64 d0, d1 @ compare (vBB, vCC)
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
mvn r0, #0 @ r0<- -1 (default)
GET_INST_OPCODE ip @ extract opcode from rINST
@@ -1470,7 +1470,7 @@
VREG_INDEX_TO_ADDR r3, r3 @ r3<- &vCC
fldd d0, [r2] @ d0<- vBB
fldd d1, [r3] @ d1<- vCC
- fcmped d0, d1 @ compare (vBB, vCC)
+ vcmpe.f64 d0, d1 @ compare (vBB, vCC)
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
mov r0, #1 @ r0<- 1 (default)
GET_INST_OPCODE ip @ extract opcode from rINST
@@ -3994,7 +3994,7 @@
flds s0, [r3] @ s0<- vB
FETCH_ADVANCE_INST 1 @ advance rPC, load rINST
and r9, r9, #15 @ r9<- A
- fcvtds d0, s0 @ d0<- op
+ vcvt.f64.f32 d0, s0 @ d0<- op
CLEAR_SHADOW_PAIR r9, ip, lr @ Zero shadow regs
GET_INST_OPCODE ip @ extract opcode from rINST
VREG_INDEX_TO_ADDR r9, r9 @ r9<- &vA
@@ -4075,7 +4075,7 @@
fldd d0, [r3] @ d0<- vB
FETCH_ADVANCE_INST 1 @ advance rPC, load rINST
and r9, r9, #15 @ r9<- A
- fcvtsd s0, d0 @ s0<- op
+ vcvt.f32.f64 s0, d0 @ s0<- op
GET_INST_OPCODE ip @ extract opcode from rINST
VREG_INDEX_TO_ADDR r9, r9 @ r9<- &vA
fsts s0, [r9] @ vA<- s0
@@ -7673,7 +7673,7 @@
cmp r0, #0 @ nonzero == yes
mvnne r0, #0 @ return maxlong (7fffffff)
mvnne r1, #0x80000000
- ldmnefd sp!, {r4, pc}
+ popne {r4, pc}
mov r0, r4 @ recover arg
mov r1, #0xdf000000 @ (float)minlong
@@ -7681,14 +7681,14 @@
cmp r0, #0 @ nonzero == yes
movne r0, #0 @ return minlong (80000000)
movne r1, #0x80000000
- ldmnefd sp!, {r4, pc}
+ popne {r4, pc}
mov r0, r4 @ recover arg
mov r1, r4
bl __aeabi_fcmpeq @ is arg == self?
cmp r0, #0 @ zero == no
moveq r1, #0 @ return zero for NaN
- ldmeqfd sp!, {r4, pc}
+ popeq {r4, pc}
mov r0, r4 @ recover arg
bl __aeabi_f2lz @ convert float to long
diff --git a/runtime/interpreter/mterp/out/mterp_mips.S b/runtime/interpreter/mterp/out/mterp_mips.S
new file mode 100644
index 0000000..7ae1ab1
--- /dev/null
+++ b/runtime/interpreter/mterp/out/mterp_mips.S
@@ -0,0 +1,13157 @@
+/*
+ * This file was generated automatically by gen-mterp.py for 'mips'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: mips/header.S */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ Art assembly interpreter notes:
+
+ First validate assembly code by implementing ExecuteXXXImpl() style body (doesn't
+ handle invoke, allows higher-level code to create frame & shadow frame.
+
+ Once that's working, support direct entry code & eliminate shadow frame (and
+ excess locals allocation.
+
+ Some (hopefully) temporary ugliness. We'll treat rFP as pointing to the
+ base of the vreg array within the shadow frame. Access the other fields,
+ dex_pc_, method_ and number_of_vregs_ via negative offsets. For now, we'll continue
+ the shadow frame mechanism of double-storing object references - via rFP &
+ number_of_vregs_.
+
+ */
+
+#include "asm_support.h"
+
+#if (__mips==32) && (__mips_isa_rev>=2)
+#define MIPS32REVGE2 /* mips32r2 and greater */
+#if (__mips==32) && (__mips_isa_rev>=5)
+#define FPU64 /* 64 bit FPU */
+#if (__mips==32) && (__mips_isa_rev>=6)
+#define MIPS32REVGE6 /* mips32r6 and greater */
+#endif
+#endif
+#endif
+
+/* MIPS definitions and declarations
+
+ reg nick purpose
+ s0 rPC interpreted program counter, used for fetching instructions
+ s1 rFP interpreted frame pointer, used for accessing locals and args
+ s2 rSELF self (Thread) pointer
+ s3 rIBASE interpreted instruction base pointer, used for computed goto
+ s4 rINST first 16-bit code unit of current instruction
+ s6 rREFS base of object references in shadow frame (ideally, we'll get rid of this later).
+*/
+
+/* single-purpose registers, given names for clarity */
+#define rPC s0
+#define rFP s1
+#define rSELF s2
+#define rIBASE s3
+#define rINST s4
+#define rOBJ s5
+#define rREFS s6
+#define rTEMP s7
+
+#define rARG0 a0
+#define rARG1 a1
+#define rARG2 a2
+#define rARG3 a3
+#define rRESULT0 v0
+#define rRESULT1 v1
+
+/* GP register definitions */
+#define zero $0 /* always zero */
+#define AT $at /* assembler temp */
+#define v0 $2 /* return value */
+#define v1 $3
+#define a0 $4 /* argument registers */
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define t0 $8 /* temp registers (not saved across subroutine calls) */
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+#define ta0 $12 /* alias */
+#define ta1 $13
+#define ta2 $14
+#define ta3 $15
+#define s0 $16 /* saved across subroutine calls (callee saved) */
+#define s1 $17
+#define s2 $18
+#define s3 $19
+#define s4 $20
+#define s5 $21
+#define s6 $22
+#define s7 $23
+#define t8 $24 /* two more temp registers */
+#define t9 $25
+#define k0 $26 /* kernel temporary */
+#define k1 $27
+#define gp $28 /* global pointer */
+#define sp $29 /* stack pointer */
+#define s8 $30 /* one more callee saved */
+#define ra $31 /* return address */
+
+/* FP register definitions */
+#define fv0 $f0
+#define fv0f $f1
+#define fv1 $f2
+#define fv1f $f3
+#define fa0 $f12
+#define fa0f $f13
+#define fa1 $f14
+#define fa1f $f15
+#define ft0 $f4
+#define ft0f $f5
+#define ft1 $f6
+#define ft1f $f7
+#define ft2 $f8
+#define ft2f $f9
+#define ft3 $f10
+#define ft3f $f11
+#define ft4 $f16
+#define ft4f $f17
+#define ft5 $f18
+#define ft5f $f19
+#define fs0 $f20
+#define fs0f $f21
+#define fs1 $f22
+#define fs1f $f23
+#define fs2 $f24
+#define fs2f $f25
+#define fs3 $f26
+#define fs3f $f27
+#define fs4 $f28
+#define fs4f $f29
+#define fs5 $f30
+#define fs5f $f31
+
+#ifndef MIPS32REVGE6
+#define fcc0 $fcc0
+#define fcc1 $fcc1
+#endif
+
+/*
+ * Instead of holding a pointer to the shadow frame, we keep rFP at the base of the vregs. So,
+ * to access other shadow frame fields, we need to use a backwards offset. Define those here.
+ */
+#define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET)
+#define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET)
+#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET)
+#define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET)
+#define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET)
+#define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET)
+#define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET)
+#define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET)
+#define OFF_FP_SHADOWFRAME (-SHADOWFRAME_VREGS_OFFSET)
+
+#define MTERP_PROFILE_BRANCHES 1
+#define MTERP_LOGGING 0
+
+/*
+ * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must
+ * be done *before* something throws.
+ *
+ * It's okay to do this more than once.
+ *
+ * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped
+ * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction
+ * offset into the code_items_[] array. For effiency, we will "export" the
+ * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC
+ * to convert to a dex pc when needed.
+ */
+#define EXPORT_PC() \
+ sw rPC, OFF_FP_DEX_PC_PTR(rFP)
+
+#define EXPORT_DEX_PC(tmp) \
+ lw tmp, OFF_FP_CODE_ITEM(rFP) \
+ sw rPC, OFF_FP_DEX_PC_PTR(rFP) \
+ addu tmp, CODEITEM_INSNS_OFFSET \
+ subu tmp, rPC, tmp \
+ sra tmp, tmp, 1 \
+ sw tmp, OFF_FP_DEX_PC(rFP)
+
+/*
+ * Fetch the next instruction from rPC into rINST. Does not advance rPC.
+ */
+#define FETCH_INST() lhu rINST, (rPC)
+
+/*
+ * Fetch the next instruction from the specified offset. Advances rPC
+ * to point to the next instruction. "_count" is in 16-bit code units.
+ *
+ * This must come AFTER anything that can throw an exception, or the
+ * exception catch may miss. (This also implies that it must come after
+ * EXPORT_PC().)
+ */
+#define FETCH_ADVANCE_INST(_count) lhu rINST, ((_count)*2)(rPC); \
+ addu rPC, rPC, ((_count) * 2)
+
+/*
+ * The operation performed here is similar to FETCH_ADVANCE_INST, except the
+ * src and dest registers are parameterized (not hard-wired to rPC and rINST).
+ */
+#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
+ lhu _dreg, ((_count)*2)(_sreg) ; \
+ addu _sreg, _sreg, (_count)*2
+
+/*
+ * Similar to FETCH_ADVANCE_INST, but does not update rPC. Used to load
+ * rINST ahead of possible exception point. Be sure to manually advance rPC
+ * later.
+ */
+#define PREFETCH_INST(_count) lhu rINST, ((_count)*2)(rPC)
+
+/* Advance rPC by some number of code units. */
+#define ADVANCE(_count) addu rPC, rPC, ((_count) * 2)
+
+/*
+ * Fetch the next instruction from an offset specified by rd. Updates
+ * rPC to point to the next instruction. "rd" must specify the distance
+ * in bytes, *not* 16-bit code units, and may be a signed value.
+ */
+#define FETCH_ADVANCE_INST_RB(rd) addu rPC, rPC, rd; \
+ lhu rINST, (rPC)
+
+/*
+ * Fetch a half-word code unit from an offset past the current PC. The
+ * "_count" value is in 16-bit code units. Does not advance rPC.
+ *
+ * The "_S" variant works the same but treats the value as signed.
+ */
+#define FETCH(rd, _count) lhu rd, ((_count) * 2)(rPC)
+#define FETCH_S(rd, _count) lh rd, ((_count) * 2)(rPC)
+
+/*
+ * Fetch one byte from an offset past the current PC. Pass in the same
+ * "_count" as you would for FETCH, and an additional 0/1 indicating which
+ * byte of the halfword you want (lo/hi).
+ */
+#define FETCH_B(rd, _count, _byte) lbu rd, ((_count) * 2 + _byte)(rPC)
+
+/*
+ * Put the instruction's opcode field into the specified register.
+ */
+#define GET_INST_OPCODE(rd) and rd, rINST, 0xFF
+
+/*
+ * Put the prefetched instruction's opcode field into the specified register.
+ */
+#define GET_PREFETCHED_OPCODE(dreg, sreg) andi dreg, sreg, 255
+
+/*
+ * Begin executing the opcode in rd.
+ */
+#define GOTO_OPCODE(rd) sll rd, rd, 7; \
+ addu rd, rIBASE, rd; \
+ jalr zero, rd
+
+#define GOTO_OPCODE_BASE(_base, rd) sll rd, rd, 7; \
+ addu rd, _base, rd; \
+ jalr zero, rd
+
+/*
+ * Get/set the 32-bit value from a Dalvik register.
+ */
+#define GET_VREG(rd, rix) LOAD_eas2(rd, rFP, rix)
+
+#define GET_VREG_F(rd, rix) EAS2(AT, rFP, rix); \
+ .set noat; l.s rd, (AT); .set at
+
+#define SET_VREG(rd, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rd, 0(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8)
+
+#define SET_VREG64(rlo, rhi, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rlo, 0(t8); \
+ sw rhi, 4(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8); \
+ sw zero, 4(t8)
+
+#ifdef FPU64
+#define SET_VREG64_F(rlo, rhi, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rREFS, AT; \
+ sw zero, 0(t8); \
+ sw zero, 4(t8); \
+ addu t8, rFP, AT; \
+ mfhc1 AT, rlo; \
+ sw AT, 4(t8); \
+ .set at; \
+ s.s rlo, 0(t8)
+#else
+#define SET_VREG64_F(rlo, rhi, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ s.s rlo, 0(t8); \
+ s.s rhi, 4(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8); \
+ sw zero, 4(t8)
+#endif
+
+#define SET_VREG_OBJECT(rd, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rd, 0(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw rd, 0(t8)
+
+/* Combination of the SET_VREG and GOTO_OPCODE functions to save 1 instruction */
+#define SET_VREG_GOTO(rd, rix, dst) .set noreorder; \
+ sll dst, dst, 7; \
+ addu dst, rIBASE, dst; \
+ .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rd, 0(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ jalr zero, dst; \
+ sw zero, 0(t8); \
+ .set reorder
+
+/* Combination of the SET_VREG64 and GOTO_OPCODE functions to save 1 instruction */
+#define SET_VREG64_GOTO(rlo, rhi, rix, dst) .set noreorder; \
+ sll dst, dst, 7; \
+ addu dst, rIBASE, dst; \
+ .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ sw rlo, 0(t8); \
+ sw rhi, 4(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8); \
+ jalr zero, dst; \
+ sw zero, 4(t8); \
+ .set reorder
+
+#define SET_VREG_F(rd, rix) .set noat; \
+ sll AT, rix, 2; \
+ addu t8, rFP, AT; \
+ s.s rd, 0(t8); \
+ addu t8, rREFS, AT; \
+ .set at; \
+ sw zero, 0(t8)
+
+#define GET_OPA(rd) srl rd, rINST, 8
+#ifdef MIPS32REVGE2
+#define GET_OPA4(rd) ext rd, rINST, 8, 4
+#else
+#define GET_OPA4(rd) GET_OPA(rd); and rd, 0xf
+#endif
+#define GET_OPB(rd) srl rd, rINST, 12
+
+/*
+ * Form an Effective Address rd = rbase + roff<<n;
+ * Uses reg AT
+ */
+#define EASN(rd, rbase, roff, rshift) .set noat; \
+ sll AT, roff, rshift; \
+ addu rd, rbase, AT; \
+ .set at
+
+#define EAS1(rd, rbase, roff) EASN(rd, rbase, roff, 1)
+#define EAS2(rd, rbase, roff) EASN(rd, rbase, roff, 2)
+#define EAS3(rd, rbase, roff) EASN(rd, rbase, roff, 3)
+#define EAS4(rd, rbase, roff) EASN(rd, rbase, roff, 4)
+
+/*
+ * Form an Effective Shift Right rd = rbase + roff>>n;
+ * Uses reg AT
+ */
+#define ESRN(rd, rbase, roff, rshift) .set noat; \
+ srl AT, roff, rshift; \
+ addu rd, rbase, AT; \
+ .set at
+
+#define LOAD_eas2(rd, rbase, roff) EAS2(AT, rbase, roff); \
+ .set noat; lw rd, 0(AT); .set at
+
+#define STORE_eas2(rd, rbase, roff) EAS2(AT, rbase, roff); \
+ .set noat; sw rd, 0(AT); .set at
+
+#define LOAD_RB_OFF(rd, rbase, off) lw rd, off(rbase)
+#define STORE_RB_OFF(rd, rbase, off) sw rd, off(rbase)
+
+#define STORE64_off(rlo, rhi, rbase, off) sw rlo, off(rbase); \
+ sw rhi, (off+4)(rbase)
+#define LOAD64_off(rlo, rhi, rbase, off) lw rlo, off(rbase); \
+ lw rhi, (off+4)(rbase)
+
+#define STORE64(rlo, rhi, rbase) STORE64_off(rlo, rhi, rbase, 0)
+#define LOAD64(rlo, rhi, rbase) LOAD64_off(rlo, rhi, rbase, 0)
+
+#ifdef FPU64
+#define STORE64_off_F(rlo, rhi, rbase, off) s.s rlo, off(rbase); \
+ .set noat; \
+ mfhc1 AT, rlo; \
+ sw AT, (off+4)(rbase); \
+ .set at
+#define LOAD64_off_F(rlo, rhi, rbase, off) l.s rlo, off(rbase); \
+ .set noat; \
+ lw AT, (off+4)(rbase); \
+ mthc1 AT, rlo; \
+ .set at
+#else
+#define STORE64_off_F(rlo, rhi, rbase, off) s.s rlo, off(rbase); \
+ s.s rhi, (off+4)(rbase)
+#define LOAD64_off_F(rlo, rhi, rbase, off) l.s rlo, off(rbase); \
+ l.s rhi, (off+4)(rbase)
+#endif
+
+#define STORE64_F(rlo, rhi, rbase) STORE64_off_F(rlo, rhi, rbase, 0)
+#define LOAD64_F(rlo, rhi, rbase) LOAD64_off_F(rlo, rhi, rbase, 0)
+
+
+#define LOAD_base_offMirrorArray_length(rd, rbase) LOAD_RB_OFF(rd, rbase, MIRROR_ARRAY_LENGTH_OFFSET)
+
+#define STACK_STORE(rd, off) sw rd, off(sp)
+#define STACK_LOAD(rd, off) lw rd, off(sp)
+#define CREATE_STACK(n) subu sp, sp, n
+#define DELETE_STACK(n) addu sp, sp, n
+
+#define LOAD_ADDR(dest, addr) la dest, addr
+#define LOAD_IMM(dest, imm) li dest, imm
+#define MOVE_REG(dest, src) move dest, src
+#define STACK_SIZE 128
+
+#define STACK_OFFSET_ARG04 16
+#define STACK_OFFSET_ARG05 20
+#define STACK_OFFSET_ARG06 24
+#define STACK_OFFSET_ARG07 28
+#define STACK_OFFSET_GP 84
+
+#define JAL(n) jal n
+#define BAL(n) bal n
+
+/*
+ * FP register usage restrictions:
+ * 1) We don't use the callee save FP registers so we don't have to save them.
+ * 2) We don't use the odd FP registers so we can share code with mips32r6.
+ */
+#define STACK_STORE_FULL() CREATE_STACK(STACK_SIZE); \
+ STACK_STORE(ra, 124); \
+ STACK_STORE(s8, 120); \
+ STACK_STORE(s0, 116); \
+ STACK_STORE(s1, 112); \
+ STACK_STORE(s2, 108); \
+ STACK_STORE(s3, 104); \
+ STACK_STORE(s4, 100); \
+ STACK_STORE(s5, 96); \
+ STACK_STORE(s6, 92); \
+ STACK_STORE(s7, 88);
+
+#define STACK_LOAD_FULL() STACK_LOAD(gp, STACK_OFFSET_GP); \
+ STACK_LOAD(s7, 88); \
+ STACK_LOAD(s6, 92); \
+ STACK_LOAD(s5, 96); \
+ STACK_LOAD(s4, 100); \
+ STACK_LOAD(s3, 104); \
+ STACK_LOAD(s2, 108); \
+ STACK_LOAD(s1, 112); \
+ STACK_LOAD(s0, 116); \
+ STACK_LOAD(s8, 120); \
+ STACK_LOAD(ra, 124); \
+ DELETE_STACK(STACK_SIZE)
+
+/* File: mips/entry.S */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Interpreter entry point.
+ */
+
+ .text
+ .align 2
+ .global ExecuteMterpImpl
+ .ent ExecuteMterpImpl
+ .frame sp, STACK_SIZE, ra
+/*
+ * On entry:
+ * a0 Thread* self
+ * a1 code_item
+ * a2 ShadowFrame
+ * a3 JValue* result_register
+ *
+ */
+
+ExecuteMterpImpl:
+ .set noreorder
+ .cpload t9
+ .set reorder
+/* Save to the stack. Frame size = STACK_SIZE */
+ STACK_STORE_FULL()
+/* This directive will make sure all subsequent jal restore gp at a known offset */
+ .cprestore STACK_OFFSET_GP
+
+ /* Remember the return register */
+ sw a3, SHADOWFRAME_RESULT_REGISTER_OFFSET(a2)
+
+ /* Remember the code_item */
+ sw a1, SHADOWFRAME_CODE_ITEM_OFFSET(a2)
+
+ /* set up "named" registers */
+ move rSELF, a0
+ lw a0, SHADOWFRAME_NUMBER_OF_VREGS_OFFSET(a2)
+ addu rFP, a2, SHADOWFRAME_VREGS_OFFSET # point to insns[] (i.e. - the dalivk byte code).
+ EAS2(rREFS, rFP, a0) # point to reference array in shadow frame
+ lw a0, SHADOWFRAME_DEX_PC_OFFSET(a2) # Get starting dex_pc
+ addu rPC, a1, CODEITEM_INSNS_OFFSET # Point to base of insns[]
+ EAS1(rPC, rPC, a0) # Create direct pointer to 1st dex opcode
+
+ EXPORT_PC()
+
+ /* Starting ibase */
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
+
+ /* start executing the instruction at rPC */
+ FETCH_INST() # load rINST from rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* NOTE: no fallthrough */
+
+
+ .global artMterpAsmInstructionStart
+ .type artMterpAsmInstructionStart, %function
+artMterpAsmInstructionStart = .L_op_nop
+ .text
+
+/* ------------------------------ */
+ .balign 128
+.L_op_nop: /* 0x00 */
+/* File: mips/op_nop.S */
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move: /* 0x01 */
+/* File: mips/op_move.S */
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ GET_OPB(a1) # a1 <- B from 15:12
+ GET_OPA4(a0) # a0 <- A from 11:8
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[B]
+ GET_INST_OPCODE(t0) # t0 <- opcode from rINST
+ .if 0
+ SET_VREG_OBJECT(a2, a0) # fp[A] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[A] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_from16: /* 0x02 */
+/* File: mips/op_move_from16.S */
+ /* for: move/from16, move-object/from16 */
+ /* op vAA, vBBBB */
+ FETCH(a1, 1) # a1 <- BBBB
+ GET_OPA(a0) # a0 <- AA
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[BBBB]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ .if 0
+ SET_VREG_OBJECT(a2, a0) # fp[AA] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[AA] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_16: /* 0x03 */
+/* File: mips/op_move_16.S */
+ /* for: move/16, move-object/16 */
+ /* op vAAAA, vBBBB */
+ FETCH(a1, 2) # a1 <- BBBB
+ FETCH(a0, 1) # a0 <- AAAA
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[BBBB]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ .if 0
+ SET_VREG_OBJECT(a2, a0) # fp[AAAA] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[AAAA] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_wide: /* 0x04 */
+/* File: mips/op_move_wide.S */
+ /* move-wide vA, vB */
+ /* NOTE: regs can overlap, e.g. "move v6, v7" or "move v7, v6" */
+ GET_OPA4(a2) # a2 <- A(+)
+ GET_OPB(a3) # a3 <- B
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64(a0, a1, a3) # a0/a1 <- fp[B]
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ SET_VREG64(a0, a1, a2) # fp[A] <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_wide_from16: /* 0x05 */
+/* File: mips/op_move_wide_from16.S */
+ /* move-wide/from16 vAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6, v7" or "move v7, v6" */
+ FETCH(a3, 1) # a3 <- BBBB
+ GET_OPA(a2) # a2 <- AA
+ EAS2(a3, rFP, a3) # a3 <- &fp[BBBB]
+ LOAD64(a0, a1, a3) # a0/a1 <- fp[BBBB]
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ SET_VREG64(a0, a1, a2) # fp[AA] <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_wide_16: /* 0x06 */
+/* File: mips/op_move_wide_16.S */
+ /* move-wide/16 vAAAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6, v7" or "move v7, v6" */
+ FETCH(a3, 2) # a3 <- BBBB
+ FETCH(a2, 1) # a2 <- AAAA
+ EAS2(a3, rFP, a3) # a3 <- &fp[BBBB]
+ LOAD64(a0, a1, a3) # a0/a1 <- fp[BBBB]
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ SET_VREG64(a0, a1, a2) # fp[AAAA] <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_object: /* 0x07 */
+/* File: mips/op_move_object.S */
+/* File: mips/op_move.S */
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ GET_OPB(a1) # a1 <- B from 15:12
+ GET_OPA4(a0) # a0 <- A from 11:8
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[B]
+ GET_INST_OPCODE(t0) # t0 <- opcode from rINST
+ .if 1
+ SET_VREG_OBJECT(a2, a0) # fp[A] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[A] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_object_from16: /* 0x08 */
+/* File: mips/op_move_object_from16.S */
+/* File: mips/op_move_from16.S */
+ /* for: move/from16, move-object/from16 */
+ /* op vAA, vBBBB */
+ FETCH(a1, 1) # a1 <- BBBB
+ GET_OPA(a0) # a0 <- AA
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[BBBB]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ .if 1
+ SET_VREG_OBJECT(a2, a0) # fp[AA] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[AA] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_object_16: /* 0x09 */
+/* File: mips/op_move_object_16.S */
+/* File: mips/op_move_16.S */
+ /* for: move/16, move-object/16 */
+ /* op vAAAA, vBBBB */
+ FETCH(a1, 2) # a1 <- BBBB
+ FETCH(a0, 1) # a0 <- AAAA
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[BBBB]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ .if 1
+ SET_VREG_OBJECT(a2, a0) # fp[AAAA] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[AAAA] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_result: /* 0x0a */
+/* File: mips/op_move_result.S */
+ /* for: move-result, move-result-object */
+ /* op vAA */
+ GET_OPA(a2) # a2 <- AA
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ lw a0, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ lw a0, 0(a0) # a0 <- result.i
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ .if 0
+ SET_VREG_OBJECT(a0, a2) # fp[AA] <- a0
+ .else
+ SET_VREG(a0, a2) # fp[AA] <- a0
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_result_wide: /* 0x0b */
+/* File: mips/op_move_result_wide.S */
+ /* move-result-wide vAA */
+ GET_OPA(a2) # a2 <- AA
+ lw a3, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ LOAD64(a0, a1, a3) # a0/a1 <- retval.j
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ SET_VREG64(a0, a1, a2) # fp[AA] <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_result_object: /* 0x0c */
+/* File: mips/op_move_result_object.S */
+/* File: mips/op_move_result.S */
+ /* for: move-result, move-result-object */
+ /* op vAA */
+ GET_OPA(a2) # a2 <- AA
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ lw a0, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ lw a0, 0(a0) # a0 <- result.i
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ .if 1
+ SET_VREG_OBJECT(a0, a2) # fp[AA] <- a0
+ .else
+ SET_VREG(a0, a2) # fp[AA] <- a0
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_exception: /* 0x0d */
+/* File: mips/op_move_exception.S */
+ /* move-exception vAA */
+ GET_OPA(a2) # a2 <- AA
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF) # get exception obj
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ SET_VREG_OBJECT(a3, a2) # fp[AA] <- exception obj
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ sw zero, THREAD_EXCEPTION_OFFSET(rSELF) # clear exception
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_void: /* 0x0e */
+/* File: mips/op_return_void.S */
+ .extern MterpThreadFenceForConstructor
+ JAL(MterpThreadFenceForConstructor)
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqz ra, 1f
+ JAL(MterpSuspendCheck) # (self)
+1:
+ move v0, zero
+ move v1, zero
+ b MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return: /* 0x0f */
+/* File: mips/op_return.S */
+ /*
+ * Return a 32-bit value.
+ *
+ * for: return, return-object
+ */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ JAL(MterpThreadFenceForConstructor)
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqz ra, 1f
+ JAL(MterpSuspendCheck) # (self)
+1:
+ GET_OPA(a2) # a2 <- AA
+ GET_VREG(v0, a2) # v0 <- vAA
+ move v1, zero
+ b MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_wide: /* 0x10 */
+/* File: mips/op_return_wide.S */
+ /*
+ * Return a 64-bit value.
+ */
+ /* return-wide vAA */
+ .extern MterpThreadFenceForConstructor
+ JAL(MterpThreadFenceForConstructor)
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqz ra, 1f
+ JAL(MterpSuspendCheck) # (self)
+1:
+ GET_OPA(a2) # a2 <- AA
+ EAS2(a2, rFP, a2) # a2 <- &fp[AA]
+ LOAD64(v0, v1, a2) # v0/v1 <- vAA/vAA+1
+ b MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_object: /* 0x11 */
+/* File: mips/op_return_object.S */
+/* File: mips/op_return.S */
+ /*
+ * Return a 32-bit value.
+ *
+ * for: return, return-object
+ */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ JAL(MterpThreadFenceForConstructor)
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqz ra, 1f
+ JAL(MterpSuspendCheck) # (self)
+1:
+ GET_OPA(a2) # a2 <- AA
+ GET_VREG(v0, a2) # v0 <- vAA
+ move v1, zero
+ b MterpReturn
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_4: /* 0x12 */
+/* File: mips/op_const_4.S */
+ # const/4 vA, /* +B */
+ sll a1, rINST, 16 # a1 <- Bxxx0000
+ GET_OPA(a0) # a0 <- A+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ sra a1, a1, 28 # a1 <- sssssssB (sign-extended)
+ and a0, a0, 15
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a1, a0, t0) # fp[A] <- a1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_16: /* 0x13 */
+/* File: mips/op_const_16.S */
+ # const/16 vAA, /* +BBBB */
+ FETCH_S(a0, 1) # a0 <- ssssBBBB (sign-extended)
+ GET_OPA(a3) # a3 <- AA
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a3, t0) # vAA <- a0
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const: /* 0x14 */
+/* File: mips/op_const.S */
+ # const vAA, /* +BBBBbbbb */
+ GET_OPA(a3) # a3 <- AA
+ FETCH(a0, 1) # a0 <- bbbb (low)
+ FETCH(a1, 2) # a1 <- BBBB (high)
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ sll a1, a1, 16
+ or a0, a1, a0 # a0 <- BBBBbbbb
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a3, t0) # vAA <- a0
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_high16: /* 0x15 */
+/* File: mips/op_const_high16.S */
+ # const/high16 vAA, /* +BBBB0000 */
+ FETCH(a0, 1) # a0 <- 0000BBBB (zero-extended)
+ GET_OPA(a3) # a3 <- AA
+ sll a0, a0, 16 # a0 <- BBBB0000
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a3, t0) # vAA <- a0
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide_16: /* 0x16 */
+/* File: mips/op_const_wide_16.S */
+ # const-wide/16 vAA, /* +BBBB */
+ FETCH_S(a0, 1) # a0 <- ssssBBBB (sign-extended)
+ GET_OPA(a3) # a3 <- AA
+ sra a1, a0, 31 # a1 <- ssssssss
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, a3) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide_32: /* 0x17 */
+/* File: mips/op_const_wide_32.S */
+ # const-wide/32 vAA, /* +BBBBbbbb */
+ FETCH(a0, 1) # a0 <- 0000bbbb (low)
+ GET_OPA(a3) # a3 <- AA
+ FETCH_S(a2, 2) # a2 <- ssssBBBB (high)
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ sll a2, a2, 16
+ or a0, a0, a2 # a0 <- BBBBbbbb
+ sra a1, a0, 31 # a1 <- ssssssss
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, a3) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide: /* 0x18 */
+/* File: mips/op_const_wide.S */
+ # const-wide vAA, /* +HHHHhhhhBBBBbbbb */
+ FETCH(a0, 1) # a0 <- bbbb (low)
+ FETCH(a1, 2) # a1 <- BBBB (low middle)
+ FETCH(a2, 3) # a2 <- hhhh (high middle)
+ sll a1, 16 #
+ or a0, a1 # a0 <- BBBBbbbb (low word)
+ FETCH(a3, 4) # a3 <- HHHH (high)
+ GET_OPA(t1) # t1 <- AA
+ sll a3, 16
+ or a1, a3, a2 # a1 <- HHHHhhhh (high word)
+ FETCH_ADVANCE_INST(5) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, t1) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide_high16: /* 0x19 */
+/* File: mips/op_const_wide_high16.S */
+ # const-wide/high16 vAA, /* +BBBB000000000000 */
+ FETCH(a1, 1) # a1 <- 0000BBBB (zero-extended)
+ GET_OPA(a3) # a3 <- AA
+ li a0, 0 # a0 <- 00000000
+ sll a1, 16 # a1 <- BBBB0000
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, a3) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_string: /* 0x1a */
+/* File: mips/op_const_string.S */
+ # const/string vAA, String /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- BBBB
+ GET_OPA(a1) # a1 <- AA
+ addu a2, rFP, OFF_FP_SHADOWFRAME # a2 <- shadow frame
+ move a3, rSELF
+ JAL(MterpConstString) # v0 <- Mterp(index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST(2) # load rINST
+ bnez v0, MterpPossibleException
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_string_jumbo: /* 0x1b */
+/* File: mips/op_const_string_jumbo.S */
+ # const/string vAA, String /* BBBBBBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- bbbb (low)
+ FETCH(a2, 2) # a2 <- BBBB (high)
+ GET_OPA(a1) # a1 <- AA
+ sll a2, a2, 16
+ or a0, a0, a2 # a0 <- BBBBbbbb
+ addu a2, rFP, OFF_FP_SHADOWFRAME # a2 <- shadow frame
+ move a3, rSELF
+ JAL(MterpConstString) # v0 <- Mterp(index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST(3) # load rINST
+ bnez v0, MterpPossibleException
+ ADVANCE(3) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_class: /* 0x1c */
+/* File: mips/op_const_class.S */
+ # const/class vAA, Class /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- BBBB
+ GET_OPA(a1) # a1 <- AA
+ addu a2, rFP, OFF_FP_SHADOWFRAME # a2 <- shadow frame
+ move a3, rSELF
+ JAL(MterpConstClass)
+ PREFETCH_INST(2) # load rINST
+ bnez v0, MterpPossibleException
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_monitor_enter: /* 0x1d */
+/* File: mips/op_monitor_enter.S */
+ /*
+ * Synchronize on an object.
+ */
+ /* monitor-enter vAA */
+ EXPORT_PC()
+ GET_OPA(a2) # a2 <- AA
+ GET_VREG(a0, a2) # a0 <- vAA (object)
+ move a1, rSELF # a1 <- self
+ JAL(artLockObjectFromCode) # v0 <- artLockObject(obj, self)
+ bnez v0, MterpException
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_monitor_exit: /* 0x1e */
+/* File: mips/op_monitor_exit.S */
+ /*
+ * Unlock an object.
+ *
+ * Exceptions that occur when unlocking a monitor need to appear as
+ * if they happened at the following instruction. See the Dalvik
+ * instruction spec.
+ */
+ /* monitor-exit vAA */
+ EXPORT_PC()
+ GET_OPA(a2) # a2 <- AA
+ GET_VREG(a0, a2) # a0 <- vAA (object)
+ move a1, rSELF # a1 <- self
+ JAL(artUnlockObjectFromCode) # v0 <- artUnlockObject(obj, self)
+ bnez v0, MterpException
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_check_cast: /* 0x1f */
+/* File: mips/op_check_cast.S */
+ /*
+ * Check to see if a cast from one class to another is allowed.
+ */
+ # check-cast vAA, class /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- BBBB
+ GET_OPA(a1) # a1 <- AA
+ EAS2(a1, rFP, a1) # a1 <- &object
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ JAL(MterpCheckCast) # v0 <- CheckCast(index, &obj, method, self)
+ PREFETCH_INST(2)
+ bnez v0, MterpPossibleException
+ ADVANCE(2)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_instance_of: /* 0x20 */
+/* File: mips/op_instance_of.S */
+ /*
+ * Check to see if an object reference is an instance of a class.
+ *
+ * Most common situation is a non-null object, being compared against
+ * an already-resolved class.
+ */
+ # instance-of vA, vB, class /* CCCC */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- CCCC
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &object
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ JAL(MterpInstanceOf) # v0 <- Mterp(index, &obj, method, self)
+ lw a1, THREAD_EXCEPTION_OFFSET(rSELF)
+ PREFETCH_INST(2) # load rINST
+ bnez a1, MterpException
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(v0, rOBJ, t0) # vA <- v0
+
+/* ------------------------------ */
+ .balign 128
+.L_op_array_length: /* 0x21 */
+/* File: mips/op_array_length.S */
+ /*
+ * Return the length of an array.
+ */
+ GET_OPB(a1) # a1 <- B
+ GET_OPA4(a2) # a2 <- A+
+ GET_VREG(a0, a1) # a0 <- vB (object ref)
+ # is object null?
+ beqz a0, common_errNullObject # yup, fail
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- array length
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a3, a2, t0) # vA <- length
+
+/* ------------------------------ */
+ .balign 128
+.L_op_new_instance: /* 0x22 */
+/* File: mips/op_new_instance.S */
+ /*
+ * Create a new instance of a class.
+ */
+ # new-instance vAA, class /* BBBB */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rSELF
+ move a2, rINST
+ JAL(MterpNewInstance)
+ beqz v0, MterpPossibleException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_new_array: /* 0x23 */
+/* File: mips/op_new_array.S */
+ /*
+ * Allocate an array of objects, specified with the array class
+ * and a count.
+ *
+ * The verifier guarantees that this is an array class, so we don't
+ * check for it here.
+ */
+ /* new-array vA, vB, class@CCCC */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ JAL(MterpNewArray)
+ beqz v0, MterpPossibleException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_filled_new_array: /* 0x24 */
+/* File: mips/op_filled_new_array.S */
+ /*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, type /* BBBB */
+ .extern MterpFilledNewArray
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME # a0 <- shadow frame
+ move a1, rPC
+ move a2, rSELF
+ JAL(MterpFilledNewArray) # v0 <- helper(shadow_frame, pc, self)
+ beqz v0, MterpPossibleException # has exception
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_filled_new_array_range: /* 0x25 */
+/* File: mips/op_filled_new_array_range.S */
+/* File: mips/op_filled_new_array.S */
+ /*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, type /* BBBB */
+ .extern MterpFilledNewArrayRange
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME # a0 <- shadow frame
+ move a1, rPC
+ move a2, rSELF
+ JAL(MterpFilledNewArrayRange) # v0 <- helper(shadow_frame, pc, self)
+ beqz v0, MterpPossibleException # has exception
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_fill_array_data: /* 0x26 */
+/* File: mips/op_fill_array_data.S */
+ /* fill-array-data vAA, +BBBBBBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- bbbb (lo)
+ FETCH(a1, 2) # a1 <- BBBB (hi)
+ GET_OPA(a3) # a3 <- AA
+ sll a1, a1, 16 # a1 <- BBBBbbbb
+ or a1, a0, a1 # a1 <- BBBBbbbb
+ GET_VREG(a0, a3) # a0 <- vAA (array object)
+ EAS1(a1, rPC, a1) # a1 <- PC + BBBBbbbb*2 (array data off.)
+ JAL(MterpFillArrayData) # v0 <- Mterp(obj, payload)
+ beqz v0, MterpPossibleException # has exception
+ FETCH_ADVANCE_INST(3) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_throw: /* 0x27 */
+/* File: mips/op_throw.S */
+ /*
+ * Throw an exception object in the current thread.
+ */
+ /* throw vAA */
+ EXPORT_PC() # exception handler can throw
+ GET_OPA(a2) # a2 <- AA
+ GET_VREG(a1, a2) # a1 <- vAA (exception object)
+ # null object?
+ beqz a1, common_errNullObject # yes, throw an NPE instead
+ sw a1, THREAD_EXCEPTION_OFFSET(rSELF) # thread->exception <- obj
+ b MterpException
+
+/* ------------------------------ */
+ .balign 128
+.L_op_goto: /* 0x28 */
+/* File: mips/op_goto.S */
+ /*
+ * Unconditional branch, 8-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto +AA */
+#if MTERP_PROFILE_BRANCHES
+ sll a0, rINST, 16 # a0 <- AAxx0000
+ sra rINST, a0, 24 # rINST <- ssssssAA (sign-extended)
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+ addu a2, rINST, rINST # a2 <- byte offset
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ /* If backwards branch refresh rIBASE */
+ bgez a2, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#else
+ sll a0, rINST, 16 # a0 <- AAxx0000
+ sra rINST, a0, 24 # rINST <- ssssssAA (sign-extended)
+ addu a2, rINST, rINST # a2 <- byte offset
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ /* If backwards branch refresh rIBASE */
+ bgez a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_goto_16: /* 0x29 */
+/* File: mips/op_goto_16.S */
+ /*
+ * Unconditional branch, 16-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto/16 +AAAA */
+#if MTERP_PROFILE_BRANCHES
+ FETCH_S(rINST, 1) # rINST <- ssssAAAA (sign-extended)
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+ addu a1, rINST, rINST # a1 <- byte offset, flags set
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#else
+ FETCH_S(rINST, 1) # rINST <- ssssAAAA (sign-extended)
+ addu a1, rINST, rINST # a1 <- byte offset, flags set
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_goto_32: /* 0x2a */
+/* File: mips/op_goto_32.S */
+ /*
+ * Unconditional branch, 32-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ *
+ * Unlike most opcodes, this one is allowed to branch to itself, so
+ * our "backward branch" test must be "<=0" instead of "<0".
+ */
+ /* goto/32 +AAAAAAAA */
+#if MTERP_PROFILE_BRANCHES
+ FETCH(a0, 1) # a0 <- aaaa (lo)
+ FETCH(a1, 2) # a1 <- AAAA (hi)
+ sll a1, a1, 16
+ or rINST, a0, a1 # rINST <- AAAAaaaa
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#else
+ FETCH(a0, 1) # a0 <- aaaa (lo)
+ FETCH(a1, 2) # a1 <- AAAA (hi)
+ sll a1, a1, 16
+ or rINST, a0, a1 # rINST <- AAAAaaaa
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_packed_switch: /* 0x2b */
+/* File: mips/op_packed_switch.S */
+ /*
+ * Handle a packed-switch or sparse-switch instruction. In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+ /* op vAA, +BBBB */
+#if MTERP_PROFILE_BRANCHES
+ FETCH(a0, 1) # a0 <- bbbb (lo)
+ FETCH(a1, 2) # a1 <- BBBB (hi)
+ GET_OPA(a3) # a3 <- AA
+ sll t0, a1, 16
+ or a0, a0, t0 # a0 <- BBBBbbbb
+ GET_VREG(a1, a3) # a1 <- vAA
+ EAS1(a0, rPC, a0) # a0 <- PC + BBBBbbbb*2
+ JAL(MterpDoPackedSwitch) # a0 <- code-unit branch offset
+ move rINST, v0
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, .Lop_packed_switch_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+#else
+ FETCH(a0, 1) # a0 <- bbbb (lo)
+ FETCH(a1, 2) # a1 <- BBBB (hi)
+ GET_OPA(a3) # a3 <- AA
+ sll t0, a1, 16
+ or a0, a0, t0 # a0 <- BBBBbbbb
+ GET_VREG(a1, a3) # a1 <- vAA
+ EAS1(a0, rPC, a0) # a0 <- PC + BBBBbbbb*2
+ JAL(MterpDoPackedSwitch) # a0 <- code-unit branch offset
+ move rINST, v0
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#endif
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sparse_switch: /* 0x2c */
+/* File: mips/op_sparse_switch.S */
+/* File: mips/op_packed_switch.S */
+ /*
+ * Handle a packed-switch or sparse-switch instruction. In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+ /* op vAA, +BBBB */
+#if MTERP_PROFILE_BRANCHES
+ FETCH(a0, 1) # a0 <- bbbb (lo)
+ FETCH(a1, 2) # a1 <- BBBB (hi)
+ GET_OPA(a3) # a3 <- AA
+ sll t0, a1, 16
+ or a0, a0, t0 # a0 <- BBBBbbbb
+ GET_VREG(a1, a3) # a1 <- vAA
+ EAS1(a0, rPC, a0) # a0 <- PC + BBBBbbbb*2
+ JAL(MterpDoSparseSwitch) # a0 <- code-unit branch offset
+ move rINST, v0
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, .Lop_sparse_switch_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+#else
+ FETCH(a0, 1) # a0 <- bbbb (lo)
+ FETCH(a1, 2) # a1 <- BBBB (hi)
+ GET_OPA(a3) # a3 <- AA
+ sll t0, a1, 16
+ or a0, a0, t0 # a0 <- BBBBbbbb
+ GET_VREG(a1, a3) # a1 <- vAA
+ EAS1(a0, rPC, a0) # a0 <- PC + BBBBbbbb*2
+ JAL(MterpDoSparseSwitch) # a0 <- code-unit branch offset
+ move rINST, v0
+ addu a1, rINST, rINST # a1 <- byte offset
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgtz a1, 1f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+1:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpl_float: /* 0x2d */
+/* File: mips/op_cmpl_float.S */
+ /*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register rTEMP based on the results of the comparison.
+ *
+ * Provide a "naninst" instruction that puts 1 or -1 into rTEMP depending
+ * on what value we'd like to return when one of the operands is NaN.
+ *
+ * The operation we're implementing is:
+ * if (x == y)
+ * return 0;
+ * else if (x < y)
+ * return -1;
+ * else if (x > y)
+ * return 1;
+ * else
+ * return {-1 or 1}; // one or both operands was NaN
+ *
+ * for: cmpl-float, cmpg-float
+ */
+ /* op vAA, vBB, vCC */
+
+ /* "clasic" form */
+ FETCH(a0, 1) # a0 <- CCBB
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8
+ GET_VREG_F(ft0, a2)
+ GET_VREG_F(ft1, a3)
+#ifdef MIPS32REVGE6
+ cmp.ult.s ft2, ft0, ft1 # Is ft0 < ft1
+ li rTEMP, -1
+ bc1nez ft2, .Lop_cmpl_float_finish
+ cmp.ult.s ft2, ft1, ft0
+ li rTEMP, 1
+ bc1nez ft2, .Lop_cmpl_float_finish
+ cmp.eq.s ft2, ft0, ft1
+ li rTEMP, 0
+ bc1nez ft2, .Lop_cmpl_float_finish
+ b .Lop_cmpl_float_nan
+#else
+ c.olt.s fcc0, ft0, ft1 # Is ft0 < ft1
+ li rTEMP, -1
+ bc1t fcc0, .Lop_cmpl_float_finish
+ c.olt.s fcc0, ft1, ft0
+ li rTEMP, 1
+ bc1t fcc0, .Lop_cmpl_float_finish
+ c.eq.s fcc0, ft0, ft1
+ li rTEMP, 0
+ bc1t fcc0, .Lop_cmpl_float_finish
+ b .Lop_cmpl_float_nan
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpg_float: /* 0x2e */
+/* File: mips/op_cmpg_float.S */
+/* File: mips/op_cmpl_float.S */
+ /*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register rTEMP based on the results of the comparison.
+ *
+ * Provide a "naninst" instruction that puts 1 or -1 into rTEMP depending
+ * on what value we'd like to return when one of the operands is NaN.
+ *
+ * The operation we're implementing is:
+ * if (x == y)
+ * return 0;
+ * else if (x < y)
+ * return -1;
+ * else if (x > y)
+ * return 1;
+ * else
+ * return {-1 or 1}; // one or both operands was NaN
+ *
+ * for: cmpl-float, cmpg-float
+ */
+ /* op vAA, vBB, vCC */
+
+ /* "clasic" form */
+ FETCH(a0, 1) # a0 <- CCBB
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8
+ GET_VREG_F(ft0, a2)
+ GET_VREG_F(ft1, a3)
+#ifdef MIPS32REVGE6
+ cmp.ult.s ft2, ft0, ft1 # Is ft0 < ft1
+ li rTEMP, -1
+ bc1nez ft2, .Lop_cmpg_float_finish
+ cmp.ult.s ft2, ft1, ft0
+ li rTEMP, 1
+ bc1nez ft2, .Lop_cmpg_float_finish
+ cmp.eq.s ft2, ft0, ft1
+ li rTEMP, 0
+ bc1nez ft2, .Lop_cmpg_float_finish
+ b .Lop_cmpg_float_nan
+#else
+ c.olt.s fcc0, ft0, ft1 # Is ft0 < ft1
+ li rTEMP, -1
+ bc1t fcc0, .Lop_cmpg_float_finish
+ c.olt.s fcc0, ft1, ft0
+ li rTEMP, 1
+ bc1t fcc0, .Lop_cmpg_float_finish
+ c.eq.s fcc0, ft0, ft1
+ li rTEMP, 0
+ bc1t fcc0, .Lop_cmpg_float_finish
+ b .Lop_cmpg_float_nan
+#endif
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpl_double: /* 0x2f */
+/* File: mips/op_cmpl_double.S */
+ /*
+ * Compare two floating-point values. Puts 0(==), 1(>), or -1(<)
+ * into the destination register (rTEMP) based on the comparison results.
+ *
+ * Provide a "naninst" instruction that puts 1 or -1 into rTEMP depending
+ * on what value we'd like to return when one of the operands is NaN.
+ *
+ * See op_cmpl_float for more details.
+ *
+ * For: cmpl-double, cmpg-double
+ */
+ /* op vAA, vBB, vCC */
+
+ FETCH(a0, 1) # a0 <- CCBB
+ and rOBJ, a0, 255 # s5 <- BB
+ srl t0, a0, 8 # t0 <- CC
+ EAS2(rOBJ, rFP, rOBJ) # s5 <- &fp[BB]
+ EAS2(t0, rFP, t0) # t0 <- &fp[CC]
+ LOAD64_F(ft0, ft0f, rOBJ)
+ LOAD64_F(ft1, ft1f, t0)
+#ifdef MIPS32REVGE6
+ cmp.ult.d ft2, ft0, ft1
+ li rTEMP, -1
+ bc1nez ft2, .Lop_cmpl_double_finish
+ cmp.ult.d ft2, ft1, ft0
+ li rTEMP, 1
+ bc1nez ft2, .Lop_cmpl_double_finish
+ cmp.eq.d ft2, ft0, ft1
+ li rTEMP, 0
+ bc1nez ft2, .Lop_cmpl_double_finish
+ b .Lop_cmpl_double_nan
+#else
+ c.olt.d fcc0, ft0, ft1
+ li rTEMP, -1
+ bc1t fcc0, .Lop_cmpl_double_finish
+ c.olt.d fcc0, ft1, ft0
+ li rTEMP, 1
+ bc1t fcc0, .Lop_cmpl_double_finish
+ c.eq.d fcc0, ft0, ft1
+ li rTEMP, 0
+ bc1t fcc0, .Lop_cmpl_double_finish
+ b .Lop_cmpl_double_nan
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpg_double: /* 0x30 */
+/* File: mips/op_cmpg_double.S */
+/* File: mips/op_cmpl_double.S */
+ /*
+ * Compare two floating-point values. Puts 0(==), 1(>), or -1(<)
+ * into the destination register (rTEMP) based on the comparison results.
+ *
+ * Provide a "naninst" instruction that puts 1 or -1 into rTEMP depending
+ * on what value we'd like to return when one of the operands is NaN.
+ *
+ * See op_cmpl_float for more details.
+ *
+ * For: cmpl-double, cmpg-double
+ */
+ /* op vAA, vBB, vCC */
+
+ FETCH(a0, 1) # a0 <- CCBB
+ and rOBJ, a0, 255 # s5 <- BB
+ srl t0, a0, 8 # t0 <- CC
+ EAS2(rOBJ, rFP, rOBJ) # s5 <- &fp[BB]
+ EAS2(t0, rFP, t0) # t0 <- &fp[CC]
+ LOAD64_F(ft0, ft0f, rOBJ)
+ LOAD64_F(ft1, ft1f, t0)
+#ifdef MIPS32REVGE6
+ cmp.ult.d ft2, ft0, ft1
+ li rTEMP, -1
+ bc1nez ft2, .Lop_cmpg_double_finish
+ cmp.ult.d ft2, ft1, ft0
+ li rTEMP, 1
+ bc1nez ft2, .Lop_cmpg_double_finish
+ cmp.eq.d ft2, ft0, ft1
+ li rTEMP, 0
+ bc1nez ft2, .Lop_cmpg_double_finish
+ b .Lop_cmpg_double_nan
+#else
+ c.olt.d fcc0, ft0, ft1
+ li rTEMP, -1
+ bc1t fcc0, .Lop_cmpg_double_finish
+ c.olt.d fcc0, ft1, ft0
+ li rTEMP, 1
+ bc1t fcc0, .Lop_cmpg_double_finish
+ c.eq.d fcc0, ft0, ft1
+ li rTEMP, 0
+ bc1t fcc0, .Lop_cmpg_double_finish
+ b .Lop_cmpg_double_nan
+#endif
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmp_long: /* 0x31 */
+/* File: mips/op_cmp_long.S */
+ /*
+ * Compare two 64-bit values
+ * x = y return 0
+ * x < y return -1
+ * x > y return 1
+ *
+ * I think I can improve on the ARM code by the following observation
+ * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
+ * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
+ * subu v0, t0, t1 # v0= -1:1:0 for [ < > = ]
+ */
+ /* cmp-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(a3, rFP, a3) # a3 <- &fp[CC]
+ LOAD64(a0, a1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64(a2, a3, a3) # a2/a3 <- vCC/vCC+1
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ slt t0, a1, a3 # compare hi
+ sgt t1, a1, a3
+ subu v0, t1, t0 # v0 <- (-1, 1, 0)
+ bnez v0, .Lop_cmp_long_finish
+ # at this point x.hi==y.hi
+ sltu t0, a0, a2 # compare lo
+ sgtu t1, a0, a2
+ subu v0, t1, t0 # v0 <- (-1, 1, 0) for [< > =]
+
+.Lop_cmp_long_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(v0, rOBJ, t0) # vAA <- v0
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_eq: /* 0x32 */
+/* File: mips/op_if_eq.S */
+/* File: mips/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ GET_OPA4(a0) # a0 <- A+
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a3, a1) # a3 <- vB
+ GET_VREG(a2, a0) # a2 <- vA
+ bne a2, a3, 1f # branch to 1 if comparison failed
+ FETCH_S(rINST, 1) # rINST<- branch offset, in code units
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a2, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ bgez a2, .L_op_if_eq_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_ne: /* 0x33 */
+/* File: mips/op_if_ne.S */
+/* File: mips/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ GET_OPA4(a0) # a0 <- A+
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a3, a1) # a3 <- vB
+ GET_VREG(a2, a0) # a2 <- vA
+ beq a2, a3, 1f # branch to 1 if comparison failed
+ FETCH_S(rINST, 1) # rINST<- branch offset, in code units
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a2, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ bgez a2, .L_op_if_ne_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_lt: /* 0x34 */
+/* File: mips/op_if_lt.S */
+/* File: mips/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ GET_OPA4(a0) # a0 <- A+
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a3, a1) # a3 <- vB
+ GET_VREG(a2, a0) # a2 <- vA
+ bge a2, a3, 1f # branch to 1 if comparison failed
+ FETCH_S(rINST, 1) # rINST<- branch offset, in code units
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a2, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ bgez a2, .L_op_if_lt_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_ge: /* 0x35 */
+/* File: mips/op_if_ge.S */
+/* File: mips/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ GET_OPA4(a0) # a0 <- A+
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a3, a1) # a3 <- vB
+ GET_VREG(a2, a0) # a2 <- vA
+ blt a2, a3, 1f # branch to 1 if comparison failed
+ FETCH_S(rINST, 1) # rINST<- branch offset, in code units
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a2, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ bgez a2, .L_op_if_ge_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_gt: /* 0x36 */
+/* File: mips/op_if_gt.S */
+/* File: mips/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ GET_OPA4(a0) # a0 <- A+
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a3, a1) # a3 <- vB
+ GET_VREG(a2, a0) # a2 <- vA
+ ble a2, a3, 1f # branch to 1 if comparison failed
+ FETCH_S(rINST, 1) # rINST<- branch offset, in code units
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a2, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ bgez a2, .L_op_if_gt_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_le: /* 0x37 */
+/* File: mips/op_if_le.S */
+/* File: mips/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ GET_OPA4(a0) # a0 <- A+
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a3, a1) # a3 <- vB
+ GET_VREG(a2, a0) # a2 <- vA
+ bgt a2, a3, 1f # branch to 1 if comparison failed
+ FETCH_S(rINST, 1) # rINST<- branch offset, in code units
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a2, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ bgez a2, .L_op_if_le_finish
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_eqz: /* 0x38 */
+/* File: mips/op_if_eqz.S */
+/* File: mips/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ GET_OPA(a0) # a0 <- AA
+ GET_VREG(a2, a0) # a2 <- vAA
+ FETCH_S(rINST, 1) # rINST <- branch offset, in code units
+ bne a2, zero, 1f # branch to 1 if comparison failed
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a1, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 3f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+3:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_nez: /* 0x39 */
+/* File: mips/op_if_nez.S */
+/* File: mips/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ GET_OPA(a0) # a0 <- AA
+ GET_VREG(a2, a0) # a2 <- vAA
+ FETCH_S(rINST, 1) # rINST <- branch offset, in code units
+ beq a2, zero, 1f # branch to 1 if comparison failed
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a1, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 3f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+3:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_ltz: /* 0x3a */
+/* File: mips/op_if_ltz.S */
+/* File: mips/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ GET_OPA(a0) # a0 <- AA
+ GET_VREG(a2, a0) # a2 <- vAA
+ FETCH_S(rINST, 1) # rINST <- branch offset, in code units
+ bge a2, zero, 1f # branch to 1 if comparison failed
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a1, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 3f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+3:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_gez: /* 0x3b */
+/* File: mips/op_if_gez.S */
+/* File: mips/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ GET_OPA(a0) # a0 <- AA
+ GET_VREG(a2, a0) # a2 <- vAA
+ FETCH_S(rINST, 1) # rINST <- branch offset, in code units
+ blt a2, zero, 1f # branch to 1 if comparison failed
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a1, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 3f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+3:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_gtz: /* 0x3c */
+/* File: mips/op_if_gtz.S */
+/* File: mips/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ GET_OPA(a0) # a0 <- AA
+ GET_VREG(a2, a0) # a2 <- vAA
+ FETCH_S(rINST, 1) # rINST <- branch offset, in code units
+ ble a2, zero, 1f # branch to 1 if comparison failed
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a1, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 3f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+3:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_lez: /* 0x3d */
+/* File: mips/op_if_lez.S */
+/* File: mips/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ GET_OPA(a0) # a0 <- AA
+ GET_VREG(a2, a0) # a2 <- vAA
+ FETCH_S(rINST, 1) # rINST <- branch offset, in code units
+ bgt a2, zero, 1f # branch to 1 if comparison failed
+ b 2f
+1:
+ li rINST, 2 # rINST- BYTE branch dist for not-taken
+2:
+#if MTERP_PROFILE_BRANCHES
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpProfileBranch) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement # Note: offset must be in rINST
+#endif
+ addu a1, rINST, rINST # convert to bytes
+ FETCH_ADVANCE_INST_RB(a1) # update rPC, load rINST
+ bgez a1, 3f
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ b MterpCheckSuspendAndContinue
+3:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_3e: /* 0x3e */
+/* File: mips/op_unused_3e.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_3f: /* 0x3f */
+/* File: mips/op_unused_3f.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_40: /* 0x40 */
+/* File: mips/op_unused_40.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_41: /* 0x41 */
+/* File: mips/op_unused_41.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_42: /* 0x42 */
+/* File: mips/op_unused_42.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_43: /* 0x43 */
+/* File: mips/op_unused_43.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget: /* 0x44 */
+/* File: mips/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+ * instructions. We use a pair of FETCH_Bs instead.
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 2
+ EASN(a0, a0, a1, 2) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ # a1 >= a3; compare unsigned index
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ lw a2, MIRROR_INT_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a2, rOBJ, t0) # vAA <- a2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_wide: /* 0x45 */
+/* File: mips/op_aget_wide.S */
+ /*
+ * Array get, 64 bits. vAA <- vBB[vCC].
+ *
+ * Arrays of long/double are 64-bit aligned.
+ */
+ /* aget-wide vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ EAS3(a0, a0, a1) # a0 <- arrayObj + index*width
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ LOAD64_off(a2, a3, a0, MIRROR_WIDE_ARRAY_DATA_OFFSET)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO(a2, a3, rOBJ, t0) # vAA/vAA+1 <- a2/a3
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_object: /* 0x46 */
+/* File: mips/op_aget_object.S */
+ /*
+ * Array object get. vAA <- vBB[vCC].
+ *
+ * for: aget-object
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ EXPORT_PC()
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ JAL(artAGetObjectFromMterp) # v0 <- GetObj(array, index)
+ lw a1, THREAD_EXCEPTION_OFFSET(rSELF)
+ PREFETCH_INST(2) # load rINST
+ bnez a1, MterpException
+ SET_VREG_OBJECT(v0, rOBJ) # vAA <- v0
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_boolean: /* 0x47 */
+/* File: mips/op_aget_boolean.S */
+/* File: mips/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+ * instructions. We use a pair of FETCH_Bs instead.
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 0
+ EASN(a0, a0, a1, 0) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ # a1 >= a3; compare unsigned index
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ lbu a2, MIRROR_BOOLEAN_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a2, rOBJ, t0) # vAA <- a2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_byte: /* 0x48 */
+/* File: mips/op_aget_byte.S */
+/* File: mips/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+ * instructions. We use a pair of FETCH_Bs instead.
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 0
+ EASN(a0, a0, a1, 0) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ # a1 >= a3; compare unsigned index
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ lb a2, MIRROR_BYTE_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a2, rOBJ, t0) # vAA <- a2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_char: /* 0x49 */
+/* File: mips/op_aget_char.S */
+/* File: mips/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+ * instructions. We use a pair of FETCH_Bs instead.
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 1
+ EASN(a0, a0, a1, 1) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ # a1 >= a3; compare unsigned index
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ lhu a2, MIRROR_CHAR_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a2, rOBJ, t0) # vAA <- a2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_short: /* 0x4a */
+/* File: mips/op_aget_short.S */
+/* File: mips/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+ * instructions. We use a pair of FETCH_Bs instead.
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 1
+ EASN(a0, a0, a1, 1) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ # a1 >= a3; compare unsigned index
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ lh a2, MIRROR_SHORT_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a2, rOBJ, t0) # vAA <- a2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput: /* 0x4b */
+/* File: mips/op_aput.S */
+
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 2
+ EASN(a0, a0, a1, 2) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_VREG(a2, rOBJ) # a2 <- vAA
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ sw a2, MIRROR_INT_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_wide: /* 0x4c */
+/* File: mips/op_aput_wide.S */
+ /*
+ * Array put, 64 bits. vBB[vCC] <- vAA.
+ *
+ * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
+ */
+ /* aput-wide vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(t0) # t0 <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ EAS3(a0, a0, a1) # a0 <- arrayObj + index*width
+ EAS2(rOBJ, rFP, t0) # rOBJ <- &fp[AA]
+ # compare unsigned index, length
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ LOAD64(a2, a3, rOBJ) # a2/a3 <- vAA/vAA+1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ STORE64_off(a2, a3, a0, MIRROR_WIDE_ARRAY_DATA_OFFSET) # a2/a3 <- vBB[vCC]
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_object: /* 0x4d */
+/* File: mips/op_aput_object.S */
+ /*
+ * Store an object into an array. vBB[vCC] <- vAA.
+ *
+ */
+ /* op vAA, vBB, vCC */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ JAL(MterpAputObject)
+ beqz v0, MterpPossibleException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_boolean: /* 0x4e */
+/* File: mips/op_aput_boolean.S */
+/* File: mips/op_aput.S */
+
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 0
+ EASN(a0, a0, a1, 0) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_VREG(a2, rOBJ) # a2 <- vAA
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ sb a2, MIRROR_BOOLEAN_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_byte: /* 0x4f */
+/* File: mips/op_aput_byte.S */
+/* File: mips/op_aput.S */
+
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 0
+ EASN(a0, a0, a1, 0) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_VREG(a2, rOBJ) # a2 <- vAA
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ sb a2, MIRROR_BYTE_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_char: /* 0x50 */
+/* File: mips/op_aput_char.S */
+/* File: mips/op_aput.S */
+
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 1
+ EASN(a0, a0, a1, 1) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_VREG(a2, rOBJ) # a2 <- vAA
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ sh a2, MIRROR_CHAR_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_short: /* 0x51 */
+/* File: mips/op_aput_short.S */
+/* File: mips/op_aput.S */
+
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ FETCH_B(a2, 1, 0) # a2 <- BB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ FETCH_B(a3, 1, 1) # a3 <- CC
+ GET_VREG(a0, a2) # a0 <- vBB (array object)
+ GET_VREG(a1, a3) # a1 <- vCC (requested index)
+ # null array object?
+ beqz a0, common_errNullObject # yes, bail
+ LOAD_base_offMirrorArray_length(a3, a0) # a3 <- arrayObj->length
+ .if 1
+ EASN(a0, a0, a1, 1) # a0 <- arrayObj + index*width
+ .else
+ addu a0, a0, a1
+ .endif
+ bgeu a1, a3, common_errArrayIndex # index >= length, bail
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_VREG(a2, rOBJ) # a2 <- vAA
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ sh a2, MIRROR_SHORT_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget: /* 0x52 */
+/* File: mips/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ JAL(artGet32InstanceFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT(v0, a2) # fp[A] <- v0
+ .else
+ SET_VREG(v0, a2) # fp[A] <- v0
+ .endif
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_wide: /* 0x53 */
+/* File: mips/op_iget_wide.S */
+ /*
+ * 64-bit instance field get.
+ *
+ * for: iget-wide
+ */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field byte offset
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ JAL(artGet64InstanceFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpException # bail out
+ SET_VREG64(v0, v1, a2) # fp[A] <- v0/v1
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_object: /* 0x54 */
+/* File: mips/op_iget_object.S */
+/* File: mips/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ JAL(artGetObjInstanceFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpPossibleException # bail out
+ .if 1
+ SET_VREG_OBJECT(v0, a2) # fp[A] <- v0
+ .else
+ SET_VREG(v0, a2) # fp[A] <- v0
+ .endif
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_boolean: /* 0x55 */
+/* File: mips/op_iget_boolean.S */
+/* File: mips/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ JAL(artGetBooleanInstanceFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT(v0, a2) # fp[A] <- v0
+ .else
+ SET_VREG(v0, a2) # fp[A] <- v0
+ .endif
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_byte: /* 0x56 */
+/* File: mips/op_iget_byte.S */
+/* File: mips/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ JAL(artGetByteInstanceFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT(v0, a2) # fp[A] <- v0
+ .else
+ SET_VREG(v0, a2) # fp[A] <- v0
+ .endif
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_char: /* 0x57 */
+/* File: mips/op_iget_char.S */
+/* File: mips/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ JAL(artGetCharInstanceFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT(v0, a2) # fp[A] <- v0
+ .else
+ SET_VREG(v0, a2) # fp[A] <- v0
+ .endif
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_short: /* 0x58 */
+/* File: mips/op_iget_short.S */
+/* File: mips/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ JAL(artGetShortInstanceFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT(v0, a2) # fp[A] <- v0
+ .else
+ SET_VREG(v0, a2) # fp[A] <- v0
+ .endif
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput: /* 0x59 */
+/* File: mips/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ # op vA, vB, field /* CCCC */
+ .extern artSet32InstanceFromMterp
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ GET_OPA4(a2) # a2 <- A+
+ GET_VREG(a2, a2) # a2 <- fp[A]
+ lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet32InstanceFromMterp)
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_wide: /* 0x5a */
+/* File: mips/op_iput_wide.S */
+ # iput-wide vA, vB, field /* CCCC */
+ .extern artSet64InstanceFromMterp
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ GET_OPA4(a2) # a2 <- A+
+ EAS2(a2, rFP, a2) # a2 <- &fp[A]
+ lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet64InstanceFromMterp)
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_object: /* 0x5b */
+/* File: mips/op_iput_object.S */
+ /*
+ * 32-bit instance field put.
+ *
+ * for: iput-object, iput-object-volatile
+ */
+ # op vA, vB, field /* CCCC */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ JAL(MterpIputObject)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_boolean: /* 0x5c */
+/* File: mips/op_iput_boolean.S */
+/* File: mips/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ # op vA, vB, field /* CCCC */
+ .extern artSet8InstanceFromMterp
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ GET_OPA4(a2) # a2 <- A+
+ GET_VREG(a2, a2) # a2 <- fp[A]
+ lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet8InstanceFromMterp)
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_byte: /* 0x5d */
+/* File: mips/op_iput_byte.S */
+/* File: mips/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ # op vA, vB, field /* CCCC */
+ .extern artSet8InstanceFromMterp
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ GET_OPA4(a2) # a2 <- A+
+ GET_VREG(a2, a2) # a2 <- fp[A]
+ lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet8InstanceFromMterp)
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_char: /* 0x5e */
+/* File: mips/op_iput_char.S */
+/* File: mips/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ # op vA, vB, field /* CCCC */
+ .extern artSet16InstanceFromMterp
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ GET_OPA4(a2) # a2 <- A+
+ GET_VREG(a2, a2) # a2 <- fp[A]
+ lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet16InstanceFromMterp)
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_short: /* 0x5f */
+/* File: mips/op_iput_short.S */
+/* File: mips/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ # op vA, vB, field /* CCCC */
+ .extern artSet16InstanceFromMterp
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a1, a1) # a1 <- fp[B], the object pointer
+ GET_OPA4(a2) # a2 <- A+
+ GET_VREG(a2, a2) # a2 <- fp[A]
+ lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet16InstanceFromMterp)
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget: /* 0x60 */
+/* File: mips/op_sget.S */
+ /*
+ * General SGET handler.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ # op vAA, field /* BBBB */
+ .extern artGet32StaticFromCode
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ move a2, rSELF # a2 <- self
+ JAL(artGet32StaticFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA(a2) # a2 <- AA
+ PREFETCH_INST(2)
+ bnez a3, MterpException # bail out
+.if 0
+ SET_VREG_OBJECT(v0, a2) # fp[AA] <- v0
+.else
+ SET_VREG(v0, a2) # fp[AA] <- v0
+.endif
+ ADVANCE(2)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_wide: /* 0x61 */
+/* File: mips/op_sget_wide.S */
+ /*
+ * 64-bit SGET handler.
+ */
+ # sget-wide vAA, field /* BBBB */
+ .extern artGet64StaticFromCode
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ move a2, rSELF # a2 <- self
+ JAL(artGet64StaticFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ bnez a3, MterpException
+ GET_OPA(a1) # a1 <- AA
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ SET_VREG64(v0, v1, a1) # vAA/vAA+1 <- v0/v1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_object: /* 0x62 */
+/* File: mips/op_sget_object.S */
+/* File: mips/op_sget.S */
+ /*
+ * General SGET handler.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ # op vAA, field /* BBBB */
+ .extern artGetObjStaticFromCode
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ move a2, rSELF # a2 <- self
+ JAL(artGetObjStaticFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA(a2) # a2 <- AA
+ PREFETCH_INST(2)
+ bnez a3, MterpException # bail out
+.if 1
+ SET_VREG_OBJECT(v0, a2) # fp[AA] <- v0
+.else
+ SET_VREG(v0, a2) # fp[AA] <- v0
+.endif
+ ADVANCE(2)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_boolean: /* 0x63 */
+/* File: mips/op_sget_boolean.S */
+/* File: mips/op_sget.S */
+ /*
+ * General SGET handler.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ # op vAA, field /* BBBB */
+ .extern artGetBooleanStaticFromCode
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ move a2, rSELF # a2 <- self
+ JAL(artGetBooleanStaticFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA(a2) # a2 <- AA
+ PREFETCH_INST(2)
+ bnez a3, MterpException # bail out
+.if 0
+ SET_VREG_OBJECT(v0, a2) # fp[AA] <- v0
+.else
+ SET_VREG(v0, a2) # fp[AA] <- v0
+.endif
+ ADVANCE(2)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_byte: /* 0x64 */
+/* File: mips/op_sget_byte.S */
+/* File: mips/op_sget.S */
+ /*
+ * General SGET handler.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ # op vAA, field /* BBBB */
+ .extern artGetByteStaticFromCode
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ move a2, rSELF # a2 <- self
+ JAL(artGetByteStaticFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA(a2) # a2 <- AA
+ PREFETCH_INST(2)
+ bnez a3, MterpException # bail out
+.if 0
+ SET_VREG_OBJECT(v0, a2) # fp[AA] <- v0
+.else
+ SET_VREG(v0, a2) # fp[AA] <- v0
+.endif
+ ADVANCE(2)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_char: /* 0x65 */
+/* File: mips/op_sget_char.S */
+/* File: mips/op_sget.S */
+ /*
+ * General SGET handler.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ # op vAA, field /* BBBB */
+ .extern artGetCharStaticFromCode
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ move a2, rSELF # a2 <- self
+ JAL(artGetCharStaticFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA(a2) # a2 <- AA
+ PREFETCH_INST(2)
+ bnez a3, MterpException # bail out
+.if 0
+ SET_VREG_OBJECT(v0, a2) # fp[AA] <- v0
+.else
+ SET_VREG(v0, a2) # fp[AA] <- v0
+.endif
+ ADVANCE(2)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_short: /* 0x66 */
+/* File: mips/op_sget_short.S */
+/* File: mips/op_sget.S */
+ /*
+ * General SGET handler.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ # op vAA, field /* BBBB */
+ .extern artGetShortStaticFromCode
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ move a2, rSELF # a2 <- self
+ JAL(artGetShortStaticFromCode)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA(a2) # a2 <- AA
+ PREFETCH_INST(2)
+ bnez a3, MterpException # bail out
+.if 0
+ SET_VREG_OBJECT(v0, a2) # fp[AA] <- v0
+.else
+ SET_VREG(v0, a2) # fp[AA] <- v0
+.endif
+ ADVANCE(2)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput: /* 0x67 */
+/* File: mips/op_sput.S */
+ /*
+ * General SPUT handler.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ # op vAA, field /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ GET_OPA(a3) # a3 <- AA
+ GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet32StaticFromCode)
+ bnez v0, MterpException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_wide: /* 0x68 */
+/* File: mips/op_sput_wide.S */
+ /*
+ * 64-bit SPUT handler.
+ */
+ # sput-wide vAA, field /* BBBB */
+ .extern artSet64IndirectStaticFromMterp
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref CCCC
+ lw a1, OFF_FP_METHOD(rFP) # a1 <- method
+ GET_OPA(a2) # a2 <- AA
+ EAS2(a2, rFP, a2) # a2 <- &fp[AA]
+ move a3, rSELF # a3 <- self
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet64IndirectStaticFromMterp)
+ bnez v0, MterpException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_object: /* 0x69 */
+/* File: mips/op_sput_object.S */
+ /*
+ * General 32-bit SPUT handler.
+ *
+ * for: sput-object,
+ */
+ /* op vAA, field@BBBB */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ JAL(MterpSputObject)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_boolean: /* 0x6a */
+/* File: mips/op_sput_boolean.S */
+/* File: mips/op_sput.S */
+ /*
+ * General SPUT handler.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ # op vAA, field /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ GET_OPA(a3) # a3 <- AA
+ GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet8StaticFromCode)
+ bnez v0, MterpException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_byte: /* 0x6b */
+/* File: mips/op_sput_byte.S */
+/* File: mips/op_sput.S */
+ /*
+ * General SPUT handler.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ # op vAA, field /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ GET_OPA(a3) # a3 <- AA
+ GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet8StaticFromCode)
+ bnez v0, MterpException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_char: /* 0x6c */
+/* File: mips/op_sput_char.S */
+/* File: mips/op_sput.S */
+ /*
+ * General SPUT handler.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ # op vAA, field /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ GET_OPA(a3) # a3 <- AA
+ GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet16StaticFromCode)
+ bnez v0, MterpException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_short: /* 0x6d */
+/* File: mips/op_sput_short.S */
+/* File: mips/op_sput.S */
+ /*
+ * General SPUT handler.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ # op vAA, field /* BBBB */
+ EXPORT_PC()
+ FETCH(a0, 1) # a0 <- field ref BBBB
+ GET_OPA(a3) # a3 <- AA
+ GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ PREFETCH_INST(2) # load rINST
+ JAL(artSet16StaticFromCode)
+ bnez v0, MterpException # bail out
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual: /* 0x6e */
+/* File: mips/op_invoke_virtual.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeVirtual
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeVirtual)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_super: /* 0x6f */
+/* File: mips/op_invoke_super.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeSuper
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeSuper)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_direct: /* 0x70 */
+/* File: mips/op_invoke_direct.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeDirect
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeDirect)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_static: /* 0x71 */
+/* File: mips/op_invoke_static.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeStatic
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeStatic)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_interface: /* 0x72 */
+/* File: mips/op_invoke_interface.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeInterface
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeInterface)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_void_no_barrier: /* 0x73 */
+/* File: mips/op_return_void_no_barrier.S */
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqz ra, 1f
+ JAL(MterpSuspendCheck) # (self)
+1:
+ move v0, zero
+ move v1, zero
+ b MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual_range: /* 0x74 */
+/* File: mips/op_invoke_virtual_range.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeVirtualRange
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeVirtualRange)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_super_range: /* 0x75 */
+/* File: mips/op_invoke_super_range.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeSuperRange
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeSuperRange)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_direct_range: /* 0x76 */
+/* File: mips/op_invoke_direct_range.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeDirectRange
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeDirectRange)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_static_range: /* 0x77 */
+/* File: mips/op_invoke_static_range.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeStaticRange
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeStaticRange)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_interface_range: /* 0x78 */
+/* File: mips/op_invoke_interface_range.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeInterfaceRange
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeInterfaceRange)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_79: /* 0x79 */
+/* File: mips/op_unused_79.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_7a: /* 0x7a */
+/* File: mips/op_unused_7a.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_int: /* 0x7b */
+/* File: mips/op_neg_int.S */
+/* File: mips/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+ * int-to-byte, int-to-char, int-to-short
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(t0) # t0 <- A+
+ GET_VREG(a0, a3) # a0 <- vB
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ # optional op
+ negu a0, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ SET_VREG_GOTO(a0, t0, t1) # vAA <- result0
+ /* 9-10 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_not_int: /* 0x7c */
+/* File: mips/op_not_int.S */
+/* File: mips/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+ * int-to-byte, int-to-char, int-to-short
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(t0) # t0 <- A+
+ GET_VREG(a0, a3) # a0 <- vB
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ # optional op
+ not a0, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ SET_VREG_GOTO(a0, t0, t1) # vAA <- result0
+ /* 9-10 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_long: /* 0x7d */
+/* File: mips/op_neg_long.S */
+/* File: mips/unopWide.S */
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0/a1".
+ * This could be MIPS instruction or a function call.
+ *
+ * For: neg-long, not-long, neg-double,
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64(a0, a1, a3) # a0/a1 <- vAA
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ negu v0, a0 # optional op
+ negu v1, a1; sltu a0, zero, v0; subu v1, v1, a0 # a0/a1 <- op, a2-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(v0, v1, rOBJ) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_not_long: /* 0x7e */
+/* File: mips/op_not_long.S */
+/* File: mips/unopWide.S */
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0/a1".
+ * This could be MIPS instruction or a function call.
+ *
+ * For: neg-long, not-long, neg-double,
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64(a0, a1, a3) # a0/a1 <- vAA
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ not a0, a0 # optional op
+ not a1, a1 # a0/a1 <- op, a2-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, rOBJ) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_float: /* 0x7f */
+/* File: mips/op_neg_float.S */
+/* File: mips/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+ * int-to-byte, int-to-char, int-to-short
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(t0) # t0 <- A+
+ GET_VREG(a0, a3) # a0 <- vB
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ # optional op
+ addu a0, a0, 0x80000000 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ SET_VREG_GOTO(a0, t0, t1) # vAA <- result0
+ /* 9-10 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_double: /* 0x80 */
+/* File: mips/op_neg_double.S */
+/* File: mips/unopWide.S */
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0/a1".
+ * This could be MIPS instruction or a function call.
+ *
+ * For: neg-long, not-long, neg-double,
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64(a0, a1, a3) # a0/a1 <- vAA
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ # optional op
+ addu a1, a1, 0x80000000 # a0/a1 <- op, a2-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, rOBJ) # vAA <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_long: /* 0x81 */
+/* File: mips/op_int_to_long.S */
+/* File: mips/unopWider.S */
+ /*
+ * Generic 32bit-to-64bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0", where
+ * "result" is a 64-bit quantity in a0/a1.
+ *
+ * For: int-to-long
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, a3) # a0 <- vB
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ # optional op
+ sra a1, a0, 31 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, rOBJ) # vA/vA+1 <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 10-11 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_float: /* 0x82 */
+/* File: mips/op_int_to_float.S */
+/* File: mips/funop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: int-to-float, float-to-int
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(rOBJ) # t0 <- A+
+ GET_VREG_F(fa0, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ cvt.s.w fv0, fa0
+
+.Lop_int_to_float_set_vreg_f:
+ SET_VREG_F(fv0, rOBJ)
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ GOTO_OPCODE(t1) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_double: /* 0x83 */
+/* File: mips/op_int_to_double.S */
+/* File: mips/funopWider.S */
+ /*
+ * Generic 32bit-to-64bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0", where
+ * "result" is a 64-bit quantity in a0/a1.
+ *
+ * For: int-to-double, float-to-long, float-to-double
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ cvt.d.w fv0, fa0
+
+.Lop_int_to_double_set_vreg:
+ SET_VREG64_F(fv0, fv0f, rOBJ) # vA/vA+1 <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_long_to_int: /* 0x84 */
+/* File: mips/op_long_to_int.S */
+/* we ignore the high word, making this equivalent to a 32-bit reg move */
+/* File: mips/op_move.S */
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ GET_OPB(a1) # a1 <- B from 15:12
+ GET_OPA4(a0) # a0 <- A from 11:8
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_VREG(a2, a1) # a2 <- fp[B]
+ GET_INST_OPCODE(t0) # t0 <- opcode from rINST
+ .if 0
+ SET_VREG_OBJECT(a2, a0) # fp[A] <- a2
+ .else
+ SET_VREG(a2, a0) # fp[A] <- a2
+ .endif
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_long_to_float: /* 0x85 */
+/* File: mips/op_long_to_float.S */
+/* File: mips/unopNarrower.S */
+ /*
+ * Generic 64bit-to-32bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0/a1", where
+ * "result" is a 32-bit quantity in a0.
+ *
+ * For: long-to-float, double-to-int, double-to-float
+ * If hard floating point support is available, use fa0 as the parameter,
+ * except for long-to-float opcode.
+ * (This would work for long-to-int, but that instruction is actually
+ * an exact match for OP_MOVE.)
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(rOBJ) # t1 <- A+
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64(rARG0, rARG1, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ JAL(__floatdisf)
+
+.Lop_long_to_float_set_vreg_f:
+ SET_VREG_F(fv0, rOBJ) # vA <- result0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_long_to_double: /* 0x86 */
+/* File: mips/op_long_to_double.S */
+/* File: mips/funopWide.S */
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0/a1".
+ * This could be a MIPS instruction or a function call.
+ *
+ * long-to-double, double-to-long
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # t1 <- A+
+ GET_OPB(a3) # a3 <- B
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64(rARG0, rARG1, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ # optional op
+ JAL(__floatdidf) # a0/a1 <- op, a2-a3 changed
+
+.Lop_long_to_double_set_vreg:
+ SET_VREG64_F(fv0, fv0f, rOBJ) # vAA <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_float_to_int: /* 0x87 */
+/* File: mips/op_float_to_int.S */
+/* File: mips/funop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: int-to-float, float-to-int
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(rOBJ) # t0 <- A+
+ GET_VREG_F(fa0, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ b f2i_doconv
+
+.Lop_float_to_int_set_vreg_f:
+ SET_VREG_F(fv0, rOBJ)
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ GOTO_OPCODE(t1) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_float_to_long: /* 0x88 */
+/* File: mips/op_float_to_long.S */
+/* File: mips/funopWider.S */
+ /*
+ * Generic 32bit-to-64bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0", where
+ * "result" is a 64-bit quantity in a0/a1.
+ *
+ * For: int-to-double, float-to-long, float-to-double
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ b f2l_doconv
+
+.Lop_float_to_long_set_vreg:
+ SET_VREG64(rRESULT0, rRESULT1, rOBJ) # vA/vA+1 <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_float_to_double: /* 0x89 */
+/* File: mips/op_float_to_double.S */
+/* File: mips/funopWider.S */
+ /*
+ * Generic 32bit-to-64bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0", where
+ * "result" is a 64-bit quantity in a0/a1.
+ *
+ * For: int-to-double, float-to-long, float-to-double
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ cvt.d.s fv0, fa0
+
+.Lop_float_to_double_set_vreg:
+ SET_VREG64_F(fv0, fv0f, rOBJ) # vA/vA+1 <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_double_to_int: /* 0x8a */
+/* File: mips/op_double_to_int.S */
+/* File: mips/unopNarrower.S */
+ /*
+ * Generic 64bit-to-32bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0/a1", where
+ * "result" is a 32-bit quantity in a0.
+ *
+ * For: long-to-float, double-to-int, double-to-float
+ * If hard floating point support is available, use fa0 as the parameter,
+ * except for long-to-float opcode.
+ * (This would work for long-to-int, but that instruction is actually
+ * an exact match for OP_MOVE.)
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(rOBJ) # t1 <- A+
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64_F(fa0, fa0f, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ b d2i_doconv
+
+.Lop_double_to_int_set_vreg_f:
+ SET_VREG_F(fv0, rOBJ) # vA <- result0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/*
+ * Convert the double in a0/a1 to an int in a0.
+ *
+ * We have to clip values to int min/max per the specification. The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer. The EABI convert function isn't doing this for us.
+ */
+
+/* ------------------------------ */
+ .balign 128
+.L_op_double_to_long: /* 0x8b */
+/* File: mips/op_double_to_long.S */
+/* File: mips/funopWide.S */
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0/a1".
+ * This could be a MIPS instruction or a function call.
+ *
+ * long-to-double, double-to-long
+ */
+ /* unop vA, vB */
+ GET_OPA4(rOBJ) # t1 <- A+
+ GET_OPB(a3) # a3 <- B
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64_F(fa0, fa0f, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ # optional op
+ b d2l_doconv # a0/a1 <- op, a2-a3 changed
+
+.Lop_double_to_long_set_vreg:
+ SET_VREG64(rRESULT0, rRESULT1, rOBJ) # vAA <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_double_to_float: /* 0x8c */
+/* File: mips/op_double_to_float.S */
+/* File: mips/unopNarrower.S */
+ /*
+ * Generic 64bit-to-32bit unary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = op a0/a1", where
+ * "result" is a 32-bit quantity in a0.
+ *
+ * For: long-to-float, double-to-int, double-to-float
+ * If hard floating point support is available, use fa0 as the parameter,
+ * except for long-to-float opcode.
+ * (This would work for long-to-int, but that instruction is actually
+ * an exact match for OP_MOVE.)
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(rOBJ) # t1 <- A+
+ EAS2(a3, rFP, a3) # a3 <- &fp[B]
+ LOAD64_F(fa0, fa0f, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ cvt.s.d fv0, fa0
+
+.Lop_double_to_float_set_vreg_f:
+ SET_VREG_F(fv0, rOBJ) # vA <- result0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_byte: /* 0x8d */
+/* File: mips/op_int_to_byte.S */
+/* File: mips/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+ * int-to-byte, int-to-char, int-to-short
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(t0) # t0 <- A+
+ GET_VREG(a0, a3) # a0 <- vB
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ sll a0, a0, 24 # optional op
+ sra a0, a0, 24 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ SET_VREG_GOTO(a0, t0, t1) # vAA <- result0
+ /* 9-10 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_char: /* 0x8e */
+/* File: mips/op_int_to_char.S */
+/* File: mips/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+ * int-to-byte, int-to-char, int-to-short
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(t0) # t0 <- A+
+ GET_VREG(a0, a3) # a0 <- vB
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ # optional op
+ and a0, 0xffff # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ SET_VREG_GOTO(a0, t0, t1) # vAA <- result0
+ /* 9-10 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_short: /* 0x8f */
+/* File: mips/op_int_to_short.S */
+/* File: mips/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op a0".
+ * This could be a MIPS instruction or a function call.
+ *
+ * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+ * int-to-byte, int-to-char, int-to-short
+ */
+ /* unop vA, vB */
+ GET_OPB(a3) # a3 <- B
+ GET_OPA4(t0) # t0 <- A+
+ GET_VREG(a0, a3) # a0 <- vB
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ sll a0, 16 # optional op
+ sra a0, 16 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ SET_VREG_GOTO(a0, t0, t1) # vAA <- result0
+ /* 9-10 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int: /* 0x90 */
+/* File: mips/op_add_int.S */
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ addu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_int: /* 0x91 */
+/* File: mips/op_sub_int.S */
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ subu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int: /* 0x92 */
+/* File: mips/op_mul_int.S */
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ mul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int: /* 0x93 */
+/* File: mips/op_div_int.S */
+#ifdef MIPS32REVGE6
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ div a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+#else
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ div zero, a0, a1 # optional op
+ mflo a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int: /* 0x94 */
+/* File: mips/op_rem_int.S */
+#ifdef MIPS32REVGE6
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ mod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+#else
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ div zero, a0, a1 # optional op
+ mfhi a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int: /* 0x95 */
+/* File: mips/op_and_int.S */
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int: /* 0x96 */
+/* File: mips/op_or_int.S */
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int: /* 0x97 */
+/* File: mips/op_xor_int.S */
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_int: /* 0x98 */
+/* File: mips/op_shl_int.S */
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ sll a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_int: /* 0x99 */
+/* File: mips/op_shr_int.S */
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ sra a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_int: /* 0x9a */
+/* File: mips/op_ushr_int.S */
+/* File: mips/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+ * handles it correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG(a1, a3) # a1 <- vCC
+ GET_VREG(a0, a2) # a0 <- vBB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ # optional op
+ srl a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 11-14 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_long: /* 0x9b */
+/* File: mips/op_add_long.S */
+/*
+ * The compiler generates the following sequence for
+ * [v1 v0] = [a1 a0] + [a3 a2];
+ * addu v0,a2,a0
+ * addu a1,a3,a1
+ * sltu v1,v0,a2
+ * addu v1,v1,a1
+ */
+/* File: mips/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+ * xor-long
+ *
+ * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64(a0, a1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64(a2, a3, t1) # a2/a3 <- vCC/vCC+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ addu v0, a2, a0 # optional op
+ addu a1, a3, a1; sltu v1, v0, a2; addu v1, v1, a1 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO(v0, v1, rOBJ, t0) # vAA/vAA+1 <- v0/v1
+ /* 14-17 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_long: /* 0x9c */
+/* File: mips/op_sub_long.S */
+/*
+ * For little endian the code sequence looks as follows:
+ * subu v0,a0,a2
+ * subu v1,a1,a3
+ * sltu a0,a0,v0
+ * subu v1,v1,a0
+ */
+/* File: mips/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+ * xor-long
+ *
+ * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64(a0, a1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64(a2, a3, t1) # a2/a3 <- vCC/vCC+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ subu v0, a0, a2 # optional op
+ subu v1, a1, a3; sltu a0, a0, v0; subu v1, v1, a0 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO(v0, v1, rOBJ, t0) # vAA/vAA+1 <- v0/v1
+ /* 14-17 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_long: /* 0x9d */
+/* File: mips/op_mul_long.S */
+ /*
+ * Signed 64-bit integer multiply.
+ * a1 a0
+ * x a3 a2
+ * -------------
+ * a2a1 a2a0
+ * a3a0
+ * a3a1 (<= unused)
+ * ---------------
+ * v1 v0
+ */
+ /* mul-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ and t0, a0, 255 # a2 <- BB
+ srl t1, a0, 8 # a3 <- CC
+ EAS2(t0, rFP, t0) # t0 <- &fp[BB]
+ LOAD64(a0, a1, t0) # a0/a1 <- vBB/vBB+1
+
+ EAS2(t1, rFP, t1) # t0 <- &fp[CC]
+ LOAD64(a2, a3, t1) # a2/a3 <- vCC/vCC+1
+
+ mul v1, a3, a0 # v1= a3a0
+#ifdef MIPS32REVGE6
+ mulu v0, a2, a0 # v0= a2a0
+ muhu t1, a2, a0
+#else
+ multu a2, a0
+ mfhi t1
+ mflo v0 # v0= a2a0
+#endif
+ mul t0, a2, a1 # t0= a2a1
+ addu v1, v1, t1 # v1+= hi(a2a0)
+ addu v1, v1, t0 # v1= a3a0 + a2a1;
+
+ GET_OPA(a0) # a0 <- AA
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ b .Lop_mul_long_finish
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_long: /* 0x9e */
+/* File: mips/op_div_long.S */
+/* File: mips/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+ * xor-long
+ *
+ * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64(a0, a1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64(a2, a3, t1) # a2/a3 <- vCC/vCC+1
+ .if 1
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ JAL(__divdi3) # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO(v0, v1, rOBJ, t0) # vAA/vAA+1 <- v0/v1
+ /* 14-17 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_long: /* 0x9f */
+/* File: mips/op_rem_long.S */
+/* File: mips/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+ * xor-long
+ *
+ * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64(a0, a1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64(a2, a3, t1) # a2/a3 <- vCC/vCC+1
+ .if 1
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ JAL(__moddi3) # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO(v0, v1, rOBJ, t0) # vAA/vAA+1 <- v0/v1
+ /* 14-17 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_long: /* 0xa0 */
+/* File: mips/op_and_long.S */
+/* File: mips/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+ * xor-long
+ *
+ * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64(a0, a1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64(a2, a3, t1) # a2/a3 <- vCC/vCC+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ and a0, a0, a2 # optional op
+ and a1, a1, a3 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO(a0, a1, rOBJ, t0) # vAA/vAA+1 <- a0/a1
+ /* 14-17 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_long: /* 0xa1 */
+/* File: mips/op_or_long.S */
+/* File: mips/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+ * xor-long
+ *
+ * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64(a0, a1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64(a2, a3, t1) # a2/a3 <- vCC/vCC+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ or a0, a0, a2 # optional op
+ or a1, a1, a3 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO(a0, a1, rOBJ, t0) # vAA/vAA+1 <- a0/a1
+ /* 14-17 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_long: /* 0xa2 */
+/* File: mips/op_xor_long.S */
+/* File: mips/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+ * xor-long
+ *
+ * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64(a0, a1, a2) # a0/a1 <- vBB/vBB+1
+ LOAD64(a2, a3, t1) # a2/a3 <- vCC/vCC+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ xor a0, a0, a2 # optional op
+ xor a1, a1, a3 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64_GOTO(a0, a1, rOBJ, t0) # vAA/vAA+1 <- a0/a1
+ /* 14-17 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_long: /* 0xa3 */
+/* File: mips/op_shl_long.S */
+ /*
+ * Long integer shift. This is different from the generic 32/64-bit
+ * binary operations because vAA/vBB are 64-bit but vCC (the shift
+ * distance) is 32-bit. Also, Dalvik requires us to mask off the low
+ * 6 bits of the shift distance.
+ */
+ /* shl-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(t2) # t2 <- AA
+ and a3, a0, 255 # a3 <- BB
+ srl a0, a0, 8 # a0 <- CC
+ EAS2(a3, rFP, a3) # a3 <- &fp[BB]
+ GET_VREG(a2, a0) # a2 <- vCC
+ LOAD64(a0, a1, a3) # a0/a1 <- vBB/vBB+1
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v1, a2, 0x20 # shift< shift & 0x20
+ sll v0, a0, a2 # rlo<- alo << (shift&31)
+ bnez v1, .Lop_shl_long_finish
+ not v1, a2 # rhi<- 31-shift (shift is 5b)
+ srl a0, 1
+ srl a0, v1 # alo<- alo >> (32-(shift&31))
+ sll v1, a1, a2 # rhi<- ahi << (shift&31)
+ or v1, a0 # rhi<- rhi | alo
+ SET_VREG64_GOTO(v0, v1, t2, t0) # vAA/vAA+1 <- a0/a1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_long: /* 0xa4 */
+/* File: mips/op_shr_long.S */
+ /*
+ * Long integer shift. This is different from the generic 32/64-bit
+ * binary operations because vAA/vBB are 64-bit but vCC (the shift
+ * distance) is 32-bit. Also, Dalvik requires us to mask off the low
+ * 6 bits of the shift distance.
+ */
+ /* shr-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(t3) # t3 <- AA
+ and a3, a0, 255 # a3 <- BB
+ srl a0, a0, 8 # a0 <- CC
+ EAS2(a3, rFP, a3) # a3 <- &fp[BB]
+ GET_VREG(a2, a0) # a2 <- vCC
+ LOAD64(a0, a1, a3) # a0/a1 <- vBB/vBB+1
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v0, a2, 0x20 # shift & 0x20
+ sra v1, a1, a2 # rhi<- ahi >> (shift&31)
+ bnez v0, .Lop_shr_long_finish
+ srl v0, a0, a2 # rlo<- alo >> (shift&31)
+ not a0, a2 # alo<- 31-shift (shift is 5b)
+ sll a1, 1
+ sll a1, a0 # ahi<- ahi << (32-(shift&31))
+ or v0, a1 # rlo<- rlo | ahi
+ SET_VREG64_GOTO(v0, v1, t3, t0) # vAA/VAA+1 <- v0/v0
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_long: /* 0xa5 */
+/* File: mips/op_ushr_long.S */
+ /*
+ * Long integer shift. This is different from the generic 32/64-bit
+ * binary operations because vAA/vBB are 64-bit but vCC (the shift
+ * distance) is 32-bit. Also, Dalvik requires us to mask off the low
+ * 6 bits of the shift distance.
+ */
+ /* ushr-long vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a3, a0, 255 # a3 <- BB
+ srl a0, a0, 8 # a0 <- CC
+ EAS2(a3, rFP, a3) # a3 <- &fp[BB]
+ GET_VREG(a2, a0) # a2 <- vCC
+ LOAD64(a0, a1, a3) # a0/a1 <- vBB/vBB+1
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v0, a2, 0x20 # shift & 0x20
+ srl v1, a1, a2 # rhi<- ahi >> (shift&31)
+ bnez v0, .Lop_ushr_long_finish
+ srl v0, a0, a2 # rlo<- alo >> (shift&31)
+ not a0, a2 # alo<- 31-n (shift is 5b)
+ sll a1, 1
+ sll a1, a0 # ahi<- ahi << (32-(shift&31))
+ or v0, a1 # rlo<- rlo | ahi
+ SET_VREG64_GOTO(v0, v1, rOBJ, t0) # vAA/vAA+1 <- v0/v1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_float: /* 0xa6 */
+/* File: mips/op_add_float.S */
+/* File: mips/fbinop.S */
+ /*
+ * Generic 32-bit binary float operation.
+ *
+ * For: add-fp, sub-fp, mul-fp, div-fp, rem-fp
+ */
+
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG_F(fa1, a3) # a1 <- vCC
+ GET_VREG_F(fa0, a2) # a0 <- vBB
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ add.s fv0, fa0, fa1 # f0 = result
+ SET_VREG_F(fv0, rOBJ) # vAA <- fv0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_float: /* 0xa7 */
+/* File: mips/op_sub_float.S */
+/* File: mips/fbinop.S */
+ /*
+ * Generic 32-bit binary float operation.
+ *
+ * For: add-fp, sub-fp, mul-fp, div-fp, rem-fp
+ */
+
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG_F(fa1, a3) # a1 <- vCC
+ GET_VREG_F(fa0, a2) # a0 <- vBB
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ sub.s fv0, fa0, fa1 # f0 = result
+ SET_VREG_F(fv0, rOBJ) # vAA <- fv0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_float: /* 0xa8 */
+/* File: mips/op_mul_float.S */
+/* File: mips/fbinop.S */
+ /*
+ * Generic 32-bit binary float operation.
+ *
+ * For: add-fp, sub-fp, mul-fp, div-fp, rem-fp
+ */
+
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG_F(fa1, a3) # a1 <- vCC
+ GET_VREG_F(fa0, a2) # a0 <- vBB
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ mul.s fv0, fa0, fa1 # f0 = result
+ SET_VREG_F(fv0, rOBJ) # vAA <- fv0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_float: /* 0xa9 */
+/* File: mips/op_div_float.S */
+/* File: mips/fbinop.S */
+ /*
+ * Generic 32-bit binary float operation.
+ *
+ * For: add-fp, sub-fp, mul-fp, div-fp, rem-fp
+ */
+
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG_F(fa1, a3) # a1 <- vCC
+ GET_VREG_F(fa0, a2) # a0 <- vBB
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ div.s fv0, fa0, fa1 # f0 = result
+ SET_VREG_F(fv0, rOBJ) # vAA <- fv0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_float: /* 0xaa */
+/* File: mips/op_rem_float.S */
+/* File: mips/fbinop.S */
+ /*
+ * Generic 32-bit binary float operation.
+ *
+ * For: add-fp, sub-fp, mul-fp, div-fp, rem-fp
+ */
+
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ srl a3, a0, 8 # a3 <- CC
+ and a2, a0, 255 # a2 <- BB
+ GET_VREG_F(fa1, a3) # a1 <- vCC
+ GET_VREG_F(fa0, a2) # a0 <- vBB
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ JAL(fmodf) # f0 = result
+ SET_VREG_F(fv0, rOBJ) # vAA <- fv0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_double: /* 0xab */
+/* File: mips/op_add_double.S */
+/* File: mips/fbinopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * for: add-double, sub-double, mul-double, div-double,
+ * rem-double
+ *
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64_F(fa0, fa0f, a2)
+ LOAD64_F(fa1, fa1f, t1)
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ add.d fv0, fa0, fa1
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ b .Lop_add_double_finish
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_double: /* 0xac */
+/* File: mips/op_sub_double.S */
+/* File: mips/fbinopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * for: add-double, sub-double, mul-double, div-double,
+ * rem-double
+ *
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64_F(fa0, fa0f, a2)
+ LOAD64_F(fa1, fa1f, t1)
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ sub.d fv0, fa0, fa1
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ b .Lop_sub_double_finish
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_double: /* 0xad */
+/* File: mips/op_mul_double.S */
+/* File: mips/fbinopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * for: add-double, sub-double, mul-double, div-double,
+ * rem-double
+ *
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64_F(fa0, fa0f, a2)
+ LOAD64_F(fa1, fa1f, t1)
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ mul.d fv0, fa0, fa1
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ b .Lop_mul_double_finish
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_double: /* 0xae */
+/* File: mips/op_div_double.S */
+/* File: mips/fbinopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * for: add-double, sub-double, mul-double, div-double,
+ * rem-double
+ *
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64_F(fa0, fa0f, a2)
+ LOAD64_F(fa1, fa1f, t1)
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ div.d fv0, fa0, fa1
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ b .Lop_div_double_finish
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_double: /* 0xaf */
+/* File: mips/op_rem_double.S */
+/* File: mips/fbinopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * for: add-double, sub-double, mul-double, div-double,
+ * rem-double
+ *
+ */
+ /* binop vAA, vBB, vCC */
+ FETCH(a0, 1) # a0 <- CCBB
+ GET_OPA(rOBJ) # s5 <- AA
+ and a2, a0, 255 # a2 <- BB
+ srl a3, a0, 8 # a3 <- CC
+ EAS2(a2, rFP, a2) # a2 <- &fp[BB]
+ EAS2(t1, rFP, a3) # a3 <- &fp[CC]
+ LOAD64_F(fa0, fa0f, a2)
+ LOAD64_F(fa1, fa1f, t1)
+
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ JAL(fmod)
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ b .Lop_rem_double_finish
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int_2addr: /* 0xb0 */
+/* File: mips/op_add_int_2addr.S */
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ addu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_int_2addr: /* 0xb1 */
+/* File: mips/op_sub_int_2addr.S */
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ subu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int_2addr: /* 0xb2 */
+/* File: mips/op_mul_int_2addr.S */
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ mul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int_2addr: /* 0xb3 */
+/* File: mips/op_div_int_2addr.S */
+#ifdef MIPS32REVGE6
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ div a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+#else
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ div zero, a0, a1 # optional op
+ mflo a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int_2addr: /* 0xb4 */
+/* File: mips/op_rem_int_2addr.S */
+#ifdef MIPS32REVGE6
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ mod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+#else
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ div zero, a0, a1 # optional op
+ mfhi a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int_2addr: /* 0xb5 */
+/* File: mips/op_and_int_2addr.S */
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int_2addr: /* 0xb6 */
+/* File: mips/op_or_int_2addr.S */
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int_2addr: /* 0xb7 */
+/* File: mips/op_xor_int_2addr.S */
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_int_2addr: /* 0xb8 */
+/* File: mips/op_shl_int_2addr.S */
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ sll a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_int_2addr: /* 0xb9 */
+/* File: mips/op_shr_int_2addr.S */
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ sra a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_int_2addr: /* 0xba */
+/* File: mips/op_ushr_int_2addr.S */
+/* File: mips/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a0, rOBJ) # a0 <- vA
+ GET_VREG(a1, a3) # a1 <- vB
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ srl a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_long_2addr: /* 0xbb */
+/* File: mips/op_add_long_2addr.S */
+/*
+ * See op_add_long.S for details
+ */
+/* File: mips/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+ * and-long/2addr, or-long/2addr, xor-long/2addr
+ * rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64(a2, a3, a1) # a2/a3 <- vBB/vBB+1
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ addu v0, a2, a0 # optional op
+ addu a1, a3, a1; sltu v1, v0, a2; addu v1, v1, a1 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(v0, v1, rOBJ) # vAA/vAA+1 <- v0/v1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-15 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_long_2addr: /* 0xbc */
+/* File: mips/op_sub_long_2addr.S */
+/*
+ * See op_sub_long.S for more details
+ */
+/* File: mips/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+ * and-long/2addr, or-long/2addr, xor-long/2addr
+ * rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64(a2, a3, a1) # a2/a3 <- vBB/vBB+1
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ subu v0, a0, a2 # optional op
+ subu v1, a1, a3; sltu a0, a0, v0; subu v1, v1, a0 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(v0, v1, rOBJ) # vAA/vAA+1 <- v0/v1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-15 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_long_2addr: /* 0xbd */
+/* File: mips/op_mul_long_2addr.S */
+ /*
+ * See op_mul_long.S for more details
+ */
+ /* mul-long/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64(a0, a1, t0) # vAA.low / high
+
+ GET_OPB(t1) # t1 <- B
+ EAS2(t1, rFP, t1) # t1 <- &fp[B]
+ LOAD64(a2, a3, t1) # vBB.low / high
+
+ mul v1, a3, a0 # v1= a3a0
+#ifdef MIPS32REVGE6
+ mulu v0, a2, a0 # v0= a2a0
+ muhu t1, a2, a0
+#else
+ multu a2, a0
+ mfhi t1
+ mflo v0 # v0= a2a0
+ #endif
+ mul t2, a2, a1 # t2= a2a1
+ addu v1, v1, t1 # v1= a3a0 + hi(a2a0)
+ addu v1, v1, t2 # v1= v1 + a2a1;
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t1) # extract opcode from rINST
+ # vAA <- v0 (low)
+ SET_VREG64(v0, v1, rOBJ) # vAA+1 <- v1 (high)
+ GOTO_OPCODE(t1) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_long_2addr: /* 0xbe */
+/* File: mips/op_div_long_2addr.S */
+/* File: mips/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+ * and-long/2addr, or-long/2addr, xor-long/2addr
+ * rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64(a2, a3, a1) # a2/a3 <- vBB/vBB+1
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+ .if 1
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ JAL(__divdi3) # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(v0, v1, rOBJ) # vAA/vAA+1 <- v0/v1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-15 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_long_2addr: /* 0xbf */
+/* File: mips/op_rem_long_2addr.S */
+/* File: mips/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+ * and-long/2addr, or-long/2addr, xor-long/2addr
+ * rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64(a2, a3, a1) # a2/a3 <- vBB/vBB+1
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+ .if 1
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ # optional op
+ JAL(__moddi3) # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(v0, v1, rOBJ) # vAA/vAA+1 <- v0/v1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-15 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_long_2addr: /* 0xc0 */
+/* File: mips/op_and_long_2addr.S */
+/* File: mips/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+ * and-long/2addr, or-long/2addr, xor-long/2addr
+ * rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64(a2, a3, a1) # a2/a3 <- vBB/vBB+1
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ and a0, a0, a2 # optional op
+ and a1, a1, a3 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, rOBJ) # vAA/vAA+1 <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-15 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_long_2addr: /* 0xc1 */
+/* File: mips/op_or_long_2addr.S */
+/* File: mips/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+ * and-long/2addr, or-long/2addr, xor-long/2addr
+ * rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64(a2, a3, a1) # a2/a3 <- vBB/vBB+1
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ or a0, a0, a2 # optional op
+ or a1, a1, a3 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, rOBJ) # vAA/vAA+1 <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-15 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_long_2addr: /* 0xc2 */
+/* File: mips/op_xor_long_2addr.S */
+/* File: mips/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+ * and-long/2addr, or-long/2addr, xor-long/2addr
+ * rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64(a2, a3, a1) # a2/a3 <- vBB/vBB+1
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+ .if 0
+ or t0, a2, a3 # second arg (a2-a3) is zero?
+ beqz t0, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ xor a0, a0, a2 # optional op
+ xor a1, a1, a3 # result <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, rOBJ) # vAA/vAA+1 <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+ /* 12-15 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_long_2addr: /* 0xc3 */
+/* File: mips/op_shl_long_2addr.S */
+ /*
+ * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
+ * 32-bit shift distance.
+ */
+ /* shl-long/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a2, a3) # a2 <- vB
+ EAS2(t2, rFP, rOBJ) # t2 <- &fp[A]
+ LOAD64(a0, a1, t2) # a0/a1 <- vAA/vAA+1
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v1, a2, 0x20 # shift< shift & 0x20
+ sll v0, a0, a2 # rlo<- alo << (shift&31)
+ bnez v1, .Lop_shl_long_2addr_finish
+ not v1, a2 # rhi<- 31-shift (shift is 5b)
+ srl a0, 1
+ srl a0, v1 # alo<- alo >> (32-(shift&31))
+ sll v1, a1, a2 # rhi<- ahi << (shift&31)
+ or v1, a0 # rhi<- rhi | alo
+ SET_VREG64_GOTO(v0, v1, rOBJ, t0) # vAA/vAA+1 <- a0/a1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_long_2addr: /* 0xc4 */
+/* File: mips/op_shr_long_2addr.S */
+ /*
+ * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
+ * 32-bit shift distance.
+ */
+ /* shr-long/2addr vA, vB */
+ GET_OPA4(t2) # t2 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a2, a3) # a2 <- vB
+ EAS2(t0, rFP, t2) # t0 <- &fp[A]
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v0, a2, 0x20 # shift & 0x20
+ sra v1, a1, a2 # rhi<- ahi >> (shift&31)
+ bnez v0, .Lop_shr_long_2addr_finish
+ srl v0, a0, a2 # rlo<- alo >> (shift&31)
+ not a0, a2 # alo<- 31-shift (shift is 5b)
+ sll a1, 1
+ sll a1, a0 # ahi<- ahi << (32-(shift&31))
+ or v0, a1 # rlo<- rlo | ahi
+ SET_VREG64_GOTO(v0, v1, t2, t0) # vAA/vAA+1 <- a0/a1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_long_2addr: /* 0xc5 */
+/* File: mips/op_ushr_long_2addr.S */
+ /*
+ * Long integer shift, 2addr version. vA is 64-bit value/result, vB is
+ * 32-bit shift distance.
+ */
+ /* ushr-long/2addr vA, vB */
+ GET_OPA4(t3) # t3 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG(a2, a3) # a2 <- vB
+ EAS2(t0, rFP, t3) # t0 <- &fp[A]
+ LOAD64(a0, a1, t0) # a0/a1 <- vAA/vAA+1
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+
+ andi v0, a2, 0x20 # shift & 0x20
+ srl v1, a1, a2 # rhi<- ahi >> (shift&31)
+ bnez v0, .Lop_ushr_long_2addr_finish
+ srl v0, a0, a2 # rlo<- alo >> (shift&31)
+ not a0, a2 # alo<- 31-n (shift is 5b)
+ sll a1, 1
+ sll a1, a0 # ahi<- ahi << (32-(shift&31))
+ or v0, a1 # rlo<- rlo | ahi
+ SET_VREG64_GOTO(v0, v1, t3, t0) # vAA/vAA+1 <- a0/a1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_float_2addr: /* 0xc6 */
+/* File: mips/op_add_float_2addr.S */
+/* File: mips/fbinop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr"
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr,
+ * div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # t1 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, rOBJ)
+ GET_VREG_F(fa1, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ add.s fv0, fa0, fa1
+ SET_VREG_F(fv0, rOBJ) # vAA <- result
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_float_2addr: /* 0xc7 */
+/* File: mips/op_sub_float_2addr.S */
+/* File: mips/fbinop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr"
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr,
+ * div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # t1 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, rOBJ)
+ GET_VREG_F(fa1, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ sub.s fv0, fa0, fa1
+ SET_VREG_F(fv0, rOBJ) # vAA <- result
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_float_2addr: /* 0xc8 */
+/* File: mips/op_mul_float_2addr.S */
+/* File: mips/fbinop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr"
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr,
+ * div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # t1 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, rOBJ)
+ GET_VREG_F(fa1, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ mul.s fv0, fa0, fa1
+ SET_VREG_F(fv0, rOBJ) # vAA <- result
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_float_2addr: /* 0xc9 */
+/* File: mips/op_div_float_2addr.S */
+/* File: mips/fbinop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr"
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr,
+ * div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # t1 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, rOBJ)
+ GET_VREG_F(fa1, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ div.s fv0, fa0, fa1
+ SET_VREG_F(fv0, rOBJ) # vAA <- result
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_float_2addr: /* 0xca */
+/* File: mips/op_rem_float_2addr.S */
+/* File: mips/fbinop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr"
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr,
+ * div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # t1 <- A+
+ GET_OPB(a3) # a3 <- B
+ GET_VREG_F(fa0, rOBJ)
+ GET_VREG_F(fa1, a3)
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+
+ JAL(fmodf)
+ SET_VREG_F(fv0, rOBJ) # vAA <- result
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_double_2addr: /* 0xcb */
+/* File: mips/op_add_double_2addr.S */
+/* File: mips/fbinopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+ * div-double/2addr, rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64_F(fa0, fa0f, t0)
+ LOAD64_F(fa1, fa1f, a1)
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ add.d fv0, fa0, fa1
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_double_2addr: /* 0xcc */
+/* File: mips/op_sub_double_2addr.S */
+/* File: mips/fbinopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+ * div-double/2addr, rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64_F(fa0, fa0f, t0)
+ LOAD64_F(fa1, fa1f, a1)
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ sub.d fv0, fa0, fa1
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_double_2addr: /* 0xcd */
+/* File: mips/op_mul_double_2addr.S */
+/* File: mips/fbinopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+ * div-double/2addr, rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64_F(fa0, fa0f, t0)
+ LOAD64_F(fa1, fa1f, a1)
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ mul.d fv0, fa0, fa1
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_double_2addr: /* 0xce */
+/* File: mips/op_div_double_2addr.S */
+/* File: mips/fbinopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+ * div-double/2addr, rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64_F(fa0, fa0f, t0)
+ LOAD64_F(fa1, fa1f, a1)
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ div.d fv0, fa0, fa1
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_double_2addr: /* 0xcf */
+/* File: mips/op_rem_double_2addr.S */
+/* File: mips/fbinopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0-a1 op a2-a3".
+ * This could be an MIPS instruction or a function call.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+ * div-double/2addr, rem-double/2addr
+ */
+ /* binop/2addr vA, vB */
+ GET_OPA4(rOBJ) # rOBJ <- A+
+ GET_OPB(a1) # a1 <- B
+ EAS2(a1, rFP, a1) # a1 <- &fp[B]
+ EAS2(t0, rFP, rOBJ) # t0 <- &fp[A]
+ LOAD64_F(fa0, fa0f, t0)
+ LOAD64_F(fa1, fa1f, a1)
+
+ FETCH_ADVANCE_INST(1) # advance rPC, load rINST
+ JAL(fmod)
+ SET_VREG64_F(fv0, fv0f, rOBJ)
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int_lit16: /* 0xd0 */
+/* File: mips/op_add_int_lit16.S */
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 0
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ addu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rsub_int: /* 0xd1 */
+/* File: mips/op_rsub_int.S */
+/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 0
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ subu a0, a1, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int_lit16: /* 0xd2 */
+/* File: mips/op_mul_int_lit16.S */
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 0
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ mul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int_lit16: /* 0xd3 */
+/* File: mips/op_div_int_lit16.S */
+#ifdef MIPS32REVGE6
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 1
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ div a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+#else
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 1
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ div zero, a0, a1 # optional op
+ mflo a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int_lit16: /* 0xd4 */
+/* File: mips/op_rem_int_lit16.S */
+#ifdef MIPS32REVGE6
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 1
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ mod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+#else
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 1
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ div zero, a0, a1 # optional op
+ mfhi a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int_lit16: /* 0xd5 */
+/* File: mips/op_and_int_lit16.S */
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 0
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int_lit16: /* 0xd6 */
+/* File: mips/op_or_int_lit16.S */
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 0
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int_lit16: /* 0xd7 */
+/* File: mips/op_xor_int_lit16.S */
+/* File: mips/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ # binop/lit16 vA, vB, /* +CCCC */
+ FETCH_S(a1, 1) # a1 <- ssssCCCC (sign-extended)
+ GET_OPB(a2) # a2 <- B
+ GET_OPA(rOBJ) # rOBJ <- A+
+ GET_VREG(a0, a2) # a0 <- vB
+ and rOBJ, rOBJ, 15
+ .if 0
+ # cmp a1, 0; is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-13 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int_lit8: /* 0xd8 */
+/* File: mips/op_add_int_lit8.S */
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ addu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rsub_int_lit8: /* 0xd9 */
+/* File: mips/op_rsub_int_lit8.S */
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ subu a0, a1, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int_lit8: /* 0xda */
+/* File: mips/op_mul_int_lit8.S */
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ mul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int_lit8: /* 0xdb */
+/* File: mips/op_div_int_lit8.S */
+#ifdef MIPS32REVGE6
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ div a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+#else
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ div zero, a0, a1 # optional op
+ mflo a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int_lit8: /* 0xdc */
+/* File: mips/op_rem_int_lit8.S */
+#ifdef MIPS32REVGE6
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ mod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+#else
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 1
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ div zero, a0, a1 # optional op
+ mfhi a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+#endif
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int_lit8: /* 0xdd */
+/* File: mips/op_and_int_lit8.S */
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int_lit8: /* 0xde */
+/* File: mips/op_or_int_lit8.S */
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int_lit8: /* 0xdf */
+/* File: mips/op_xor_int_lit8.S */
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_int_lit8: /* 0xe0 */
+/* File: mips/op_shl_int_lit8.S */
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ sll a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_int_lit8: /* 0xe1 */
+/* File: mips/op_shr_int_lit8.S */
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ sra a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_int_lit8: /* 0xe2 */
+/* File: mips/op_ushr_int_lit8.S */
+/* File: mips/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ # binop/lit8 vAA, vBB, /* +CC */
+ FETCH_S(a3, 1) # a3 <- ssssCCBB (sign-extended for CC)
+ GET_OPA(rOBJ) # rOBJ <- AA
+ and a2, a3, 255 # a2 <- BB
+ GET_VREG(a0, a2) # a0 <- vBB
+ sra a1, a3, 8 # a1 <- ssssssCC (sign extended)
+ .if 0
+ # is second operand zero?
+ beqz a1, common_errDivideByZero
+ .endif
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+
+ # optional op
+ srl a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, rOBJ, t0) # vAA <- a0
+ /* 10-12 instructions */
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_quick: /* 0xe3 */
+/* File: mips/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- object we're operating on
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ # check object for null
+ beqz a3, common_errNullObject # object was null
+ addu t0, a3, a1
+ lw a0, 0(t0) # a0 <- obj.field (8/16/32 bits)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a2, t0) # fp[A] <- a0
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_wide_quick: /* 0xe4 */
+/* File: mips/op_iget_wide_quick.S */
+ # iget-wide-quick vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- object we're operating on
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ # check object for null
+ beqz a3, common_errNullObject # object was null
+ addu t0, a3, a1 # t0 <- a3 + a1
+ LOAD64(a0, a1, t0) # a0 <- obj.field (64 bits, aligned)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(a0, a1, a2) # fp[A] <- a0/a1
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_object_quick: /* 0xe5 */
+/* File: mips/op_iget_object_quick.S */
+ /* For: iget-object-quick */
+ /* op vA, vB, offset@CCCC */
+ GET_OPB(a2) # a2 <- B
+ FETCH(a1, 1) # a1 <- field byte offset
+ EXPORT_PC()
+ GET_VREG(a0, a2) # a0 <- object we're operating on
+ JAL(artIGetObjectFromMterp) # v0 <- GetObj(obj, offset)
+ lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ GET_OPA4(a2) # a2<- A+
+ PREFETCH_INST(2) # load rINST
+ bnez a3, MterpPossibleException # bail out
+ SET_VREG_OBJECT(v0, a2) # fp[A] <- v0
+ ADVANCE(2) # advance rPC
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_quick: /* 0xe6 */
+/* File: mips/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- fp[B], the object pointer
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ beqz a3, common_errNullObject # object was null
+ GET_VREG(a0, a2) # a0 <- fp[A]
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ addu t0, a3, a1
+ sw a0, 0(t0) # obj.field (8/16/32 bits) <- a0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_wide_quick: /* 0xe7 */
+/* File: mips/op_iput_wide_quick.S */
+ # iput-wide-quick vA, vB, offset /* CCCC */
+ GET_OPA4(a0) # a0 <- A(+)
+ GET_OPB(a1) # a1 <- B
+ GET_VREG(a2, a1) # a2 <- fp[B], the object pointer
+ # check object for null
+ beqz a2, common_errNullObject # object was null
+ EAS2(a3, rFP, a0) # a3 <- &fp[A]
+ LOAD64(a0, a1, a3) # a0/a1 <- fp[A]
+ FETCH(a3, 1) # a3 <- field byte offset
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ addu a2, a2, a3 # obj.field (64 bits, aligned) <- a0/a1
+ STORE64(a0, a1, a2) # obj.field (64 bits, aligned) <- a0/a1
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_object_quick: /* 0xe8 */
+/* File: mips/op_iput_object_quick.S */
+ /* For: iput-object-quick */
+ # op vA, vB, offset /* CCCC */
+ EXPORT_PC()
+ addu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ JAL(MterpIputObjectQuick)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual_quick: /* 0xe9 */
+/* File: mips/op_invoke_virtual_quick.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeVirtualQuick
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeVirtualQuick)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual_range_quick: /* 0xea */
+/* File: mips/op_invoke_virtual_range_quick.S */
+/* File: mips/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */
+ .extern MterpInvokeVirtualQuickRange
+ EXPORT_PC()
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ JAL(MterpInvokeVirtualQuickRange)
+ beqz v0, MterpException
+ FETCH_ADVANCE_INST(3)
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_boolean_quick: /* 0xeb */
+/* File: mips/op_iput_boolean_quick.S */
+/* File: mips/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- fp[B], the object pointer
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ beqz a3, common_errNullObject # object was null
+ GET_VREG(a0, a2) # a0 <- fp[A]
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ addu t0, a3, a1
+ sb a0, 0(t0) # obj.field (8/16/32 bits) <- a0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_byte_quick: /* 0xec */
+/* File: mips/op_iput_byte_quick.S */
+/* File: mips/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- fp[B], the object pointer
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ beqz a3, common_errNullObject # object was null
+ GET_VREG(a0, a2) # a0 <- fp[A]
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ addu t0, a3, a1
+ sb a0, 0(t0) # obj.field (8/16/32 bits) <- a0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_char_quick: /* 0xed */
+/* File: mips/op_iput_char_quick.S */
+/* File: mips/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- fp[B], the object pointer
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ beqz a3, common_errNullObject # object was null
+ GET_VREG(a0, a2) # a0 <- fp[A]
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ addu t0, a3, a1
+ sh a0, 0(t0) # obj.field (8/16/32 bits) <- a0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_short_quick: /* 0xee */
+/* File: mips/op_iput_short_quick.S */
+/* File: mips/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- fp[B], the object pointer
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ beqz a3, common_errNullObject # object was null
+ GET_VREG(a0, a2) # a0 <- fp[A]
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ addu t0, a3, a1
+ sh a0, 0(t0) # obj.field (8/16/32 bits) <- a0
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_boolean_quick: /* 0xef */
+/* File: mips/op_iget_boolean_quick.S */
+/* File: mips/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- object we're operating on
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ # check object for null
+ beqz a3, common_errNullObject # object was null
+ addu t0, a3, a1
+ lbu a0, 0(t0) # a0 <- obj.field (8/16/32 bits)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a2, t0) # fp[A] <- a0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_byte_quick: /* 0xf0 */
+/* File: mips/op_iget_byte_quick.S */
+/* File: mips/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- object we're operating on
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ # check object for null
+ beqz a3, common_errNullObject # object was null
+ addu t0, a3, a1
+ lb a0, 0(t0) # a0 <- obj.field (8/16/32 bits)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a2, t0) # fp[A] <- a0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_char_quick: /* 0xf1 */
+/* File: mips/op_iget_char_quick.S */
+/* File: mips/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- object we're operating on
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ # check object for null
+ beqz a3, common_errNullObject # object was null
+ addu t0, a3, a1
+ lhu a0, 0(t0) # a0 <- obj.field (8/16/32 bits)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a2, t0) # fp[A] <- a0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_short_quick: /* 0xf2 */
+/* File: mips/op_iget_short_quick.S */
+/* File: mips/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ # op vA, vB, offset /* CCCC */
+ GET_OPB(a2) # a2 <- B
+ GET_VREG(a3, a2) # a3 <- object we're operating on
+ FETCH(a1, 1) # a1 <- field byte offset
+ GET_OPA4(a2) # a2 <- A(+)
+ # check object for null
+ beqz a3, common_errNullObject # object was null
+ addu t0, a3, a1
+ lh a0, 0(t0) # a0 <- obj.field (8/16/32 bits)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(a0, a2, t0) # fp[A] <- a0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_lambda: /* 0xf3 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_f4: /* 0xf4 */
+/* File: mips/op_unused_f4.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_capture_variable: /* 0xf5 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_create_lambda: /* 0xf6 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_liberate_variable: /* 0xf7 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_box_lambda: /* 0xf8 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unbox_lambda: /* 0xf9 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fa: /* 0xfa */
+/* File: mips/op_unused_fa.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fb: /* 0xfb */
+/* File: mips/op_unused_fb.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fc: /* 0xfc */
+/* File: mips/op_unused_fc.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fd: /* 0xfd */
+/* File: mips/op_unused_fd.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fe: /* 0xfe */
+/* File: mips/op_unused_fe.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_ff: /* 0xff */
+/* File: mips/op_unused_ff.S */
+/* File: mips/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+ .balign 128
+ .size artMterpAsmInstructionStart, .-artMterpAsmInstructionStart
+ .global artMterpAsmInstructionEnd
+artMterpAsmInstructionEnd:
+
+/*
+ * ===========================================================================
+ * Sister implementations
+ * ===========================================================================
+ */
+ .global artMterpAsmSisterStart
+ .type artMterpAsmSisterStart, %function
+ .text
+ .balign 4
+artMterpAsmSisterStart:
+
+/* continuation for op_packed_switch */
+
+.Lop_packed_switch_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_sparse_switch */
+
+.Lop_sparse_switch_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_cmpl_float */
+
+.Lop_cmpl_float_nan:
+ li rTEMP, -1
+
+.Lop_cmpl_float_finish:
+ GET_OPA(rOBJ)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(rTEMP, rOBJ, t0) # vAA <- rTEMP
+
+/* continuation for op_cmpg_float */
+
+.Lop_cmpg_float_nan:
+ li rTEMP, 1
+
+.Lop_cmpg_float_finish:
+ GET_OPA(rOBJ)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(rTEMP, rOBJ, t0) # vAA <- rTEMP
+
+/* continuation for op_cmpl_double */
+
+.Lop_cmpl_double_nan:
+ li rTEMP, -1
+
+.Lop_cmpl_double_finish:
+ GET_OPA(rOBJ)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(rTEMP, rOBJ, t0) # vAA <- rTEMP
+
+/* continuation for op_cmpg_double */
+
+.Lop_cmpg_double_nan:
+ li rTEMP, 1
+
+.Lop_cmpg_double_finish:
+ GET_OPA(rOBJ)
+ FETCH_ADVANCE_INST(2) # advance rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG_GOTO(rTEMP, rOBJ, t0) # vAA <- rTEMP
+
+/* continuation for op_if_eq */
+
+.L_op_if_eq_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_if_ne */
+
+.L_op_if_ne_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_if_lt */
+
+.L_op_if_lt_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_if_ge */
+
+.L_op_if_ge_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_if_gt */
+
+.L_op_if_gt_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_if_le */
+
+.L_op_if_le_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_float_to_int */
+
+/*
+ * Not an entry point as it is used only once !!
+ */
+f2i_doconv:
+#ifdef MIPS32REVGE6
+ l.s fa1, .LFLOAT_TO_INT_max
+ cmp.ule.s ft2, fa1, fa0
+ l.s fv0, .LFLOAT_TO_INT_ret_max
+ bc1nez ft2, .Lop_float_to_int_set_vreg_f
+
+ l.s fa1, .LFLOAT_TO_INT_min
+ cmp.ule.s ft2, fa0, fa1
+ l.s fv0, .LFLOAT_TO_INT_ret_min
+ bc1nez ft2, .Lop_float_to_int_set_vreg_f
+
+ mov.s fa1, fa0
+ cmp.un.s ft2, fa0, fa1
+ li.s fv0, 0
+ bc1nez ft2, .Lop_float_to_int_set_vreg_f
+#else
+ l.s fa1, .LFLOAT_TO_INT_max
+ c.ole.s fcc0, fa1, fa0
+ l.s fv0, .LFLOAT_TO_INT_ret_max
+ bc1t .Lop_float_to_int_set_vreg_f
+
+ l.s fa1, .LFLOAT_TO_INT_min
+ c.ole.s fcc0, fa0, fa1
+ l.s fv0, .LFLOAT_TO_INT_ret_min
+ bc1t .Lop_float_to_int_set_vreg_f
+
+ mov.s fa1, fa0
+ c.un.s fcc0, fa0, fa1
+ li.s fv0, 0
+ bc1t .Lop_float_to_int_set_vreg_f
+#endif
+
+ trunc.w.s fv0, fa0
+ b .Lop_float_to_int_set_vreg_f
+
+.LFLOAT_TO_INT_max:
+ .word 0x4f000000
+.LFLOAT_TO_INT_min:
+ .word 0xcf000000
+.LFLOAT_TO_INT_ret_max:
+ .word 0x7fffffff
+.LFLOAT_TO_INT_ret_min:
+ .word 0x80000000
+
+/* continuation for op_float_to_long */
+
+f2l_doconv:
+#ifdef MIPS32REVGE6
+ l.s fa1, .LLONG_TO_max
+ cmp.ule.s ft2, fa1, fa0
+ li rRESULT0, ~0
+ li rRESULT1, ~0x80000000
+ bc1nez ft2, .Lop_float_to_long_set_vreg
+
+ l.s fa1, .LLONG_TO_min
+ cmp.ule.s ft2, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0x80000000
+ bc1nez ft2, .Lop_float_to_long_set_vreg
+
+ mov.s fa1, fa0
+ cmp.un.s ft2, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0
+ bc1nez ft2, .Lop_float_to_long_set_vreg
+#else
+ l.s fa1, .LLONG_TO_max
+ c.ole.s fcc0, fa1, fa0
+ li rRESULT0, ~0
+ li rRESULT1, ~0x80000000
+ bc1t .Lop_float_to_long_set_vreg
+
+ l.s fa1, .LLONG_TO_min
+ c.ole.s fcc0, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0x80000000
+ bc1t .Lop_float_to_long_set_vreg
+
+ mov.s fa1, fa0
+ c.un.s fcc0, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0
+ bc1t .Lop_float_to_long_set_vreg
+#endif
+
+ JAL(__fixsfdi)
+
+ b .Lop_float_to_long_set_vreg
+
+.LLONG_TO_max:
+ .word 0x5f000000
+
+.LLONG_TO_min:
+ .word 0xdf000000
+
+/* continuation for op_double_to_int */
+
+d2i_doconv:
+#ifdef MIPS32REVGE6
+ la t0, .LDOUBLE_TO_INT_max
+ LOAD64_F(fa1, fa1f, t0)
+ cmp.ule.d ft2, fa1, fa0
+ l.s fv0, .LDOUBLE_TO_INT_maxret
+ bc1nez ft2, .Lop_double_to_int_set_vreg_f
+
+ la t0, .LDOUBLE_TO_INT_min
+ LOAD64_F(fa1, fa1f, t0)
+ cmp.ule.d ft2, fa0, fa1
+ l.s fv0, .LDOUBLE_TO_INT_minret
+ bc1nez ft2, .Lop_double_to_int_set_vreg_f
+
+ mov.d fa1, fa0
+ cmp.un.d ft2, fa0, fa1
+ li.s fv0, 0
+ bc1nez ft2, .Lop_double_to_int_set_vreg_f
+#else
+ la t0, .LDOUBLE_TO_INT_max
+ LOAD64_F(fa1, fa1f, t0)
+ c.ole.d fcc0, fa1, fa0
+ l.s fv0, .LDOUBLE_TO_INT_maxret
+ bc1t .Lop_double_to_int_set_vreg_f
+
+ la t0, .LDOUBLE_TO_INT_min
+ LOAD64_F(fa1, fa1f, t0)
+ c.ole.d fcc0, fa0, fa1
+ l.s fv0, .LDOUBLE_TO_INT_minret
+ bc1t .Lop_double_to_int_set_vreg_f
+
+ mov.d fa1, fa0
+ c.un.d fcc0, fa0, fa1
+ li.s fv0, 0
+ bc1t .Lop_double_to_int_set_vreg_f
+#endif
+
+ trunc.w.d fv0, fa0
+ b .Lop_double_to_int_set_vreg_f
+
+.LDOUBLE_TO_INT_max:
+ .dword 0x41dfffffffc00000
+.LDOUBLE_TO_INT_min:
+ .dword 0xc1e0000000000000 # minint, as a double (high word)
+.LDOUBLE_TO_INT_maxret:
+ .word 0x7fffffff
+.LDOUBLE_TO_INT_minret:
+ .word 0x80000000
+
+/* continuation for op_double_to_long */
+
+d2l_doconv:
+#ifdef MIPS32REVGE6
+ la t0, .LDOUBLE_TO_LONG_max
+ LOAD64_F(fa1, fa1f, t0)
+ cmp.ule.d ft2, fa1, fa0
+ la t0, .LDOUBLE_TO_LONG_ret_max
+ LOAD64(rRESULT0, rRESULT1, t0)
+ bc1nez ft2, .Lop_double_to_long_set_vreg
+
+ la t0, .LDOUBLE_TO_LONG_min
+ LOAD64_F(fa1, fa1f, t0)
+ cmp.ule.d ft2, fa0, fa1
+ la t0, .LDOUBLE_TO_LONG_ret_min
+ LOAD64(rRESULT0, rRESULT1, t0)
+ bc1nez ft2, .Lop_double_to_long_set_vreg
+
+ mov.d fa1, fa0
+ cmp.un.d ft2, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0
+ bc1nez ft2, .Lop_double_to_long_set_vreg
+#else
+ la t0, .LDOUBLE_TO_LONG_max
+ LOAD64_F(fa1, fa1f, t0)
+ c.ole.d fcc0, fa1, fa0
+ la t0, .LDOUBLE_TO_LONG_ret_max
+ LOAD64(rRESULT0, rRESULT1, t0)
+ bc1t .Lop_double_to_long_set_vreg
+
+ la t0, .LDOUBLE_TO_LONG_min
+ LOAD64_F(fa1, fa1f, t0)
+ c.ole.d fcc0, fa0, fa1
+ la t0, .LDOUBLE_TO_LONG_ret_min
+ LOAD64(rRESULT0, rRESULT1, t0)
+ bc1t .Lop_double_to_long_set_vreg
+
+ mov.d fa1, fa0
+ c.un.d fcc0, fa0, fa1
+ li rRESULT0, 0
+ li rRESULT1, 0
+ bc1t .Lop_double_to_long_set_vreg
+#endif
+ JAL(__fixdfdi)
+ b .Lop_double_to_long_set_vreg
+
+.LDOUBLE_TO_LONG_max:
+ .dword 0x43e0000000000000 # maxlong, as a double (high word)
+.LDOUBLE_TO_LONG_min:
+ .dword 0xc3e0000000000000 # minlong, as a double (high word)
+.LDOUBLE_TO_LONG_ret_max:
+ .dword 0x7fffffffffffffff
+.LDOUBLE_TO_LONG_ret_min:
+ .dword 0x8000000000000000
+
+/* continuation for op_mul_long */
+
+.Lop_mul_long_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ SET_VREG64(v0, v1, a0) # vAA::vAA+1 <- v0(low) :: v1(high)
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_shl_long */
+
+.Lop_shl_long_finish:
+ SET_VREG64_GOTO(zero, v0, t2, t0) # vAA/vAA+1 <- rlo/rhi
+
+/* continuation for op_shr_long */
+
+.Lop_shr_long_finish:
+ sra a3, a1, 31 # a3<- sign(ah)
+ SET_VREG64_GOTO(v1, a3, t3, t0) # vAA/VAA+1 <- rlo/rhi
+
+/* continuation for op_ushr_long */
+
+.Lop_ushr_long_finish:
+ SET_VREG64_GOTO(v1, zero, rOBJ, t0) # vAA/vAA+1 <- rlo/rhi
+
+/* continuation for op_add_double */
+
+.Lop_add_double_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_sub_double */
+
+.Lop_sub_double_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_mul_double */
+
+.Lop_mul_double_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_div_double */
+
+.Lop_div_double_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_rem_double */
+
+.Lop_rem_double_finish:
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/* continuation for op_shl_long_2addr */
+
+.Lop_shl_long_2addr_finish:
+ SET_VREG64_GOTO(zero, v0, rOBJ, t0) # vAA/vAA+1 <- rlo/rhi
+
+/* continuation for op_shr_long_2addr */
+
+.Lop_shr_long_2addr_finish:
+ sra a3, a1, 31 # a3<- sign(ah)
+ SET_VREG64_GOTO(v1, a3, t2, t0) # vAA/vAA+1 <- rlo/rhi
+
+/* continuation for op_ushr_long_2addr */
+
+.Lop_ushr_long_2addr_finish:
+ SET_VREG64_GOTO(v1, zero, t3, t0) # vAA/vAA+1 <- rlo/rhi
+
+ .size artMterpAsmSisterStart, .-artMterpAsmSisterStart
+ .global artMterpAsmSisterEnd
+artMterpAsmSisterEnd:
+
+
+ .global artMterpAsmAltInstructionStart
+ .type artMterpAsmAltInstructionStart, %function
+ .text
+
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_nop: /* 0x00 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (0 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move: /* 0x01 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (1 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_from16: /* 0x02 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (2 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_16: /* 0x03 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (3 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_wide: /* 0x04 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (4 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_wide_from16: /* 0x05 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (5 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_wide_16: /* 0x06 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (6 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_object: /* 0x07 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (7 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_object_from16: /* 0x08 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (8 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_object_16: /* 0x09 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (9 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_result: /* 0x0a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (10 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_result_wide: /* 0x0b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (11 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_result_object: /* 0x0c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (12 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_exception: /* 0x0d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (13 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_void: /* 0x0e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (14 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return: /* 0x0f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (15 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_wide: /* 0x10 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (16 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_object: /* 0x11 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (17 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_4: /* 0x12 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (18 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_16: /* 0x13 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (19 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const: /* 0x14 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (20 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_high16: /* 0x15 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (21 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide_16: /* 0x16 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (22 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide_32: /* 0x17 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (23 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide: /* 0x18 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (24 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide_high16: /* 0x19 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (25 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_string: /* 0x1a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (26 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_string_jumbo: /* 0x1b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (27 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_class: /* 0x1c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (28 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_monitor_enter: /* 0x1d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (29 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_monitor_exit: /* 0x1e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (30 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_check_cast: /* 0x1f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (31 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_instance_of: /* 0x20 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (32 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_array_length: /* 0x21 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (33 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_new_instance: /* 0x22 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (34 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_new_array: /* 0x23 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (35 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_filled_new_array: /* 0x24 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (36 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_filled_new_array_range: /* 0x25 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (37 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_fill_array_data: /* 0x26 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (38 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_throw: /* 0x27 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (39 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_goto: /* 0x28 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (40 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_goto_16: /* 0x29 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (41 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_goto_32: /* 0x2a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (42 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_packed_switch: /* 0x2b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (43 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sparse_switch: /* 0x2c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (44 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpl_float: /* 0x2d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (45 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpg_float: /* 0x2e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (46 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpl_double: /* 0x2f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (47 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpg_double: /* 0x30 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (48 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmp_long: /* 0x31 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (49 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_eq: /* 0x32 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (50 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_ne: /* 0x33 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (51 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_lt: /* 0x34 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (52 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_ge: /* 0x35 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (53 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_gt: /* 0x36 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (54 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_le: /* 0x37 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (55 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_eqz: /* 0x38 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (56 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_nez: /* 0x39 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (57 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_ltz: /* 0x3a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (58 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_gez: /* 0x3b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (59 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_gtz: /* 0x3c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (60 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_lez: /* 0x3d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (61 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_3e: /* 0x3e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (62 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_3f: /* 0x3f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (63 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_40: /* 0x40 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (64 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_41: /* 0x41 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (65 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_42: /* 0x42 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (66 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_43: /* 0x43 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (67 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget: /* 0x44 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (68 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_wide: /* 0x45 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (69 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_object: /* 0x46 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (70 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_boolean: /* 0x47 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (71 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_byte: /* 0x48 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (72 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_char: /* 0x49 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (73 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_short: /* 0x4a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (74 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput: /* 0x4b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (75 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_wide: /* 0x4c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (76 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_object: /* 0x4d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (77 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_boolean: /* 0x4e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (78 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_byte: /* 0x4f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (79 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_char: /* 0x50 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (80 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_short: /* 0x51 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (81 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget: /* 0x52 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (82 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_wide: /* 0x53 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (83 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_object: /* 0x54 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (84 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_boolean: /* 0x55 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (85 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_byte: /* 0x56 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (86 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_char: /* 0x57 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (87 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_short: /* 0x58 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (88 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput: /* 0x59 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (89 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_wide: /* 0x5a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (90 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_object: /* 0x5b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (91 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_boolean: /* 0x5c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (92 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_byte: /* 0x5d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (93 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_char: /* 0x5e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (94 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_short: /* 0x5f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (95 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget: /* 0x60 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (96 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_wide: /* 0x61 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (97 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_object: /* 0x62 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (98 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_boolean: /* 0x63 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (99 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_byte: /* 0x64 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (100 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_char: /* 0x65 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (101 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_short: /* 0x66 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (102 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput: /* 0x67 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (103 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_wide: /* 0x68 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (104 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_object: /* 0x69 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (105 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_boolean: /* 0x6a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (106 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_byte: /* 0x6b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (107 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_char: /* 0x6c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (108 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_short: /* 0x6d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (109 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual: /* 0x6e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (110 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_super: /* 0x6f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (111 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_direct: /* 0x70 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (112 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_static: /* 0x71 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (113 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_interface: /* 0x72 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (114 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_void_no_barrier: /* 0x73 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (115 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual_range: /* 0x74 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (116 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_super_range: /* 0x75 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (117 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_direct_range: /* 0x76 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (118 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_static_range: /* 0x77 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (119 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_interface_range: /* 0x78 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (120 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_79: /* 0x79 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (121 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_7a: /* 0x7a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (122 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_int: /* 0x7b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (123 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_not_int: /* 0x7c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (124 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_long: /* 0x7d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (125 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_not_long: /* 0x7e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (126 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_float: /* 0x7f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (127 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_double: /* 0x80 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (128 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_long: /* 0x81 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (129 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_float: /* 0x82 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (130 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_double: /* 0x83 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (131 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_long_to_int: /* 0x84 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (132 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_long_to_float: /* 0x85 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (133 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_long_to_double: /* 0x86 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (134 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_float_to_int: /* 0x87 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (135 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_float_to_long: /* 0x88 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (136 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_float_to_double: /* 0x89 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (137 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_double_to_int: /* 0x8a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (138 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_double_to_long: /* 0x8b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (139 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_double_to_float: /* 0x8c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (140 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_byte: /* 0x8d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (141 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_char: /* 0x8e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (142 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_short: /* 0x8f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (143 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int: /* 0x90 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (144 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_int: /* 0x91 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (145 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int: /* 0x92 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (146 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int: /* 0x93 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (147 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int: /* 0x94 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (148 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int: /* 0x95 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (149 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int: /* 0x96 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (150 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int: /* 0x97 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (151 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_int: /* 0x98 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (152 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_int: /* 0x99 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (153 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_int: /* 0x9a */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (154 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_long: /* 0x9b */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (155 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_long: /* 0x9c */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (156 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_long: /* 0x9d */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (157 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_long: /* 0x9e */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (158 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_long: /* 0x9f */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (159 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_long: /* 0xa0 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (160 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_long: /* 0xa1 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (161 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_long: /* 0xa2 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (162 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_long: /* 0xa3 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (163 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_long: /* 0xa4 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (164 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_long: /* 0xa5 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (165 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_float: /* 0xa6 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (166 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_float: /* 0xa7 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (167 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_float: /* 0xa8 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (168 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_float: /* 0xa9 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (169 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_float: /* 0xaa */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (170 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_double: /* 0xab */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (171 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_double: /* 0xac */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (172 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_double: /* 0xad */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (173 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_double: /* 0xae */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (174 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_double: /* 0xaf */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (175 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int_2addr: /* 0xb0 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (176 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_int_2addr: /* 0xb1 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (177 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int_2addr: /* 0xb2 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (178 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int_2addr: /* 0xb3 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (179 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int_2addr: /* 0xb4 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (180 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int_2addr: /* 0xb5 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (181 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int_2addr: /* 0xb6 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (182 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int_2addr: /* 0xb7 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (183 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_int_2addr: /* 0xb8 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (184 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_int_2addr: /* 0xb9 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (185 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_int_2addr: /* 0xba */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (186 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_long_2addr: /* 0xbb */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (187 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_long_2addr: /* 0xbc */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (188 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_long_2addr: /* 0xbd */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (189 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_long_2addr: /* 0xbe */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (190 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_long_2addr: /* 0xbf */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (191 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_long_2addr: /* 0xc0 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (192 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_long_2addr: /* 0xc1 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (193 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_long_2addr: /* 0xc2 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (194 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_long_2addr: /* 0xc3 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (195 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_long_2addr: /* 0xc4 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (196 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_long_2addr: /* 0xc5 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (197 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_float_2addr: /* 0xc6 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (198 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_float_2addr: /* 0xc7 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (199 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_float_2addr: /* 0xc8 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (200 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_float_2addr: /* 0xc9 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (201 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_float_2addr: /* 0xca */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (202 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_double_2addr: /* 0xcb */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (203 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_double_2addr: /* 0xcc */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (204 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_double_2addr: /* 0xcd */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (205 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_double_2addr: /* 0xce */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (206 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_double_2addr: /* 0xcf */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (207 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int_lit16: /* 0xd0 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (208 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rsub_int: /* 0xd1 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (209 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int_lit16: /* 0xd2 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (210 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int_lit16: /* 0xd3 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (211 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int_lit16: /* 0xd4 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (212 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int_lit16: /* 0xd5 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (213 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int_lit16: /* 0xd6 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (214 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int_lit16: /* 0xd7 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (215 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int_lit8: /* 0xd8 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (216 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rsub_int_lit8: /* 0xd9 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (217 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int_lit8: /* 0xda */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (218 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int_lit8: /* 0xdb */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (219 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int_lit8: /* 0xdc */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (220 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int_lit8: /* 0xdd */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (221 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int_lit8: /* 0xde */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (222 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int_lit8: /* 0xdf */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (223 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_int_lit8: /* 0xe0 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (224 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_int_lit8: /* 0xe1 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (225 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_int_lit8: /* 0xe2 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (226 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_quick: /* 0xe3 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (227 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_wide_quick: /* 0xe4 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (228 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_object_quick: /* 0xe5 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (229 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_quick: /* 0xe6 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (230 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_wide_quick: /* 0xe7 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (231 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_object_quick: /* 0xe8 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (232 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual_quick: /* 0xe9 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (233 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual_range_quick: /* 0xea */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (234 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_boolean_quick: /* 0xeb */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (235 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_byte_quick: /* 0xec */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (236 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_char_quick: /* 0xed */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (237 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_short_quick: /* 0xee */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (238 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_boolean_quick: /* 0xef */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (239 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_byte_quick: /* 0xf0 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (240 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_char_quick: /* 0xf1 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (241 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_short_quick: /* 0xf2 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (242 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_lambda: /* 0xf3 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (243 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_f4: /* 0xf4 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (244 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_capture_variable: /* 0xf5 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (245 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_create_lambda: /* 0xf6 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (246 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_liberate_variable: /* 0xf7 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (247 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_box_lambda: /* 0xf8 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (248 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unbox_lambda: /* 0xf9 */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (249 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fa: /* 0xfa */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (250 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fb: /* 0xfb */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (251 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fc: /* 0xfc */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (252 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fd: /* 0xfd */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (253 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fe: /* 0xfe */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (254 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_ff: /* 0xff */
+/* File: mips/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC()
+ la ra, artMterpAsmInstructionStart + (255 * 128) # Addr of primary handler
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh IBASE
+ move a0, rSELF # arg0
+ addu a1, rFP, OFF_FP_SHADOWFRAME # arg1
+ la a2, MterpCheckBefore
+ jalr zero, a2 # Tail call to Mterp(self, shadow_frame)
+
+ .balign 128
+ .size artMterpAsmAltInstructionStart, .-artMterpAsmAltInstructionStart
+ .global artMterpAsmAltInstructionEnd
+artMterpAsmAltInstructionEnd:
+/* File: mips/footer.S */
+/*
+ * ===========================================================================
+ * Common subroutines and data
+ * ===========================================================================
+ */
+
+ .text
+ .align 2
+
+/*
+ * We've detected a condition that will result in an exception, but the exception
+ * has not yet been thrown. Just bail out to the reference interpreter to deal with it.
+ * TUNING: for consistency, we may want to just go ahead and handle these here.
+ */
+common_errDivideByZero:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogDivideByZeroException)
+#endif
+ b MterpCommonFallback
+
+common_errArrayIndex:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogArrayIndexException)
+#endif
+ b MterpCommonFallback
+
+common_errNegativeArraySize:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogNegativeArraySizeException)
+#endif
+ b MterpCommonFallback
+
+common_errNoSuchMethod:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogNoSuchMethodException)
+#endif
+ b MterpCommonFallback
+
+common_errNullObject:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogNullObjectException)
+#endif
+ b MterpCommonFallback
+
+common_exceptionThrown:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogExceptionThrownException)
+#endif
+ b MterpCommonFallback
+
+MterpSuspendFallback:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ lw a2, THREAD_FLAGS_OFFSET(rSELF)
+ JAL(MterpLogSuspendFallback)
+#endif
+ b MterpCommonFallback
+
+/*
+ * If we're here, something is out of the ordinary. If there is a pending
+ * exception, handle it. Otherwise, roll back and retry with the reference
+ * interpreter.
+ */
+MterpPossibleException:
+ lw a0, THREAD_EXCEPTION_OFFSET(rSELF)
+ beqz a0, MterpFallback # If exception, fall back to reference interpreter.
+ /* intentional fallthrough - handle pending exception. */
+/*
+ * On return from a runtime helper routine, we've found a pending exception.
+ * Can we handle it here - or need to bail out to caller?
+ *
+ */
+MterpException:
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpHandleException) # (self, shadow_frame)
+ beqz v0, MterpExceptionReturn # no local catch, back to caller.
+ lw a0, OFF_FP_CODE_ITEM(rFP)
+ lw a1, OFF_FP_DEX_PC(rFP)
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
+ addu rPC, a0, CODEITEM_INSNS_OFFSET
+ sll a1, a1, 1
+ addu rPC, rPC, a1 # generate new dex_pc_ptr
+ /* Do we need to switch interpreters? */
+ JAL(MterpShouldSwitchInterpreters)
+ bnez v0, MterpFallback
+ /* resume execution at catch block */
+ EXPORT_PC()
+ FETCH_INST()
+ GET_INST_OPCODE(t0)
+ GOTO_OPCODE(t0)
+ /* NOTE: no fallthrough */
+
+/*
+ * Check for suspend check request. Assumes rINST already loaded, rPC advanced and
+ * still needs to get the opcode and branch to it, and flags are in lr.
+ */
+MterpCheckSuspendAndContinue:
+ lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh rIBASE
+ and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ bnez ra, 1f
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+1:
+ EXPORT_PC()
+ move a0, rSELF
+ JAL(MterpSuspendCheck) # (self)
+ bnez v0, MterpFallback
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+/*
+ * On-stack replacement has happened, and now we've returned from the compiled method.
+ */
+MterpOnStackReplacement:
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ JAL(MterpLogOSR)
+#endif
+ li v0, 1 # Signal normal return
+ b MterpDone
+
+/*
+ * Bail out to reference interpreter.
+ */
+MterpFallback:
+ EXPORT_PC()
+#if MTERP_LOGGING
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ JAL(MterpLogFallback)
+#endif
+MterpCommonFallback:
+ move v0, zero # signal retry with reference interpreter.
+ b MterpDone
+/*
+ * We pushed some registers on the stack in ExecuteMterpImpl, then saved
+ * SP and LR. Here we restore SP, restore the registers, and then restore
+ * LR to PC.
+ *
+ * On entry:
+ * uint32_t* rFP (should still be live, pointer to base of vregs)
+ */
+MterpExceptionReturn:
+ li v0, 1 # signal return to caller.
+ b MterpDone
+MterpReturn:
+ lw a2, OFF_FP_RESULT_REGISTER(rFP)
+ sw v0, 0(a2)
+ sw v1, 4(a2)
+ li v0, 1 # signal return to caller.
+MterpDone:
+/* Restore from the stack and return. Frame size = STACK_SIZE */
+ STACK_LOAD_FULL()
+ jalr zero, ra
+
+ .end ExecuteMterpImpl
+
diff --git a/runtime/interpreter/mterp/out/mterp_mips64.S b/runtime/interpreter/mterp/out/mterp_mips64.S
new file mode 100644
index 0000000..7cef823
--- /dev/null
+++ b/runtime/interpreter/mterp/out/mterp_mips64.S
@@ -0,0 +1,12362 @@
+/*
+ * This file was generated automatically by gen-mterp.py for 'mips64'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: mips64/header.S */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <machine/regdef.h>
+
+/* TODO: add the missing file and use its FP register definitions. */
+/* #include <machine/fpregdef.h> */
+/* FP register definitions */
+#define f0 $f0
+#define f1 $f1
+#define f2 $f2
+#define f3 $f3
+#define f12 $f12
+#define f13 $f13
+
+/*
+ * It looks like the GNU assembler currently does not support the blec and bgtc
+ * idioms, which should translate into bgec and bltc respectively with swapped
+ * left and right register operands.
+ * TODO: remove these macros when the assembler is fixed.
+ */
+.macro blec lreg, rreg, target
+ bgec \rreg, \lreg, \target
+.endm
+.macro bgtc lreg, rreg, target
+ bltc \rreg, \lreg, \target
+.endm
+
+/*
+Mterp and MIPS64 notes:
+
+The following registers have fixed assignments:
+
+ reg nick purpose
+ s0 rPC interpreted program counter, used for fetching instructions
+ s1 rFP interpreted frame pointer, used for accessing locals and args
+ s2 rSELF self (Thread) pointer
+ s3 rINST first 16-bit code unit of current instruction
+ s4 rIBASE interpreted instruction base pointer, used for computed goto
+ s5 rREFS base of object references in shadow frame (ideally, we'll get rid of this later).
+*/
+
+/* During bringup, we'll use the shadow frame model instead of rFP */
+/* single-purpose registers, given names for clarity */
+#define rPC s0
+#define rFP s1
+#define rSELF s2
+#define rINST s3
+#define rIBASE s4
+#define rREFS s5
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "asm_support.h"
+
+/*
+ * Instead of holding a pointer to the shadow frame, we keep rFP at the base of the vregs. So,
+ * to access other shadow frame fields, we need to use a backwards offset. Define those here.
+ */
+#define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET)
+#define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET)
+#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET)
+#define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET)
+#define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET)
+#define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET)
+#define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET)
+#define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET)
+#define OFF_FP_SHADOWFRAME (-SHADOWFRAME_VREGS_OFFSET)
+
+/*
+ *
+ * The reference interpreter performs explicit suspect checks, which is somewhat wasteful.
+ * Dalvik's interpreter folded suspend checks into the jump table mechanism, and eventually
+ * mterp should do so as well.
+ */
+#define MTERP_SUSPEND 0
+
+#define MTERP_LOGGING 0
+
+/*
+ * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must
+ * be done *before* something throws.
+ *
+ * It's okay to do this more than once.
+ *
+ * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped
+ * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction
+ * offset into the code_items_[] array. For effiency, we will "export" the
+ * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC
+ * to convert to a dex pc when needed.
+ */
+.macro EXPORT_PC
+ sd rPC, OFF_FP_DEX_PC_PTR(rFP)
+.endm
+
+/*
+ * Refresh handler table.
+ */
+.macro REFRESH_IBASE
+ ld rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
+.endm
+
+/*
+ * Fetch the next instruction from rPC into rINST. Does not advance rPC.
+ */
+.macro FETCH_INST
+ lhu rINST, 0(rPC)
+.endm
+
+/* Advance rPC by some number of code units. */
+.macro ADVANCE count
+ daddu rPC, rPC, (\count) * 2
+.endm
+
+/*
+ * Fetch the next instruction from the specified offset. Advances rPC
+ * to point to the next instruction.
+ *
+ * This must come AFTER anything that can throw an exception, or the
+ * exception catch may miss. (This also implies that it must come after
+ * EXPORT_PC.)
+ */
+.macro FETCH_ADVANCE_INST count
+ ADVANCE \count
+ FETCH_INST
+.endm
+
+/*
+ * Similar to FETCH_ADVANCE_INST, but does not update rPC. Used to load
+ * rINST ahead of possible exception point. Be sure to manually advance rPC
+ * later.
+ */
+.macro PREFETCH_INST count
+ lhu rINST, ((\count) * 2)(rPC)
+.endm
+
+/*
+ * Put the instruction's opcode field into the specified register.
+ */
+.macro GET_INST_OPCODE reg
+ and \reg, rINST, 255
+.endm
+
+/*
+ * Begin executing the opcode in _reg.
+ */
+.macro GOTO_OPCODE reg
+ .set noat
+ sll AT, \reg, 7
+ daddu AT, rIBASE, AT
+ jic AT, 0
+ .set at
+.endm
+
+/*
+ * Get/set the 32-bit value from a Dalvik register.
+ * Note, GET_VREG does sign extension to 64 bits while
+ * GET_VREG_U does zero extension to 64 bits.
+ * One is useful for arithmetic while the other is
+ * useful for storing the result value as 64-bit.
+ */
+.macro GET_VREG reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lw \reg, 0(AT)
+ .set at
+.endm
+.macro GET_VREG_U reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lwu \reg, 0(AT)
+ .set at
+.endm
+.macro GET_VREG_FLOAT reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lwc1 \reg, 0(AT)
+ .set at
+.endm
+.macro SET_VREG reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ sw \reg, 0(AT)
+ dlsa AT, \vreg, rREFS, 2
+ sw zero, 0(AT)
+ .set at
+.endm
+.macro SET_VREG_OBJECT reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ sw \reg, 0(AT)
+ dlsa AT, \vreg, rREFS, 2
+ sw \reg, 0(AT)
+ .set at
+.endm
+.macro SET_VREG_FLOAT reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ swc1 \reg, 0(AT)
+ dlsa AT, \vreg, rREFS, 2
+ sw zero, 0(AT)
+ .set at
+.endm
+
+/*
+ * Get/set the 64-bit value from a Dalvik register.
+ * Avoid unaligned memory accesses.
+ * Note, SET_VREG_WIDE clobbers the register containing the value being stored.
+ * Note, SET_VREG_DOUBLE clobbers the register containing the Dalvik register number.
+ */
+.macro GET_VREG_WIDE reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lw \reg, 0(AT)
+ lw AT, 4(AT)
+ dinsu \reg, AT, 32, 32
+ .set at
+.endm
+.macro GET_VREG_DOUBLE reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ lwc1 \reg, 0(AT)
+ lw AT, 4(AT)
+ mthc1 AT, \reg
+ .set at
+.endm
+.macro SET_VREG_WIDE reg, vreg
+ .set noat
+ dlsa AT, \vreg, rFP, 2
+ sw \reg, 0(AT)
+ drotr32 \reg, \reg, 0
+ sw \reg, 4(AT)
+ dlsa AT, \vreg, rREFS, 2
+ sw zero, 0(AT)
+ sw zero, 4(AT)
+ .set at
+.endm
+.macro SET_VREG_DOUBLE reg, vreg
+ .set noat
+ dlsa AT, \vreg, rREFS, 2
+ sw zero, 0(AT)
+ sw zero, 4(AT)
+ dlsa AT, \vreg, rFP, 2
+ swc1 \reg, 0(AT)
+ mfhc1 \vreg, \reg
+ sw \vreg, 4(AT)
+ .set at
+.endm
+
+/*
+ * On-stack offsets for spilling/unspilling callee-saved registers
+ * and the frame size.
+ */
+#define STACK_OFFSET_RA 0
+#define STACK_OFFSET_GP 8
+#define STACK_OFFSET_S0 16
+#define STACK_OFFSET_S1 24
+#define STACK_OFFSET_S2 32
+#define STACK_OFFSET_S3 40
+#define STACK_OFFSET_S4 48
+#define STACK_OFFSET_S5 56
+#define STACK_SIZE 64
+
+/* Constants for float/double_to_int/long conversions */
+#define INT_MIN 0x80000000
+#define INT_MIN_AS_FLOAT 0xCF000000
+#define INT_MIN_AS_DOUBLE 0xC1E0000000000000
+#define LONG_MIN 0x8000000000000000
+#define LONG_MIN_AS_FLOAT 0xDF000000
+#define LONG_MIN_AS_DOUBLE 0xC3E0000000000000
+
+/* File: mips64/entry.S */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Interpreter entry point.
+ */
+
+ .set reorder
+
+ .text
+ .global ExecuteMterpImpl
+ .type ExecuteMterpImpl, %function
+ .balign 16
+/*
+ * On entry:
+ * a0 Thread* self
+ * a1 code_item
+ * a2 ShadowFrame
+ * a3 JValue* result_register
+ *
+ */
+ExecuteMterpImpl:
+ .cfi_startproc
+ .cpsetup t9, t8, ExecuteMterpImpl
+
+ .cfi_def_cfa sp, 0
+ daddu sp, sp, -STACK_SIZE
+ .cfi_adjust_cfa_offset STACK_SIZE
+
+ sd t8, STACK_OFFSET_GP(sp)
+ .cfi_rel_offset 28, STACK_OFFSET_GP
+ sd ra, STACK_OFFSET_RA(sp)
+ .cfi_rel_offset 31, STACK_OFFSET_RA
+
+ sd s0, STACK_OFFSET_S0(sp)
+ .cfi_rel_offset 16, STACK_OFFSET_S0
+ sd s1, STACK_OFFSET_S1(sp)
+ .cfi_rel_offset 17, STACK_OFFSET_S1
+ sd s2, STACK_OFFSET_S2(sp)
+ .cfi_rel_offset 18, STACK_OFFSET_S2
+ sd s3, STACK_OFFSET_S3(sp)
+ .cfi_rel_offset 19, STACK_OFFSET_S3
+ sd s4, STACK_OFFSET_S4(sp)
+ .cfi_rel_offset 20, STACK_OFFSET_S4
+ sd s5, STACK_OFFSET_S5(sp)
+ .cfi_rel_offset 21, STACK_OFFSET_S5
+
+ /* Remember the return register */
+ sd a3, SHADOWFRAME_RESULT_REGISTER_OFFSET(a2)
+
+ /* Remember the code_item */
+ sd a1, SHADOWFRAME_CODE_ITEM_OFFSET(a2)
+
+ /* set up "named" registers */
+ move rSELF, a0
+ daddu rFP, a2, SHADOWFRAME_VREGS_OFFSET
+ lw v0, SHADOWFRAME_NUMBER_OF_VREGS_OFFSET(a2)
+ dlsa rREFS, v0, rFP, 2
+ daddu rPC, a1, CODEITEM_INSNS_OFFSET
+ lw v0, SHADOWFRAME_DEX_PC_OFFSET(a2)
+ dlsa rPC, v0, rPC, 1
+ EXPORT_PC
+
+ /* Starting ibase */
+ REFRESH_IBASE
+
+ /* start executing the instruction at rPC */
+ FETCH_INST
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+ /* NOTE: no fallthrough */
+
+
+ .global artMterpAsmInstructionStart
+ .type artMterpAsmInstructionStart, %function
+artMterpAsmInstructionStart = .L_op_nop
+ .text
+
+/* ------------------------------ */
+ .balign 128
+.L_op_nop: /* 0x00 */
+/* File: mips64/op_nop.S */
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move: /* 0x01 */
+/* File: mips64/op_move.S */
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if 0
+ SET_VREG_OBJECT a0, a2 # vA <- vB
+ .else
+ SET_VREG a0, a2 # vA <- vB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_from16: /* 0x02 */
+/* File: mips64/op_move_from16.S */
+ /* for: move/from16, move-object/from16 */
+ /* op vAA, vBBBB */
+ lhu a3, 2(rPC) # a3 <- BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vBBBB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if 0
+ SET_VREG_OBJECT a0, a2 # vAA <- vBBBB
+ .else
+ SET_VREG a0, a2 # vAA <- vBBBB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_16: /* 0x03 */
+/* File: mips64/op_move_16.S */
+ /* for: move/16, move-object/16 */
+ /* op vAAAA, vBBBB */
+ lhu a3, 4(rPC) # a3 <- BBBB
+ lhu a2, 2(rPC) # a2 <- AAAA
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vBBBB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if 0
+ SET_VREG_OBJECT a0, a2 # vAAAA <- vBBBB
+ .else
+ SET_VREG a0, a2 # vAAAA <- vBBBB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_wide: /* 0x04 */
+/* File: mips64/op_move_wide.S */
+ /* move-wide vA, vB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ ext a3, rINST, 12, 4 # a3 <- B
+ ext a2, rINST, 8, 4 # a2 <- A
+ GET_VREG_WIDE a0, a3 # a0 <- vB
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- vB
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_wide_from16: /* 0x05 */
+/* File: mips64/op_move_wide_from16.S */
+ /* move-wide/from16 vAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ lhu a3, 2(rPC) # a3 <- BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_WIDE a0, a3 # a0 <- vBBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- vBBBB
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_wide_16: /* 0x06 */
+/* File: mips64/op_move_wide_16.S */
+ /* move-wide/16 vAAAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ lhu a3, 4(rPC) # a3 <- BBBB
+ lhu a2, 2(rPC) # a2 <- AAAA
+ GET_VREG_WIDE a0, a3 # a0 <- vBBBB
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAAAA <- vBBBB
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_object: /* 0x07 */
+/* File: mips64/op_move_object.S */
+/* File: mips64/op_move.S */
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if 1
+ SET_VREG_OBJECT a0, a2 # vA <- vB
+ .else
+ SET_VREG a0, a2 # vA <- vB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_object_from16: /* 0x08 */
+/* File: mips64/op_move_object_from16.S */
+/* File: mips64/op_move_from16.S */
+ /* for: move/from16, move-object/from16 */
+ /* op vAA, vBBBB */
+ lhu a3, 2(rPC) # a3 <- BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vBBBB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if 1
+ SET_VREG_OBJECT a0, a2 # vAA <- vBBBB
+ .else
+ SET_VREG a0, a2 # vAA <- vBBBB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_object_16: /* 0x09 */
+/* File: mips64/op_move_object_16.S */
+/* File: mips64/op_move_16.S */
+ /* for: move/16, move-object/16 */
+ /* op vAAAA, vBBBB */
+ lhu a3, 4(rPC) # a3 <- BBBB
+ lhu a2, 2(rPC) # a2 <- AAAA
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vBBBB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if 1
+ SET_VREG_OBJECT a0, a2 # vAAAA <- vBBBB
+ .else
+ SET_VREG a0, a2 # vAAAA <- vBBBB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_result: /* 0x0a */
+/* File: mips64/op_move_result.S */
+ /* for: move-result, move-result-object */
+ /* op vAA */
+ srl a2, rINST, 8 # a2 <- AA
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ ld a0, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ lw a0, 0(a0) # a0 <- result.i
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if 0
+ SET_VREG_OBJECT a0, a2 # vAA <- result
+ .else
+ SET_VREG a0, a2 # vAA <- result
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_result_wide: /* 0x0b */
+/* File: mips64/op_move_result_wide.S */
+ /* for: move-result-wide */
+ /* op vAA */
+ srl a2, rINST, 8 # a2 <- AA
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ ld a0, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ ld a0, 0(a0) # a0 <- result.j
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- result
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_result_object: /* 0x0c */
+/* File: mips64/op_move_result_object.S */
+/* File: mips64/op_move_result.S */
+ /* for: move-result, move-result-object */
+ /* op vAA */
+ srl a2, rINST, 8 # a2 <- AA
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ ld a0, OFF_FP_RESULT_REGISTER(rFP) # get pointer to result JType
+ lw a0, 0(a0) # a0 <- result.i
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if 1
+ SET_VREG_OBJECT a0, a2 # vAA <- result
+ .else
+ SET_VREG a0, a2 # vAA <- result
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_exception: /* 0x0d */
+/* File: mips64/op_move_exception.S */
+ /* move-exception vAA */
+ srl a2, rINST, 8 # a2 <- AA
+ ld a0, THREAD_EXCEPTION_OFFSET(rSELF) # load exception obj
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ SET_VREG_OBJECT a0, a2 # vAA <- exception obj
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ sd zero, THREAD_EXCEPTION_OFFSET(rSELF) # clear exception
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_void: /* 0x0e */
+/* File: mips64/op_return_void.S */
+ .extern MterpThreadFenceForConstructor
+ .extern MterpSuspendCheck
+ jal MterpThreadFenceForConstructor
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, 1f
+ jal MterpSuspendCheck # (self)
+1:
+ li a0, 0
+ b MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return: /* 0x0f */
+/* File: mips64/op_return.S */
+ /*
+ * Return a 32-bit value.
+ *
+ * for: return, return-object
+ */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ .extern MterpSuspendCheck
+ jal MterpThreadFenceForConstructor
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, 1f
+ jal MterpSuspendCheck # (self)
+1:
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_U a0, a2 # a0 <- vAA
+ b MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_wide: /* 0x10 */
+/* File: mips64/op_return_wide.S */
+ /*
+ * Return a 64-bit value.
+ */
+ /* return-wide vAA */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ .extern MterpSuspendCheck
+ jal MterpThreadFenceForConstructor
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, 1f
+ jal MterpSuspendCheck # (self)
+1:
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_WIDE a0, a2 # a0 <- vAA
+ b MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_object: /* 0x11 */
+/* File: mips64/op_return_object.S */
+/* File: mips64/op_return.S */
+ /*
+ * Return a 32-bit value.
+ *
+ * for: return, return-object
+ */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ .extern MterpSuspendCheck
+ jal MterpThreadFenceForConstructor
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, 1f
+ jal MterpSuspendCheck # (self)
+1:
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_U a0, a2 # a0 <- vAA
+ b MterpReturn
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_4: /* 0x12 */
+/* File: mips64/op_const_4.S */
+ /* const/4 vA, #+B */
+ ext a2, rINST, 8, 4 # a2 <- A
+ seh a0, rINST # sign extend B in rINST
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ sra a0, a0, 12 # shift B into its final position
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- +B
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_16: /* 0x13 */
+/* File: mips64/op_const_16.S */
+ /* const/16 vAA, #+BBBB */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- sign-extended BBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- +BBBB
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const: /* 0x14 */
+/* File: mips64/op_const.S */
+ /* const vAA, #+BBBBbbbb */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- bbbb (low)
+ lh a1, 4(rPC) # a1 <- BBBB (high)
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ ins a0, a1, 16, 16 # a0 = BBBBbbbb
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- +BBBBbbbb
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_high16: /* 0x15 */
+/* File: mips64/op_const_high16.S */
+ /* const/high16 vAA, #+BBBB0000 */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- BBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ sll a0, a0, 16 # a0 <- BBBB0000
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- +BBBB0000
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide_16: /* 0x16 */
+/* File: mips64/op_const_wide_16.S */
+ /* const-wide/16 vAA, #+BBBB */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- sign-extended BBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- +BBBB
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide_32: /* 0x17 */
+/* File: mips64/op_const_wide_32.S */
+ /* const-wide/32 vAA, #+BBBBbbbb */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- bbbb (low)
+ lh a1, 4(rPC) # a1 <- BBBB (high)
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ ins a0, a1, 16, 16 # a0 = BBBBbbbb
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- +BBBBbbbb
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide: /* 0x18 */
+/* File: mips64/op_const_wide.S */
+ /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
+ srl a4, rINST, 8 # a4 <- AA
+ lh a0, 2(rPC) # a0 <- bbbb (low)
+ lh a1, 4(rPC) # a1 <- BBBB (low middle)
+ lh a2, 6(rPC) # a2 <- hhhh (high middle)
+ lh a3, 8(rPC) # a3 <- HHHH (high)
+ FETCH_ADVANCE_INST 5 # advance rPC, load rINST
+ ins a0, a1, 16, 16 # a0 = BBBBbbbb
+ ins a2, a3, 16, 16 # a2 = HHHHhhhh
+ dinsu a0, a2, 32, 32 # a0 = HHHHhhhhBBBBbbbb
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- +HHHHhhhhBBBBbbbb
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide_high16: /* 0x19 */
+/* File: mips64/op_const_wide_high16.S */
+ /* const-wide/high16 vAA, #+BBBB000000000000 */
+ srl a2, rINST, 8 # a2 <- AA
+ lh a0, 2(rPC) # a0 <- BBBB
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ dsll32 a0, a0, 16 # a0 <- BBBB000000000000
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vAA <- +BBBB000000000000
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_string: /* 0x1a */
+/* File: mips64/op_const_string.S */
+ /* const/string vAA, String//BBBB */
+ .extern MterpConstString
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- BBBB
+ srl a1, rINST, 8 # a1 <- AA
+ daddu a2, rFP, OFF_FP_SHADOWFRAME
+ move a3, rSELF
+ jal MterpConstString # (index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST 2 # load rINST
+ bnez v0, MterpPossibleException # let reference interpreter deal with it.
+ ADVANCE 2 # advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_string_jumbo: /* 0x1b */
+/* File: mips64/op_const_string_jumbo.S */
+ /* const/string vAA, String//BBBBBBBB */
+ .extern MterpConstString
+ EXPORT_PC
+ lh a0, 2(rPC) # a0 <- bbbb (low)
+ lh a4, 4(rPC) # a4 <- BBBB (high)
+ srl a1, rINST, 8 # a1 <- AA
+ ins a0, a4, 16, 16 # a0 <- BBBBbbbb
+ daddu a2, rFP, OFF_FP_SHADOWFRAME
+ move a3, rSELF
+ jal MterpConstString # (index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST 3 # load rINST
+ bnez v0, MterpPossibleException # let reference interpreter deal with it.
+ ADVANCE 3 # advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_class: /* 0x1c */
+/* File: mips64/op_const_class.S */
+ /* const/class vAA, Class//BBBB */
+ .extern MterpConstClass
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- BBBB
+ srl a1, rINST, 8 # a1 <- AA
+ daddu a2, rFP, OFF_FP_SHADOWFRAME
+ move a3, rSELF
+ jal MterpConstClass # (index, tgt_reg, shadow_frame, self)
+ PREFETCH_INST 2 # load rINST
+ bnez v0, MterpPossibleException # let reference interpreter deal with it.
+ ADVANCE 2 # advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_monitor_enter: /* 0x1d */
+/* File: mips64/op_monitor_enter.S */
+ /*
+ * Synchronize on an object.
+ */
+ /* monitor-enter vAA */
+ .extern artLockObjectFromCode
+ EXPORT_PC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_U a0, a2 # a0 <- vAA (object)
+ move a1, rSELF # a1 <- self
+ jal artLockObjectFromCode
+ bnezc v0, MterpException
+ FETCH_ADVANCE_INST 1
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_monitor_exit: /* 0x1e */
+/* File: mips64/op_monitor_exit.S */
+ /*
+ * Unlock an object.
+ *
+ * Exceptions that occur when unlocking a monitor need to appear as
+ * if they happened at the following instruction. See the Dalvik
+ * instruction spec.
+ */
+ /* monitor-exit vAA */
+ .extern artUnlockObjectFromCode
+ EXPORT_PC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_U a0, a2 # a0 <- vAA (object)
+ move a1, rSELF # a1 <- self
+ jal artUnlockObjectFromCode # v0 <- success for unlock(self, obj)
+ bnezc v0, MterpException
+ FETCH_ADVANCE_INST 1 # before throw: advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_check_cast: /* 0x1f */
+/* File: mips64/op_check_cast.S */
+ /*
+ * Check to see if a cast from one class to another is allowed.
+ */
+ /* check-cast vAA, class//BBBB */
+ .extern MterpCheckCast
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- BBBB
+ srl a1, rINST, 8 # a1 <- AA
+ dlsa a1, a1, rFP, 2 # a1 <- &object
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ jal MterpCheckCast # (index, &obj, method, self)
+ PREFETCH_INST 2
+ bnez v0, MterpPossibleException
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_instance_of: /* 0x20 */
+/* File: mips64/op_instance_of.S */
+ /*
+ * Check to see if an object reference is an instance of a class.
+ *
+ * Most common situation is a non-null object, being compared against
+ * an already-resolved class.
+ */
+ /* instance-of vA, vB, class//CCCC */
+ .extern MterpInstanceOf
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- CCCC
+ srl a1, rINST, 12 # a1 <- B
+ dlsa a1, a1, rFP, 2 # a1 <- &object
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- method
+ move a3, rSELF # a3 <- self
+ jal MterpInstanceOf # (index, &obj, method, self)
+ ld a1, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a1, MterpException
+ ADVANCE 2 # advance rPC
+ SET_VREG v0, a2 # vA <- v0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_array_length: /* 0x21 */
+/* File: mips64/op_array_length.S */
+ /*
+ * Return the length of an array.
+ */
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a0, a1 # a0 <- vB (object ref)
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a0, common_errNullObject # yup, fail
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- array length
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a3, a2 # vB <- length
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_new_instance: /* 0x22 */
+/* File: mips64/op_new_instance.S */
+ /*
+ * Create a new instance of a class.
+ */
+ /* new-instance vAA, class//BBBB */
+ .extern MterpNewInstance
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rSELF
+ move a2, rINST
+ jal MterpNewInstance # (shadow_frame, self, inst_data)
+ beqzc v0, MterpPossibleException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_new_array: /* 0x23 */
+/* File: mips64/op_new_array.S */
+ /*
+ * Allocate an array of objects, specified with the array class
+ * and a count.
+ *
+ * The verifier guarantees that this is an array class, so we don't
+ * check for it here.
+ */
+ /* new-array vA, vB, class//CCCC */
+ .extern MterpNewArray
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ jal MterpNewArray
+ beqzc v0, MterpPossibleException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_filled_new_array: /* 0x24 */
+/* File: mips64/op_filled_new_array.S */
+ /*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class//CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, type//BBBB */
+ .extern MterpFilledNewArray
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rSELF
+ jal MterpFilledNewArray
+ beqzc v0, MterpPossibleException
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_filled_new_array_range: /* 0x25 */
+/* File: mips64/op_filled_new_array_range.S */
+/* File: mips64/op_filled_new_array.S */
+ /*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class//CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, type//BBBB */
+ .extern MterpFilledNewArrayRange
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rSELF
+ jal MterpFilledNewArrayRange
+ beqzc v0, MterpPossibleException
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_fill_array_data: /* 0x26 */
+/* File: mips64/op_fill_array_data.S */
+ /* fill-array-data vAA, +BBBBBBBB */
+ .extern MterpFillArrayData
+ EXPORT_PC
+ lh a1, 2(rPC) # a1 <- bbbb (lo)
+ lh a0, 4(rPC) # a0 <- BBBB (hi)
+ srl a3, rINST, 8 # a3 <- AA
+ ins a1, a0, 16, 16 # a1 <- BBBBbbbb
+ GET_VREG_U a0, a3 # a0 <- vAA (array object)
+ dlsa a1, a1, rPC, 1 # a1 <- PC + BBBBbbbb*2 (array data off.)
+ jal MterpFillArrayData # (obj, payload)
+ beqzc v0, MterpPossibleException # exception?
+ FETCH_ADVANCE_INST 3 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_throw: /* 0x27 */
+/* File: mips64/op_throw.S */
+ /*
+ * Throw an exception object in the current thread.
+ */
+ /* throw vAA */
+ EXPORT_PC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG_U a0, a2 # a0 <- vAA (exception object)
+ beqzc a0, common_errNullObject
+ sd a0, THREAD_EXCEPTION_OFFSET(rSELF) # thread->exception <- obj
+ b MterpException
+
+/* ------------------------------ */
+ .balign 128
+.L_op_goto: /* 0x28 */
+/* File: mips64/op_goto.S */
+ /*
+ * Unconditional branch, 8-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto +AA */
+ srl a0, rINST, 8
+ seb a0, a0 # a0 <- sign-extended AA
+ dlsa rPC, a0, rPC, 1 # rPC <- rPC + AA * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a0, 1f # AA * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+1:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a0, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_goto_16: /* 0x29 */
+/* File: mips64/op_goto_16.S */
+ /*
+ * Unconditional branch, 16-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto/16 +AAAA */
+ lh a0, 2(rPC) # a0 <- sign-extended AAAA
+ dlsa rPC, a0, rPC, 1 # rPC <- rPC + AAAA * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a0, 1f # AA * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+1:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a0, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_goto_32: /* 0x2a */
+/* File: mips64/op_goto_32.S */
+ /*
+ * Unconditional branch, 32-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ *
+ * Unlike most opcodes, this one is allowed to branch to itself, so
+ * our "backward branch" test must be "<=0" instead of "<0".
+ */
+ /* goto/32 +AAAAAAAA */
+ lh a0, 2(rPC) # a0 <- aaaa (low)
+ lh a1, 4(rPC) # a1 <- AAAA (high)
+ ins a0, a1, 16, 16 # a0 = sign-extended AAAAaaaa
+ dlsa rPC, a0, rPC, 1 # rPC <- rPC + AAAAAAAA * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgtz a0, 1f # AA * 2 > 0 => no suspend check
+ REFRESH_IBASE
+1:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ blez a0, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_packed_switch: /* 0x2b */
+/* File: mips64/op_packed_switch.S */
+ /*
+ * Handle a packed-switch or sparse-switch instruction. In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+ /* op vAA, +BBBBBBBB */
+ .extern MterpDoPackedSwitch
+ lh a0, 2(rPC) # a0 <- bbbb (lo)
+ lh a1, 4(rPC) # a1 <- BBBB (hi)
+ srl a3, rINST, 8 # a3 <- AA
+ ins a0, a1, 16, 16 # a0 <- BBBBbbbb
+ GET_VREG a1, a3 # a1 <- vAA
+ dlsa a0, a0, rPC, 1 # a0 <- PC + BBBBbbbb*2
+ jal MterpDoPackedSwitch # v0 <- code-unit branch offset
+ dlsa rPC, v0, rPC, 1 # rPC <- rPC + offset * 2
+ FETCH_INST # load rINST
+#if MTERP_SUSPEND
+ bgtz v0, 1f # offset * 2 > 0 => no suspend check
+ REFRESH_IBASE
+1:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ blez v0, MterpCheckSuspendAndContinue
+#endif
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sparse_switch: /* 0x2c */
+/* File: mips64/op_sparse_switch.S */
+/* File: mips64/op_packed_switch.S */
+ /*
+ * Handle a packed-switch or sparse-switch instruction. In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+ /* op vAA, +BBBBBBBB */
+ .extern MterpDoSparseSwitch
+ lh a0, 2(rPC) # a0 <- bbbb (lo)
+ lh a1, 4(rPC) # a1 <- BBBB (hi)
+ srl a3, rINST, 8 # a3 <- AA
+ ins a0, a1, 16, 16 # a0 <- BBBBbbbb
+ GET_VREG a1, a3 # a1 <- vAA
+ dlsa a0, a0, rPC, 1 # a0 <- PC + BBBBbbbb*2
+ jal MterpDoSparseSwitch # v0 <- code-unit branch offset
+ dlsa rPC, v0, rPC, 1 # rPC <- rPC + offset * 2
+ FETCH_INST # load rINST
+#if MTERP_SUSPEND
+ bgtz v0, 1f # offset * 2 > 0 => no suspend check
+ REFRESH_IBASE
+1:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ blez v0, MterpCheckSuspendAndContinue
+#endif
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpl_float: /* 0x2d */
+/* File: mips64/op_cmpl_float.S */
+/* File: mips64/fcmp.S */
+ /*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * For: cmpl-float, cmpg-float
+ */
+ /* op vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f0, a2 # f0 <- vBB
+ GET_VREG_FLOAT f1, a3 # f1 <- vCC
+ cmp.eq.s f2, f0, f1
+ li a0, 0
+ bc1nez f2, 1f # done if vBB == vCC (ordered)
+ .if 0
+ cmp.lt.s f2, f0, f1
+ li a0, -1
+ bc1nez f2, 1f # done if vBB < vCC (ordered)
+ li a0, 1 # vBB > vCC or unordered
+ .else
+ cmp.lt.s f2, f1, f0
+ li a0, 1
+ bc1nez f2, 1f # done if vBB > vCC (ordered)
+ li a0, -1 # vBB < vCC or unordered
+ .endif
+1:
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpg_float: /* 0x2e */
+/* File: mips64/op_cmpg_float.S */
+/* File: mips64/fcmp.S */
+ /*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * For: cmpl-float, cmpg-float
+ */
+ /* op vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f0, a2 # f0 <- vBB
+ GET_VREG_FLOAT f1, a3 # f1 <- vCC
+ cmp.eq.s f2, f0, f1
+ li a0, 0
+ bc1nez f2, 1f # done if vBB == vCC (ordered)
+ .if 1
+ cmp.lt.s f2, f0, f1
+ li a0, -1
+ bc1nez f2, 1f # done if vBB < vCC (ordered)
+ li a0, 1 # vBB > vCC or unordered
+ .else
+ cmp.lt.s f2, f1, f0
+ li a0, 1
+ bc1nez f2, 1f # done if vBB > vCC (ordered)
+ li a0, -1 # vBB < vCC or unordered
+ .endif
+1:
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpl_double: /* 0x2f */
+/* File: mips64/op_cmpl_double.S */
+/* File: mips64/fcmpWide.S */
+ /*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * For: cmpl-double, cmpg-double
+ */
+ /* op vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f0, a2 # f0 <- vBB
+ GET_VREG_DOUBLE f1, a3 # f1 <- vCC
+ cmp.eq.d f2, f0, f1
+ li a0, 0
+ bc1nez f2, 1f # done if vBB == vCC (ordered)
+ .if 0
+ cmp.lt.d f2, f0, f1
+ li a0, -1
+ bc1nez f2, 1f # done if vBB < vCC (ordered)
+ li a0, 1 # vBB > vCC or unordered
+ .else
+ cmp.lt.d f2, f1, f0
+ li a0, 1
+ bc1nez f2, 1f # done if vBB > vCC (ordered)
+ li a0, -1 # vBB < vCC or unordered
+ .endif
+1:
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpg_double: /* 0x30 */
+/* File: mips64/op_cmpg_double.S */
+/* File: mips64/fcmpWide.S */
+ /*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * For: cmpl-double, cmpg-double
+ */
+ /* op vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f0, a2 # f0 <- vBB
+ GET_VREG_DOUBLE f1, a3 # f1 <- vCC
+ cmp.eq.d f2, f0, f1
+ li a0, 0
+ bc1nez f2, 1f # done if vBB == vCC (ordered)
+ .if 1
+ cmp.lt.d f2, f0, f1
+ li a0, -1
+ bc1nez f2, 1f # done if vBB < vCC (ordered)
+ li a0, 1 # vBB > vCC or unordered
+ .else
+ cmp.lt.d f2, f1, f0
+ li a0, 1
+ bc1nez f2, 1f # done if vBB > vCC (ordered)
+ li a0, -1 # vBB < vCC or unordered
+ .endif
+1:
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmp_long: /* 0x31 */
+/* File: mips64/op_cmp_long.S */
+ /* cmp-long vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ slt a2, a0, a1
+ slt a0, a1, a0
+ subu a0, a0, a2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- result
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_eq: /* 0x32 */
+/* File: mips64/op_if_eq.S */
+/* File: mips64/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-le" you would use "le".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ lh a4, 2(rPC) # a4 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+
+ beqc a0, a1, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + CCCC * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # CCCC * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_ne: /* 0x33 */
+/* File: mips64/op_if_ne.S */
+/* File: mips64/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-le" you would use "le".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ lh a4, 2(rPC) # a4 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+
+ bnec a0, a1, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + CCCC * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # CCCC * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_lt: /* 0x34 */
+/* File: mips64/op_if_lt.S */
+/* File: mips64/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-le" you would use "le".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ lh a4, 2(rPC) # a4 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+
+ bltc a0, a1, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + CCCC * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # CCCC * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_ge: /* 0x35 */
+/* File: mips64/op_if_ge.S */
+/* File: mips64/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-le" you would use "le".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ lh a4, 2(rPC) # a4 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+
+ bgec a0, a1, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + CCCC * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # CCCC * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_gt: /* 0x36 */
+/* File: mips64/op_if_gt.S */
+/* File: mips64/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-le" you would use "le".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ lh a4, 2(rPC) # a4 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+
+ bgtc a0, a1, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + CCCC * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # CCCC * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_le: /* 0x37 */
+/* File: mips64/op_if_le.S */
+/* File: mips64/bincmp.S */
+ /*
+ * Generic two-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-le" you would use "le".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ lh a4, 2(rPC) # a4 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+
+ blec a0, a1, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + CCCC * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # CCCC * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_eqz: /* 0x38 */
+/* File: mips64/op_if_eqz.S */
+/* File: mips64/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-lez" you would use "le".
+ *
+ * For: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ lh a4, 2(rPC) # a4 <- sign-extended BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a2 # a0 <- vAA
+
+ beqzc a0, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + BBBB * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # BBBB * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_nez: /* 0x39 */
+/* File: mips64/op_if_nez.S */
+/* File: mips64/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-lez" you would use "le".
+ *
+ * For: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ lh a4, 2(rPC) # a4 <- sign-extended BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a2 # a0 <- vAA
+
+ bnezc a0, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + BBBB * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # BBBB * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_ltz: /* 0x3a */
+/* File: mips64/op_if_ltz.S */
+/* File: mips64/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-lez" you would use "le".
+ *
+ * For: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ lh a4, 2(rPC) # a4 <- sign-extended BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a2 # a0 <- vAA
+
+ bltzc a0, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + BBBB * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # BBBB * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_gez: /* 0x3b */
+/* File: mips64/op_if_gez.S */
+/* File: mips64/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-lez" you would use "le".
+ *
+ * For: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ lh a4, 2(rPC) # a4 <- sign-extended BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a2 # a0 <- vAA
+
+ bgezc a0, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + BBBB * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # BBBB * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_gtz: /* 0x3c */
+/* File: mips64/op_if_gtz.S */
+/* File: mips64/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-lez" you would use "le".
+ *
+ * For: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ lh a4, 2(rPC) # a4 <- sign-extended BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a2 # a0 <- vAA
+
+ bgtzc a0, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + BBBB * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # BBBB * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_lez: /* 0x3d */
+/* File: mips64/op_if_lez.S */
+/* File: mips64/zcmp.S */
+ /*
+ * Generic one-operand compare-and-branch operation. Provide a "condition"
+ * fragment that specifies the comparison to perform, e.g. for
+ * "if-lez" you would use "le".
+ *
+ * For: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ lh a4, 2(rPC) # a4 <- sign-extended BBBB
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a2 # a0 <- vAA
+
+ blezc a0, 1f
+ li a4, 2 # offset if branch not taken
+1:
+
+ dlsa rPC, a4, rPC, 1 # rPC <- rPC + BBBB * 2
+ FETCH_INST # load rINST
+
+#if MTERP_SUSPEND
+ bgez a4, 2f # BBBB * 2 >= 0 => no suspend check
+ REFRESH_IBASE
+2:
+#else
+ lw ra, THREAD_FLAGS_OFFSET(rSELF) # Preload flags for MterpCheckSuspendAndContinue
+ bltz a4, MterpCheckSuspendAndContinue
+#endif
+
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_3e: /* 0x3e */
+/* File: mips64/op_unused_3e.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_3f: /* 0x3f */
+/* File: mips64/op_unused_3f.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_40: /* 0x40 */
+/* File: mips64/op_unused_40.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_41: /* 0x41 */
+/* File: mips64/op_unused_41.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_42: /* 0x42 */
+/* File: mips64/op_unused_42.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_43: /* 0x43 */
+/* File: mips64/op_unused_43.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget: /* 0x44 */
+/* File: mips64/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 2
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 2 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ lw a2, MIRROR_INT_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a2, a4 # vAA <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_wide: /* 0x45 */
+/* File: mips64/op_aget_wide.S */
+ /*
+ * Array get, 64 bits. vAA <- vBB[vCC].
+ *
+ */
+ /* aget-wide vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ dlsa a0, a1, a0, 3 # a0 <- arrayObj + index*width
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ lw a2, MIRROR_WIDE_ARRAY_DATA_OFFSET(a0)
+ lw a3, (MIRROR_WIDE_ARRAY_DATA_OFFSET+4)(a0)
+ dinsu a2, a3, 32, 32 # a2 <- vBB[vCC]
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a2, a4 # vAA <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_object: /* 0x46 */
+/* File: mips64/op_aget_object.S */
+ /*
+ * Array object get. vAA <- vBB[vCC].
+ *
+ * for: aget-object
+ */
+ /* op vAA, vBB, vCC */
+ .extern artAGetObjectFromMterp
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ EXPORT_PC
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ jal artAGetObjectFromMterp # (array, index)
+ ld a1, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a4, rINST, 8 # a4 <- AA
+ PREFETCH_INST 2
+ bnez a1, MterpException
+ SET_VREG_OBJECT v0, a4 # vAA <- v0
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_boolean: /* 0x47 */
+/* File: mips64/op_aget_boolean.S */
+/* File: mips64/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 0
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 0 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ lbu a2, MIRROR_BOOLEAN_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a2, a4 # vAA <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_byte: /* 0x48 */
+/* File: mips64/op_aget_byte.S */
+/* File: mips64/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 0
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 0 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ lb a2, MIRROR_BYTE_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a2, a4 # vAA <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_char: /* 0x49 */
+/* File: mips64/op_aget_char.S */
+/* File: mips64/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 1
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 1 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ lhu a2, MIRROR_CHAR_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a2, a4 # vAA <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_short: /* 0x4a */
+/* File: mips64/op_aget_short.S */
+/* File: mips64/op_aget.S */
+ /*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short
+ *
+ * NOTE: assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 1
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 1 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ lh a2, MIRROR_SHORT_ARRAY_DATA_OFFSET(a0) # a2 <- vBB[vCC]
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a2, a4 # vAA <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput: /* 0x4b */
+/* File: mips64/op_aput.S */
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 2
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 2 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_VREG a2, a4 # a2 <- vAA
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ sw a2, MIRROR_INT_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_wide: /* 0x4c */
+/* File: mips64/op_aput_wide.S */
+ /*
+ * Array put, 64 bits. vBB[vCC] <- vAA.
+ *
+ */
+ /* aput-wide vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ dlsa a0, a1, a0, 3 # a0 <- arrayObj + index*width
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ GET_VREG_WIDE a2, a4 # a2 <- vAA
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ sw a2, MIRROR_WIDE_ARRAY_DATA_OFFSET(a0)
+ dsrl32 a2, a2, 0
+ sw a2, (MIRROR_WIDE_ARRAY_DATA_OFFSET+4)(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_object: /* 0x4d */
+/* File: mips64/op_aput_object.S */
+ /*
+ * Store an object into an array. vBB[vCC] <- vAA.
+ */
+ /* op vAA, vBB, vCC */
+ .extern MterpAputObject
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ jal MterpAputObject
+ beqzc v0, MterpPossibleException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_boolean: /* 0x4e */
+/* File: mips64/op_aput_boolean.S */
+/* File: mips64/op_aput.S */
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 0
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 0 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_VREG a2, a4 # a2 <- vAA
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ sb a2, MIRROR_BOOLEAN_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_byte: /* 0x4f */
+/* File: mips64/op_aput_byte.S */
+/* File: mips64/op_aput.S */
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 0
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 0 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_VREG a2, a4 # a2 <- vAA
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ sb a2, MIRROR_BYTE_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_char: /* 0x50 */
+/* File: mips64/op_aput_char.S */
+/* File: mips64/op_aput.S */
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 1
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 1 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_VREG a2, a4 # a2 <- vAA
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ sh a2, MIRROR_CHAR_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_short: /* 0x51 */
+/* File: mips64/op_aput_short.S */
+/* File: mips64/op_aput.S */
+ /*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+ *
+ * NOTE: this assumes data offset for arrays is the same for all non-wide types.
+ * If this changes, specialize.
+ */
+ /* op vAA, vBB, vCC */
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ srl a4, rINST, 8 # a4 <- AA
+ GET_VREG_U a0, a2 # a0 <- vBB (array object)
+ GET_VREG a1, a3 # a1 <- vCC (requested index)
+ beqz a0, common_errNullObject # bail if null array object
+ lw a3, MIRROR_ARRAY_LENGTH_OFFSET(a0) # a3 <- arrayObj->length
+ .if 1
+ # [d]lsa does not support shift count of 0.
+ dlsa a0, a1, a0, 1 # a0 <- arrayObj + index*width
+ .else
+ daddu a0, a1, a0 # a0 <- arrayObj + index*width
+ .endif
+ bgeu a1, a3, common_errArrayIndex # unsigned compare: index >= length, bail
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_VREG a2, a4 # a2 <- vAA
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ sh a2, MIRROR_SHORT_ARRAY_DATA_OFFSET(a0) # vBB[vCC] <- a2
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget: /* 0x52 */
+/* File: mips64/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ .extern artGet32InstanceFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ jal artGet32InstanceFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[A] <- v0
+ .else
+ SET_VREG v0, a2 # fp[A] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_wide: /* 0x53 */
+/* File: mips64/op_iget_wide.S */
+ /*
+ * 64-bit instance field get.
+ *
+ * for: iget-wide
+ */
+ .extern artGet64InstanceFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ jal artGet64InstanceFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ SET_VREG_WIDE v0, a2 # fp[A] <- v0
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_object: /* 0x54 */
+/* File: mips64/op_iget_object.S */
+/* File: mips64/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ .extern artGetObjInstanceFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ jal artGetObjInstanceFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ .if 1
+ SET_VREG_OBJECT v0, a2 # fp[A] <- v0
+ .else
+ SET_VREG v0, a2 # fp[A] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_boolean: /* 0x55 */
+/* File: mips64/op_iget_boolean.S */
+/* File: mips64/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ .extern artGetBooleanInstanceFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ jal artGetBooleanInstanceFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[A] <- v0
+ .else
+ SET_VREG v0, a2 # fp[A] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_byte: /* 0x56 */
+/* File: mips64/op_iget_byte.S */
+/* File: mips64/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ .extern artGetByteInstanceFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ jal artGetByteInstanceFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[A] <- v0
+ .else
+ SET_VREG v0, a2 # fp[A] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_char: /* 0x57 */
+/* File: mips64/op_iget_char.S */
+/* File: mips64/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ .extern artGetCharInstanceFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ jal artGetCharInstanceFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[A] <- v0
+ .else
+ SET_VREG v0, a2 # fp[A] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_short: /* 0x58 */
+/* File: mips64/op_iget_short.S */
+/* File: mips64/op_iget.S */
+ /*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+ */
+ .extern artGetShortInstanceFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer
+ move a3, rSELF # a3 <- self
+ jal artGetShortInstanceFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[A] <- v0
+ .else
+ SET_VREG v0, a2 # fp[A] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput: /* 0x59 */
+/* File: mips64/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field//CCCC */
+ .extern artSet32InstanceFromMterp
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ GET_VREG a2, a2 # a2 <- fp[A]
+ ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST 2
+ jal artSet32InstanceFromMterp
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_wide: /* 0x5a */
+/* File: mips64/op_iput_wide.S */
+ /* iput-wide vA, vB, field//CCCC */
+ .extern artSet64InstanceFromMterp
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ dlsa a2, a2, rFP, 2 # a2 <- &fp[A]
+ ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST 2
+ jal artSet64InstanceFromMterp
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_object: /* 0x5b */
+/* File: mips64/op_iput_object.S */
+ .extern MterpIputObject
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ jal MterpIputObject
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_boolean: /* 0x5c */
+/* File: mips64/op_iput_boolean.S */
+/* File: mips64/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field//CCCC */
+ .extern artSet8InstanceFromMterp
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ GET_VREG a2, a2 # a2 <- fp[A]
+ ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST 2
+ jal artSet8InstanceFromMterp
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_byte: /* 0x5d */
+/* File: mips64/op_iput_byte.S */
+/* File: mips64/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field//CCCC */
+ .extern artSet8InstanceFromMterp
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ GET_VREG a2, a2 # a2 <- fp[A]
+ ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST 2
+ jal artSet8InstanceFromMterp
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_char: /* 0x5e */
+/* File: mips64/op_iput_char.S */
+/* File: mips64/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field//CCCC */
+ .extern artSet16InstanceFromMterp
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ GET_VREG a2, a2 # a2 <- fp[A]
+ ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST 2
+ jal artSet16InstanceFromMterp
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_short: /* 0x5f */
+/* File: mips64/op_iput_short.S */
+/* File: mips64/op_iput.S */
+ /*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field//CCCC */
+ .extern artSet16InstanceFromMterp
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref CCCC
+ srl a1, rINST, 12 # a1 <- B
+ GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ GET_VREG a2, a2 # a2 <- fp[A]
+ ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer
+ PREFETCH_INST 2
+ jal artSet16InstanceFromMterp
+ bnez v0, MterpPossibleException # bail out
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget: /* 0x60 */
+/* File: mips64/op_sget.S */
+ /*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artGet32StaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ move a2, rSELF
+ jal artGet32StaticFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a2, rINST, 8 # a2 <- AA
+
+ PREFETCH_INST 2
+ bnez a3, MterpException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[AA] <- v0
+ .else
+ SET_VREG v0, a2 # fp[AA] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_wide: /* 0x61 */
+/* File: mips64/op_sget_wide.S */
+ /*
+ * SGET_WIDE handler wrapper.
+ *
+ */
+ /* sget-wide vAA, field//BBBB */
+ .extern artGet64StaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ move a2, rSELF
+ jal artGet64StaticFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a4, rINST, 8 # a4 <- AA
+ bnez a3, MterpException # bail out
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG_WIDE v0, a4
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_object: /* 0x62 */
+/* File: mips64/op_sget_object.S */
+/* File: mips64/op_sget.S */
+ /*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artGetObjStaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ move a2, rSELF
+ jal artGetObjStaticFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a2, rINST, 8 # a2 <- AA
+
+ PREFETCH_INST 2
+ bnez a3, MterpException # bail out
+ .if 1
+ SET_VREG_OBJECT v0, a2 # fp[AA] <- v0
+ .else
+ SET_VREG v0, a2 # fp[AA] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_boolean: /* 0x63 */
+/* File: mips64/op_sget_boolean.S */
+/* File: mips64/op_sget.S */
+ /*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artGetBooleanStaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ move a2, rSELF
+ jal artGetBooleanStaticFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a2, rINST, 8 # a2 <- AA
+ and v0, v0, 0xff
+ PREFETCH_INST 2
+ bnez a3, MterpException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[AA] <- v0
+ .else
+ SET_VREG v0, a2 # fp[AA] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_byte: /* 0x64 */
+/* File: mips64/op_sget_byte.S */
+/* File: mips64/op_sget.S */
+ /*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artGetByteStaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ move a2, rSELF
+ jal artGetByteStaticFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a2, rINST, 8 # a2 <- AA
+ seb v0, v0
+ PREFETCH_INST 2
+ bnez a3, MterpException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[AA] <- v0
+ .else
+ SET_VREG v0, a2 # fp[AA] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_char: /* 0x65 */
+/* File: mips64/op_sget_char.S */
+/* File: mips64/op_sget.S */
+ /*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artGetCharStaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ move a2, rSELF
+ jal artGetCharStaticFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a2, rINST, 8 # a2 <- AA
+ and v0, v0, 0xffff
+ PREFETCH_INST 2
+ bnez a3, MterpException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[AA] <- v0
+ .else
+ SET_VREG v0, a2 # fp[AA] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_short: /* 0x66 */
+/* File: mips64/op_sget_short.S */
+/* File: mips64/op_sget.S */
+ /*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artGetShortStaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ move a2, rSELF
+ jal artGetShortStaticFromCode
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ srl a2, rINST, 8 # a2 <- AA
+ seh v0, v0
+ PREFETCH_INST 2
+ bnez a3, MterpException # bail out
+ .if 0
+ SET_VREG_OBJECT v0, a2 # fp[AA] <- v0
+ .else
+ SET_VREG v0, a2 # fp[AA] <- v0
+ .endif
+ ADVANCE 2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput: /* 0x67 */
+/* File: mips64/op_sput.S */
+ /*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artSet32StaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ srl a3, rINST, 8 # a3 <- AA
+ GET_VREG a1, a3 # a1 <- fp[AA]
+ ld a2, OFF_FP_METHOD(rFP)
+ move a3, rSELF
+ PREFETCH_INST 2 # Get next inst, but don't advance rPC
+ jal artSet32StaticFromCode
+ bnezc v0, MterpException # 0 on success
+ ADVANCE 2 # Past exception point - now advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_wide: /* 0x68 */
+/* File: mips64/op_sput_wide.S */
+ /*
+ * SPUT_WIDE handler wrapper.
+ *
+ */
+ /* sput-wide vAA, field//BBBB */
+ .extern artSet64IndirectStaticFromMterp
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ ld a1, OFF_FP_METHOD(rFP)
+ srl a2, rINST, 8 # a2 <- AA
+ dlsa a2, a2, rFP, 2
+ move a3, rSELF
+ PREFETCH_INST 2 # Get next inst, but don't advance rPC
+ jal artSet64IndirectStaticFromMterp
+ bnezc v0, MterpException # 0 on success, -1 on failure
+ ADVANCE 2 # Past exception point - now advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_object: /* 0x69 */
+/* File: mips64/op_sput_object.S */
+ .extern MterpSputObject
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ move a3, rSELF
+ jal MterpSputObject
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_boolean: /* 0x6a */
+/* File: mips64/op_sput_boolean.S */
+/* File: mips64/op_sput.S */
+ /*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artSet8StaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ srl a3, rINST, 8 # a3 <- AA
+ GET_VREG a1, a3 # a1 <- fp[AA]
+ ld a2, OFF_FP_METHOD(rFP)
+ move a3, rSELF
+ PREFETCH_INST 2 # Get next inst, but don't advance rPC
+ jal artSet8StaticFromCode
+ bnezc v0, MterpException # 0 on success
+ ADVANCE 2 # Past exception point - now advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_byte: /* 0x6b */
+/* File: mips64/op_sput_byte.S */
+/* File: mips64/op_sput.S */
+ /*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artSet8StaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ srl a3, rINST, 8 # a3 <- AA
+ GET_VREG a1, a3 # a1 <- fp[AA]
+ ld a2, OFF_FP_METHOD(rFP)
+ move a3, rSELF
+ PREFETCH_INST 2 # Get next inst, but don't advance rPC
+ jal artSet8StaticFromCode
+ bnezc v0, MterpException # 0 on success
+ ADVANCE 2 # Past exception point - now advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_char: /* 0x6c */
+/* File: mips64/op_sput_char.S */
+/* File: mips64/op_sput.S */
+ /*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artSet16StaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ srl a3, rINST, 8 # a3 <- AA
+ GET_VREG a1, a3 # a1 <- fp[AA]
+ ld a2, OFF_FP_METHOD(rFP)
+ move a3, rSELF
+ PREFETCH_INST 2 # Get next inst, but don't advance rPC
+ jal artSet16StaticFromCode
+ bnezc v0, MterpException # 0 on success
+ ADVANCE 2 # Past exception point - now advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_short: /* 0x6d */
+/* File: mips64/op_sput_short.S */
+/* File: mips64/op_sput.S */
+ /*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field//BBBB */
+ .extern artSet16StaticFromCode
+ EXPORT_PC
+ lhu a0, 2(rPC) # a0 <- field ref BBBB
+ srl a3, rINST, 8 # a3 <- AA
+ GET_VREG a1, a3 # a1 <- fp[AA]
+ ld a2, OFF_FP_METHOD(rFP)
+ move a3, rSELF
+ PREFETCH_INST 2 # Get next inst, but don't advance rPC
+ jal artSet16StaticFromCode
+ bnezc v0, MterpException # 0 on success
+ ADVANCE 2 # Past exception point - now advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual: /* 0x6e */
+/* File: mips64/op_invoke_virtual.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeVirtual
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeVirtual
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+ /*
+ * Handle a virtual method call.
+ *
+ * for: invoke-virtual, invoke-virtual/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_super: /* 0x6f */
+/* File: mips64/op_invoke_super.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeSuper
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeSuper
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+ /*
+ * Handle a "super" method call.
+ *
+ * for: invoke-super, invoke-super/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_direct: /* 0x70 */
+/* File: mips64/op_invoke_direct.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeDirect
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeDirect
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_static: /* 0x71 */
+/* File: mips64/op_invoke_static.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeStatic
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeStatic
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_interface: /* 0x72 */
+/* File: mips64/op_invoke_interface.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeInterface
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeInterface
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+ /*
+ * Handle an interface method call.
+ *
+ * for: invoke-interface, invoke-interface/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_void_no_barrier: /* 0x73 */
+/* File: mips64/op_return_void_no_barrier.S */
+ .extern MterpSuspendCheck
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, 1f
+ jal MterpSuspendCheck # (self)
+1:
+ li a0, 0
+ b MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual_range: /* 0x74 */
+/* File: mips64/op_invoke_virtual_range.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeVirtualRange
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeVirtualRange
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_super_range: /* 0x75 */
+/* File: mips64/op_invoke_super_range.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeSuperRange
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeSuperRange
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_direct_range: /* 0x76 */
+/* File: mips64/op_invoke_direct_range.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeDirectRange
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeDirectRange
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_static_range: /* 0x77 */
+/* File: mips64/op_invoke_static_range.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeStaticRange
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeStaticRange
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_interface_range: /* 0x78 */
+/* File: mips64/op_invoke_interface_range.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeInterfaceRange
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeInterfaceRange
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_79: /* 0x79 */
+/* File: mips64/op_unused_79.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_7a: /* 0x7a */
+/* File: mips64/op_unused_7a.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_int: /* 0x7b */
+/* File: mips64/op_neg_int.S */
+/* File: mips64/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "a0 = op a0".
+ *
+ * for: int-to-byte, int-to-char, int-to-short,
+ * not-int, neg-int
+ */
+ /* unop vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ ext a2, rINST, 8, 4 # a2 <- A
+ # optional op
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ subu a0, zero, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_not_int: /* 0x7c */
+/* File: mips64/op_not_int.S */
+/* File: mips64/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "a0 = op a0".
+ *
+ * for: int-to-byte, int-to-char, int-to-short,
+ * not-int, neg-int
+ */
+ /* unop vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ ext a2, rINST, 8, 4 # a2 <- A
+ # optional op
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ nor a0, zero, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_long: /* 0x7d */
+/* File: mips64/op_neg_long.S */
+/* File: mips64/unopWide.S */
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "a0 = op a0".
+ *
+ * For: not-long, neg-long
+ */
+ /* unop vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a3 # a0 <- vB
+ ext a2, rINST, 8, 4 # a2 <- A
+ # optional op
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ dsubu a0, zero, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_not_long: /* 0x7e */
+/* File: mips64/op_not_long.S */
+/* File: mips64/unopWide.S */
+ /*
+ * Generic 64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "a0 = op a0".
+ *
+ * For: not-long, neg-long
+ */
+ /* unop vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a3 # a0 <- vB
+ ext a2, rINST, 8, 4 # a2 <- A
+ # optional op
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ nor a0, zero, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_float: /* 0x7f */
+/* File: mips64/op_neg_float.S */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_FLOAT f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ neg.s f0, f0
+/* File: mips64/fcvtFooter.S */
+ /*
+ * Stores a specified register containing the result of conversion
+ * from or to a floating-point type and jumps to the next instruction.
+ *
+ * Expects a1 to contain the destination Dalvik register number.
+ * a1 is set up by fcvtHeader.S.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ *
+ * Note that this file can't be included after a break in other files
+ * and in those files its contents appear as a copy.
+ * See: float-to-int, float-to-long, double-to-int, double-to-long.
+ */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_double: /* 0x80 */
+/* File: mips64/op_neg_double.S */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_DOUBLE f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ neg.d f0, f0
+/* File: mips64/fcvtFooter.S */
+ /*
+ * Stores a specified register containing the result of conversion
+ * from or to a floating-point type and jumps to the next instruction.
+ *
+ * Expects a1 to contain the destination Dalvik register number.
+ * a1 is set up by fcvtHeader.S.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ *
+ * Note that this file can't be included after a break in other files
+ * and in those files its contents appear as a copy.
+ * See: float-to-int, float-to-long, double-to-int, double-to-long.
+ */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_long: /* 0x81 */
+/* File: mips64/op_int_to_long.S */
+ /* int-to-long vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB (sign-extended to 64 bits)
+ ext a2, rINST, 8, 4 # a2 <- A
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- vB
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_float: /* 0x82 */
+/* File: mips64/op_int_to_float.S */
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_FLOAT f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ cvt.s.w f0, f0
+/* File: mips64/fcvtFooter.S */
+ /*
+ * Stores a specified register containing the result of conversion
+ * from or to a floating-point type and jumps to the next instruction.
+ *
+ * Expects a1 to contain the destination Dalvik register number.
+ * a1 is set up by fcvtHeader.S.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ *
+ * Note that this file can't be included after a break in other files
+ * and in those files its contents appear as a copy.
+ * See: float-to-int, float-to-long, double-to-int, double-to-long.
+ */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_double: /* 0x83 */
+/* File: mips64/op_int_to_double.S */
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_FLOAT f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ cvt.d.w f0, f0
+/* File: mips64/fcvtFooter.S */
+ /*
+ * Stores a specified register containing the result of conversion
+ * from or to a floating-point type and jumps to the next instruction.
+ *
+ * Expects a1 to contain the destination Dalvik register number.
+ * a1 is set up by fcvtHeader.S.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ *
+ * Note that this file can't be included after a break in other files
+ * and in those files its contents appear as a copy.
+ * See: float-to-int, float-to-long, double-to-int, double-to-long.
+ */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_long_to_int: /* 0x84 */
+/* File: mips64/op_long_to_int.S */
+/* we ignore the high word, making this equivalent to a 32-bit reg move */
+/* File: mips64/op_move.S */
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_VREG a0, a3 # a0 <- vB
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ .if 0
+ SET_VREG_OBJECT a0, a2 # vA <- vB
+ .else
+ SET_VREG a0, a2 # vA <- vB
+ .endif
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_long_to_float: /* 0x85 */
+/* File: mips64/op_long_to_float.S */
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_DOUBLE f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ cvt.s.l f0, f0
+/* File: mips64/fcvtFooter.S */
+ /*
+ * Stores a specified register containing the result of conversion
+ * from or to a floating-point type and jumps to the next instruction.
+ *
+ * Expects a1 to contain the destination Dalvik register number.
+ * a1 is set up by fcvtHeader.S.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ *
+ * Note that this file can't be included after a break in other files
+ * and in those files its contents appear as a copy.
+ * See: float-to-int, float-to-long, double-to-int, double-to-long.
+ */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_long_to_double: /* 0x86 */
+/* File: mips64/op_long_to_double.S */
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_DOUBLE f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ cvt.d.l f0, f0
+/* File: mips64/fcvtFooter.S */
+ /*
+ * Stores a specified register containing the result of conversion
+ * from or to a floating-point type and jumps to the next instruction.
+ *
+ * Expects a1 to contain the destination Dalvik register number.
+ * a1 is set up by fcvtHeader.S.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ *
+ * Note that this file can't be included after a break in other files
+ * and in those files its contents appear as a copy.
+ * See: float-to-int, float-to-long, double-to-int, double-to-long.
+ */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_float_to_int: /* 0x87 */
+/* File: mips64/op_float_to_int.S */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_FLOAT f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ /*
+ * TODO: simplify this when the MIPS64R6 emulator
+ * supports NAN2008=1.
+ */
+ li t0, INT_MIN_AS_FLOAT
+ mtc1 t0, f1
+ cmp.le.s f1, f1, f0
+ bc1nez f1, .Lop_float_to_int_trunc
+ cmp.eq.s f1, f0, f0
+ li t0, INT_MIN
+ mfc1 t1, f1
+ and t0, t0, t1
+ b .Lop_float_to_int_done
+
+/* ------------------------------ */
+ .balign 128
+.L_op_float_to_long: /* 0x88 */
+/* File: mips64/op_float_to_long.S */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_FLOAT f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ /*
+ * TODO: simplify this when the MIPS64R6 emulator
+ * supports NAN2008=1.
+ */
+ li t0, LONG_MIN_AS_FLOAT
+ mtc1 t0, f1
+ cmp.le.s f1, f1, f0
+ bc1nez f1, .Lop_float_to_long_trunc
+ cmp.eq.s f1, f0, f0
+ dli t0, LONG_MIN
+ mfc1 t1, f1
+ and t0, t0, t1
+ b .Lop_float_to_long_done
+
+/* ------------------------------ */
+ .balign 128
+.L_op_float_to_double: /* 0x89 */
+/* File: mips64/op_float_to_double.S */
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_FLOAT f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ cvt.d.s f0, f0
+/* File: mips64/fcvtFooter.S */
+ /*
+ * Stores a specified register containing the result of conversion
+ * from or to a floating-point type and jumps to the next instruction.
+ *
+ * Expects a1 to contain the destination Dalvik register number.
+ * a1 is set up by fcvtHeader.S.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ *
+ * Note that this file can't be included after a break in other files
+ * and in those files its contents appear as a copy.
+ * See: float-to-int, float-to-long, double-to-int, double-to-long.
+ */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_double_to_int: /* 0x8a */
+/* File: mips64/op_double_to_int.S */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_DOUBLE f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ /*
+ * TODO: simplify this when the MIPS64R6 emulator
+ * supports NAN2008=1.
+ */
+ dli t0, INT_MIN_AS_DOUBLE
+ dmtc1 t0, f1
+ cmp.le.d f1, f1, f0
+ bc1nez f1, .Lop_double_to_int_trunc
+ cmp.eq.d f1, f0, f0
+ li t0, INT_MIN
+ mfc1 t1, f1
+ and t0, t0, t1
+ b .Lop_double_to_int_done
+
+/* ------------------------------ */
+ .balign 128
+.L_op_double_to_long: /* 0x8b */
+/* File: mips64/op_double_to_long.S */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_DOUBLE f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ /*
+ * TODO: simplify this when the MIPS64R6 emulator
+ * supports NAN2008=1.
+ */
+ dli t0, LONG_MIN_AS_DOUBLE
+ dmtc1 t0, f1
+ cmp.le.d f1, f1, f0
+ bc1nez f1, .Lop_double_to_long_trunc
+ cmp.eq.d f1, f0, f0
+ dli t0, LONG_MIN
+ mfc1 t1, f1
+ and t0, t0, t1
+ b .Lop_double_to_long_done
+
+/* ------------------------------ */
+ .balign 128
+.L_op_double_to_float: /* 0x8c */
+/* File: mips64/op_double_to_float.S */
+ /*
+ * Conversion from or to floating-point happens in a floating-point register.
+ * Therefore we load the input and store the output into or from a
+ * floating-point register irrespective of the type.
+ */
+/* File: mips64/fcvtHeader.S */
+ /*
+ * Loads a specified register from vB. Used primarily for conversions
+ * from or to a floating-point type.
+ *
+ * Sets up a1 = A and a2 = B. a2 is later used by fcvtFooter.S to
+ * store the result in vA and jump to the next instruction.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ */
+ ext a1, rINST, 8, 4 # a1 <- A
+ srl a2, rINST, 12 # a2 <- B
+ GET_VREG_DOUBLE f0, a2
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+
+ cvt.s.d f0, f0
+/* File: mips64/fcvtFooter.S */
+ /*
+ * Stores a specified register containing the result of conversion
+ * from or to a floating-point type and jumps to the next instruction.
+ *
+ * Expects a1 to contain the destination Dalvik register number.
+ * a1 is set up by fcvtHeader.S.
+ *
+ * For: int-to-float, int-to-double, long-to-float, long-to-double,
+ * float-to-int, float-to-long, float-to-double, double-to-int,
+ * double-to-long, double-to-float, neg-float, neg-double.
+ *
+ * Note that this file can't be included after a break in other files
+ * and in those files its contents appear as a copy.
+ * See: float-to-int, float-to-long, double-to-int, double-to-long.
+ */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_byte: /* 0x8d */
+/* File: mips64/op_int_to_byte.S */
+/* File: mips64/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "a0 = op a0".
+ *
+ * for: int-to-byte, int-to-char, int-to-short,
+ * not-int, neg-int
+ */
+ /* unop vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ ext a2, rINST, 8, 4 # a2 <- A
+ # optional op
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ seb a0, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_char: /* 0x8e */
+/* File: mips64/op_int_to_char.S */
+/* File: mips64/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "a0 = op a0".
+ *
+ * for: int-to-byte, int-to-char, int-to-short,
+ * not-int, neg-int
+ */
+ /* unop vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ ext a2, rINST, 8, 4 # a2 <- A
+ # optional op
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ and a0, a0, 0xffff # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_short: /* 0x8f */
+/* File: mips64/op_int_to_short.S */
+/* File: mips64/unop.S */
+ /*
+ * Generic 32-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "a0 = op a0".
+ *
+ * for: int-to-byte, int-to-char, int-to-short,
+ * not-int, neg-int
+ */
+ /* unop vA, vB */
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ ext a2, rINST, 8, 4 # a2 <- A
+ # optional op
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ seh a0, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int: /* 0x90 */
+/* File: mips64/op_add_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ addu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_int: /* 0x91 */
+/* File: mips64/op_sub_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ subu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int: /* 0x92 */
+/* File: mips64/op_mul_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ mul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int: /* 0x93 */
+/* File: mips64/op_div_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ div a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int: /* 0x94 */
+/* File: mips64/op_rem_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ mod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int: /* 0x95 */
+/* File: mips64/op_and_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int: /* 0x96 */
+/* File: mips64/op_or_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int: /* 0x97 */
+/* File: mips64/op_xor_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_int: /* 0x98 */
+/* File: mips64/op_shl_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ sll a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_int: /* 0x99 */
+/* File: mips64/op_shr_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ sra a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_int: /* 0x9a */
+/* File: mips64/op_ushr_int.S */
+/* File: mips64/binop.S */
+ /*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG a0, a2 # a0 <- vBB
+ GET_VREG a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ srl a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_long: /* 0x9b */
+/* File: mips64/op_add_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ daddu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_long: /* 0x9c */
+/* File: mips64/op_sub_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ dsubu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_long: /* 0x9d */
+/* File: mips64/op_mul_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ dmul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_long: /* 0x9e */
+/* File: mips64/op_div_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ ddiv a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_long: /* 0x9f */
+/* File: mips64/op_rem_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ dmod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_long: /* 0xa0 */
+/* File: mips64/op_and_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_long: /* 0xa1 */
+/* File: mips64/op_or_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_long: /* 0xa2 */
+/* File: mips64/op_xor_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_long: /* 0xa3 */
+/* File: mips64/op_shl_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ dsll a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_long: /* 0xa4 */
+/* File: mips64/op_shr_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ dsra a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_long: /* 0xa5 */
+/* File: mips64/op_ushr_long.S */
+/* File: mips64/binopWide.S */
+ /*
+ * Generic 64-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vCC (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long,
+ * xor-long, shl-long, shr-long, ushr-long
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_WIDE a0, a2 # a0 <- vBB
+ GET_VREG_WIDE a1, a3 # a1 <- vCC
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ dsrl a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a4 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_float: /* 0xa6 */
+/* File: mips64/op_add_float.S */
+/* File: mips64/fbinop.S */
+ /*:
+ * Generic 32-bit floating-point operation.
+ *
+ * For: add-float, sub-float, mul-float, div-float.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f0, a2 # f0 <- vBB
+ GET_VREG_FLOAT f1, a3 # f1 <- vCC
+ add.s f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_float: /* 0xa7 */
+/* File: mips64/op_sub_float.S */
+/* File: mips64/fbinop.S */
+ /*:
+ * Generic 32-bit floating-point operation.
+ *
+ * For: add-float, sub-float, mul-float, div-float.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f0, a2 # f0 <- vBB
+ GET_VREG_FLOAT f1, a3 # f1 <- vCC
+ sub.s f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_float: /* 0xa8 */
+/* File: mips64/op_mul_float.S */
+/* File: mips64/fbinop.S */
+ /*:
+ * Generic 32-bit floating-point operation.
+ *
+ * For: add-float, sub-float, mul-float, div-float.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f0, a2 # f0 <- vBB
+ GET_VREG_FLOAT f1, a3 # f1 <- vCC
+ mul.s f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_float: /* 0xa9 */
+/* File: mips64/op_div_float.S */
+/* File: mips64/fbinop.S */
+ /*:
+ * Generic 32-bit floating-point operation.
+ *
+ * For: add-float, sub-float, mul-float, div-float.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f0, a2 # f0 <- vBB
+ GET_VREG_FLOAT f1, a3 # f1 <- vCC
+ div.s f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_float: /* 0xaa */
+/* File: mips64/op_rem_float.S */
+ /* rem-float vAA, vBB, vCC */
+ .extern fmodf
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_FLOAT f12, a2 # f12 <- vBB
+ GET_VREG_FLOAT f13, a3 # f13 <- vCC
+ jal fmodf # f0 <- f12 op f13
+ srl a4, rINST, 8 # a4 <- AA
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_double: /* 0xab */
+/* File: mips64/op_add_double.S */
+/* File: mips64/fbinopWide.S */
+ /*:
+ * Generic 64-bit floating-point operation.
+ *
+ * For: add-double, sub-double, mul-double, div-double.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f0, a2 # f0 <- vBB
+ GET_VREG_DOUBLE f1, a3 # f1 <- vCC
+ add.d f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_double: /* 0xac */
+/* File: mips64/op_sub_double.S */
+/* File: mips64/fbinopWide.S */
+ /*:
+ * Generic 64-bit floating-point operation.
+ *
+ * For: add-double, sub-double, mul-double, div-double.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f0, a2 # f0 <- vBB
+ GET_VREG_DOUBLE f1, a3 # f1 <- vCC
+ sub.d f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_double: /* 0xad */
+/* File: mips64/op_mul_double.S */
+/* File: mips64/fbinopWide.S */
+ /*:
+ * Generic 64-bit floating-point operation.
+ *
+ * For: add-double, sub-double, mul-double, div-double.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f0, a2 # f0 <- vBB
+ GET_VREG_DOUBLE f1, a3 # f1 <- vCC
+ mul.d f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_double: /* 0xae */
+/* File: mips64/op_div_double.S */
+/* File: mips64/fbinopWide.S */
+ /*:
+ * Generic 64-bit floating-point operation.
+ *
+ * For: add-double, sub-double, mul-double, div-double.
+ * form: <op> f0, f0, f1
+ */
+ /* binop vAA, vBB, vCC */
+ srl a4, rINST, 8 # a4 <- AA
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f0, a2 # f0 <- vBB
+ GET_VREG_DOUBLE f1, a3 # f1 <- vCC
+ div.d f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_double: /* 0xaf */
+/* File: mips64/op_rem_double.S */
+ /* rem-double vAA, vBB, vCC */
+ .extern fmod
+ lbu a2, 2(rPC) # a2 <- BB
+ lbu a3, 3(rPC) # a3 <- CC
+ GET_VREG_DOUBLE f12, a2 # f12 <- vBB
+ GET_VREG_DOUBLE f13, a3 # f13 <- vCC
+ jal fmod # f0 <- f12 op f13
+ srl a4, rINST, 8 # a4 <- AA
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a4 # vAA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int_2addr: /* 0xb0 */
+/* File: mips64/op_add_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ addu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_int_2addr: /* 0xb1 */
+/* File: mips64/op_sub_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ subu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int_2addr: /* 0xb2 */
+/* File: mips64/op_mul_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ mul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int_2addr: /* 0xb3 */
+/* File: mips64/op_div_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ div a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int_2addr: /* 0xb4 */
+/* File: mips64/op_rem_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ mod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int_2addr: /* 0xb5 */
+/* File: mips64/op_and_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int_2addr: /* 0xb6 */
+/* File: mips64/op_or_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int_2addr: /* 0xb7 */
+/* File: mips64/op_xor_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_int_2addr: /* 0xb8 */
+/* File: mips64/op_shl_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ sll a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_int_2addr: /* 0xb9 */
+/* File: mips64/op_shr_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ sra a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_int_2addr: /* 0xba */
+/* File: mips64/op_ushr_int_2addr.S */
+/* File: mips64/binop2addr.S */
+ /*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (INT_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a2 # a0 <- vA
+ GET_VREG a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ srl a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_long_2addr: /* 0xbb */
+/* File: mips64/op_add_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ daddu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_long_2addr: /* 0xbc */
+/* File: mips64/op_sub_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ dsubu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_long_2addr: /* 0xbd */
+/* File: mips64/op_mul_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ dmul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_long_2addr: /* 0xbe */
+/* File: mips64/op_div_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ ddiv a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_long_2addr: /* 0xbf */
+/* File: mips64/op_rem_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ dmod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_long_2addr: /* 0xc0 */
+/* File: mips64/op_and_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_long_2addr: /* 0xc1 */
+/* File: mips64/op_or_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_long_2addr: /* 0xc2 */
+/* File: mips64/op_xor_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_long_2addr: /* 0xc3 */
+/* File: mips64/op_shl_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ dsll a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_long_2addr: /* 0xc4 */
+/* File: mips64/op_shr_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ dsra a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_long_2addr: /* 0xc5 */
+/* File: mips64/op_ushr_long_2addr.S */
+/* File: mips64/binopWide2addr.S */
+ /*
+ * Generic 64-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be a MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * vB (a1). Useful for integer division and modulus. Note that we
+ * *don't* check for (LONG_MIN / -1) here, because the CPU handles it
+ * correctly.
+ *
+ * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr,
+ * rem-long/2addr, and-long/2addr, or-long/2addr, xor-long/2addr,
+ * shl-long/2addr, shr-long/2addr, ushr-long/2addr
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_WIDE a0, a2 # a0 <- vA
+ GET_VREG_WIDE a1, a3 # a1 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ # optional op
+ dsrl a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_float_2addr: /* 0xc6 */
+/* File: mips64/op_add_float_2addr.S */
+/* File: mips64/fbinop2addr.S */
+ /*:
+ * Generic 32-bit "/2addr" floating-point operation.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_FLOAT f0, a2 # f0 <- vA
+ GET_VREG_FLOAT f1, a3 # f1 <- vB
+ add.s f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_float_2addr: /* 0xc7 */
+/* File: mips64/op_sub_float_2addr.S */
+/* File: mips64/fbinop2addr.S */
+ /*:
+ * Generic 32-bit "/2addr" floating-point operation.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_FLOAT f0, a2 # f0 <- vA
+ GET_VREG_FLOAT f1, a3 # f1 <- vB
+ sub.s f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_float_2addr: /* 0xc8 */
+/* File: mips64/op_mul_float_2addr.S */
+/* File: mips64/fbinop2addr.S */
+ /*:
+ * Generic 32-bit "/2addr" floating-point operation.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_FLOAT f0, a2 # f0 <- vA
+ GET_VREG_FLOAT f1, a3 # f1 <- vB
+ mul.s f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_float_2addr: /* 0xc9 */
+/* File: mips64/op_div_float_2addr.S */
+/* File: mips64/fbinop2addr.S */
+ /*:
+ * Generic 32-bit "/2addr" floating-point operation.
+ *
+ * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_FLOAT f0, a2 # f0 <- vA
+ GET_VREG_FLOAT f1, a3 # f1 <- vB
+ div.s f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_float_2addr: /* 0xca */
+/* File: mips64/op_rem_float_2addr.S */
+ /* rem-float/2addr vA, vB */
+ .extern fmodf
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_FLOAT f12, a2 # f12 <- vA
+ GET_VREG_FLOAT f13, a3 # f13 <- vB
+ jal fmodf # f0 <- f12 op f13
+ ext a2, rINST, 8, 4 # a2 <- A
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_FLOAT f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_double_2addr: /* 0xcb */
+/* File: mips64/op_add_double_2addr.S */
+/* File: mips64/fbinopWide2addr.S */
+ /*:
+ * Generic 64-bit "/2addr" floating-point operation.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr, div-double/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_DOUBLE f0, a2 # f0 <- vA
+ GET_VREG_DOUBLE f1, a3 # f1 <- vB
+ add.d f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_double_2addr: /* 0xcc */
+/* File: mips64/op_sub_double_2addr.S */
+/* File: mips64/fbinopWide2addr.S */
+ /*:
+ * Generic 64-bit "/2addr" floating-point operation.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr, div-double/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_DOUBLE f0, a2 # f0 <- vA
+ GET_VREG_DOUBLE f1, a3 # f1 <- vB
+ sub.d f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_double_2addr: /* 0xcd */
+/* File: mips64/op_mul_double_2addr.S */
+/* File: mips64/fbinopWide2addr.S */
+ /*:
+ * Generic 64-bit "/2addr" floating-point operation.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr, div-double/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_DOUBLE f0, a2 # f0 <- vA
+ GET_VREG_DOUBLE f1, a3 # f1 <- vB
+ mul.d f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_double_2addr: /* 0xce */
+/* File: mips64/op_div_double_2addr.S */
+/* File: mips64/fbinopWide2addr.S */
+ /*:
+ * Generic 64-bit "/2addr" floating-point operation.
+ *
+ * For: add-double/2addr, sub-double/2addr, mul-double/2addr, div-double/2addr.
+ * form: <op> f0, f0, f1
+ */
+ /* binop/2addr vA, vB */
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_DOUBLE f0, a2 # f0 <- vA
+ GET_VREG_DOUBLE f1, a3 # f1 <- vB
+ div.d f0, f0, f1 # f0 <- f0 op f1
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_double_2addr: /* 0xcf */
+/* File: mips64/op_rem_double_2addr.S */
+ /* rem-double/2addr vA, vB */
+ .extern fmod
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG_DOUBLE f12, a2 # f12 <- vA
+ GET_VREG_DOUBLE f13, a3 # f13 <- vB
+ jal fmod # f0 <- f12 op f13
+ ext a2, rINST, 8, 4 # a2 <- A
+ FETCH_ADVANCE_INST 1 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_DOUBLE f0, a2 # vA <- f0
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int_lit16: /* 0xd0 */
+/* File: mips64/op_add_int_lit16.S */
+/* File: mips64/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CCCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ lh a1, 2(rPC) # a1 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ addu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rsub_int: /* 0xd1 */
+/* File: mips64/op_rsub_int.S */
+/* File: mips64/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CCCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ lh a1, 2(rPC) # a1 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ subu a0, a1, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int_lit16: /* 0xd2 */
+/* File: mips64/op_mul_int_lit16.S */
+/* File: mips64/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CCCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ lh a1, 2(rPC) # a1 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ mul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int_lit16: /* 0xd3 */
+/* File: mips64/op_div_int_lit16.S */
+/* File: mips64/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CCCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ lh a1, 2(rPC) # a1 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ div a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int_lit16: /* 0xd4 */
+/* File: mips64/op_rem_int_lit16.S */
+/* File: mips64/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CCCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ lh a1, 2(rPC) # a1 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ mod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int_lit16: /* 0xd5 */
+/* File: mips64/op_and_int_lit16.S */
+/* File: mips64/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CCCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ lh a1, 2(rPC) # a1 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int_lit16: /* 0xd6 */
+/* File: mips64/op_or_int_lit16.S */
+/* File: mips64/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CCCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ lh a1, 2(rPC) # a1 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int_lit16: /* 0xd7 */
+/* File: mips64/op_xor_int_lit16.S */
+/* File: mips64/binopLit16.S */
+ /*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CCCC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+ * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ lh a1, 2(rPC) # a1 <- sign-extended CCCC
+ ext a2, rINST, 8, 4 # a2 <- A
+ ext a3, rINST, 12, 4 # a3 <- B
+ GET_VREG a0, a3 # a0 <- vB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int_lit8: /* 0xd8 */
+/* File: mips64/op_add_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ addu a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rsub_int_lit8: /* 0xd9 */
+/* File: mips64/op_rsub_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ subu a0, a1, a0 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int_lit8: /* 0xda */
+/* File: mips64/op_mul_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ mul a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int_lit8: /* 0xdb */
+/* File: mips64/op_div_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ div a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int_lit8: /* 0xdc */
+/* File: mips64/op_rem_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 1
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ mod a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int_lit8: /* 0xdd */
+/* File: mips64/op_and_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ and a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int_lit8: /* 0xde */
+/* File: mips64/op_or_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ or a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int_lit8: /* 0xdf */
+/* File: mips64/op_xor_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ xor a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_int_lit8: /* 0xe0 */
+/* File: mips64/op_shl_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ sll a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_int_lit8: /* 0xe1 */
+/* File: mips64/op_shr_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ sra a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_int_lit8: /* 0xe2 */
+/* File: mips64/op_ushr_int_lit8.S */
+/* File: mips64/binopLit8.S */
+ /*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = a0 op a1".
+ * This could be an MIPS instruction or a function call. (If the result
+ * comes back in a register other than a0, you can override "result".)
+ *
+ * If "chkzero" is set to 1, we perform a divide-by-zero check on
+ * CC (a1). Useful for integer division and modulus.
+ *
+ * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+ * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ lbu a3, 2(rPC) # a3 <- BB
+ lb a1, 3(rPC) # a1 <- sign-extended CC
+ srl a2, rINST, 8 # a2 <- AA
+ GET_VREG a0, a3 # a0 <- vBB
+ .if 0
+ beqz a1, common_errDivideByZero # is second operand zero?
+ .endif
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ # optional op
+ srl a0, a0, a1 # a0 <- op, a0-a3 changed
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG a0, a2 # vAA <- a0
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_quick: /* 0xe3 */
+/* File: mips64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- object we're operating on
+ ext a4, rINST, 8, 4 # a4 <- A
+ daddu a1, a1, a3
+ beqz a3, common_errNullObject # object was null
+ lw a0, 0(a1) # a0 <- obj.field
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG a0, a4 # fp[A] <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_wide_quick: /* 0xe4 */
+/* File: mips64/op_iget_wide_quick.S */
+ /* iget-wide-quick vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a4, 2(rPC) # a4 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- object we're operating on
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a3, common_errNullObject # object was null
+ daddu a4, a3, a4 # create direct pointer
+ lw a0, 0(a4)
+ lw a1, 4(a4)
+ dinsu a0, a1, 32, 32
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG_WIDE a0, a2
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_object_quick: /* 0xe5 */
+/* File: mips64/op_iget_object_quick.S */
+ /* For: iget-object-quick */
+ /* op vA, vB, offset//CCCC */
+ .extern artIGetObjectFromMterp
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ EXPORT_PC
+ GET_VREG_U a0, a2 # a0 <- object we're operating on
+ jal artIGetObjectFromMterp # (obj, offset)
+ ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
+ ext a2, rINST, 8, 4 # a2 <- A
+ PREFETCH_INST 2
+ bnez a3, MterpPossibleException # bail out
+ SET_VREG_OBJECT v0, a2 # fp[A] <- v0
+ ADVANCE 2 # advance rPC
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_quick: /* 0xe6 */
+/* File: mips64/op_iput_quick.S */
+ /* For: iput-quick, iput-boolean-quick, iput-byte-quick, iput-char-quick, iput-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a3, common_errNullObject # object was null
+ GET_VREG a0, a2 # a0 <- fp[A]
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ daddu a1, a1, a3
+ sw a0, 0(a1) # obj.field <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_wide_quick: /* 0xe7 */
+/* File: mips64/op_iput_wide_quick.S */
+ /* iput-wide-quick vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a3, 2(rPC) # a3 <- field byte offset
+ GET_VREG_U a2, a2 # a2 <- fp[B], the object pointer
+ ext a0, rINST, 8, 4 # a0 <- A
+ beqz a2, common_errNullObject # object was null
+ GET_VREG_WIDE a0, a0 # a0 <- fp[A]
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ daddu a1, a2, a3 # create a direct pointer
+ sw a0, 0(a1)
+ dsrl32 a0, a0, 0
+ sw a0, 4(a1)
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_object_quick: /* 0xe8 */
+/* File: mips64/op_iput_object_quick.S */
+ .extern MterpIputObjectQuick
+ EXPORT_PC
+ daddu a0, rFP, OFF_FP_SHADOWFRAME
+ move a1, rPC
+ move a2, rINST
+ jal MterpIputObjectQuick
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual_quick: /* 0xe9 */
+/* File: mips64/op_invoke_virtual_quick.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeVirtualQuick
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeVirtualQuick
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual_range_quick: /* 0xea */
+/* File: mips64/op_invoke_virtual_range_quick.S */
+/* File: mips64/invoke.S */
+ /*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeVirtualQuickRange
+ EXPORT_PC
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rPC
+ move a3, rINST
+ jal MterpInvokeVirtualQuickRange
+ beqzc v0, MterpException
+ FETCH_ADVANCE_INST 3
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_boolean_quick: /* 0xeb */
+/* File: mips64/op_iput_boolean_quick.S */
+/* File: mips64/op_iput_quick.S */
+ /* For: iput-quick, iput-boolean-quick, iput-byte-quick, iput-char-quick, iput-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a3, common_errNullObject # object was null
+ GET_VREG a0, a2 # a0 <- fp[A]
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ daddu a1, a1, a3
+ sb a0, 0(a1) # obj.field <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_byte_quick: /* 0xec */
+/* File: mips64/op_iput_byte_quick.S */
+/* File: mips64/op_iput_quick.S */
+ /* For: iput-quick, iput-boolean-quick, iput-byte-quick, iput-char-quick, iput-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a3, common_errNullObject # object was null
+ GET_VREG a0, a2 # a0 <- fp[A]
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ daddu a1, a1, a3
+ sb a0, 0(a1) # obj.field <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_char_quick: /* 0xed */
+/* File: mips64/op_iput_char_quick.S */
+/* File: mips64/op_iput_quick.S */
+ /* For: iput-quick, iput-boolean-quick, iput-byte-quick, iput-char-quick, iput-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a3, common_errNullObject # object was null
+ GET_VREG a0, a2 # a0 <- fp[A]
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ daddu a1, a1, a3
+ sh a0, 0(a1) # obj.field <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_short_quick: /* 0xee */
+/* File: mips64/op_iput_short_quick.S */
+/* File: mips64/op_iput_quick.S */
+ /* For: iput-quick, iput-boolean-quick, iput-byte-quick, iput-char-quick, iput-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- fp[B], the object pointer
+ ext a2, rINST, 8, 4 # a2 <- A
+ beqz a3, common_errNullObject # object was null
+ GET_VREG a0, a2 # a0 <- fp[A]
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ daddu a1, a1, a3
+ sh a0, 0(a1) # obj.field <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_boolean_quick: /* 0xef */
+/* File: mips64/op_iget_boolean_quick.S */
+/* File: mips64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- object we're operating on
+ ext a4, rINST, 8, 4 # a4 <- A
+ daddu a1, a1, a3
+ beqz a3, common_errNullObject # object was null
+ lbu a0, 0(a1) # a0 <- obj.field
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG a0, a4 # fp[A] <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_byte_quick: /* 0xf0 */
+/* File: mips64/op_iget_byte_quick.S */
+/* File: mips64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- object we're operating on
+ ext a4, rINST, 8, 4 # a4 <- A
+ daddu a1, a1, a3
+ beqz a3, common_errNullObject # object was null
+ lb a0, 0(a1) # a0 <- obj.field
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG a0, a4 # fp[A] <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_char_quick: /* 0xf1 */
+/* File: mips64/op_iget_char_quick.S */
+/* File: mips64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- object we're operating on
+ ext a4, rINST, 8, 4 # a4 <- A
+ daddu a1, a1, a3
+ beqz a3, common_errNullObject # object was null
+ lhu a0, 0(a1) # a0 <- obj.field
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG a0, a4 # fp[A] <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_short_quick: /* 0xf2 */
+/* File: mips64/op_iget_short_quick.S */
+/* File: mips64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */
+ /* op vA, vB, offset//CCCC */
+ srl a2, rINST, 12 # a2 <- B
+ lhu a1, 2(rPC) # a1 <- field byte offset
+ GET_VREG_U a3, a2 # a3 <- object we're operating on
+ ext a4, rINST, 8, 4 # a4 <- A
+ daddu a1, a1, a3
+ beqz a3, common_errNullObject # object was null
+ lh a0, 0(a1) # a0 <- obj.field
+ FETCH_ADVANCE_INST 2 # advance rPC, load rINST
+ SET_VREG a0, a4 # fp[A] <- a0
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_lambda: /* 0xf3 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_f4: /* 0xf4 */
+/* File: mips64/op_unused_f4.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_capture_variable: /* 0xf5 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_create_lambda: /* 0xf6 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_liberate_variable: /* 0xf7 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_box_lambda: /* 0xf8 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unbox_lambda: /* 0xf9 */
+/* Transfer stub to alternate interpreter */
+ b MterpFallback
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fa: /* 0xfa */
+/* File: mips64/op_unused_fa.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fb: /* 0xfb */
+/* File: mips64/op_unused_fb.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fc: /* 0xfc */
+/* File: mips64/op_unused_fc.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fd: /* 0xfd */
+/* File: mips64/op_unused_fd.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fe: /* 0xfe */
+/* File: mips64/op_unused_fe.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_ff: /* 0xff */
+/* File: mips64/op_unused_ff.S */
+/* File: mips64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ b MterpFallback
+
+
+ .balign 128
+ .size artMterpAsmInstructionStart, .-artMterpAsmInstructionStart
+ .global artMterpAsmInstructionEnd
+artMterpAsmInstructionEnd:
+
+/*
+ * ===========================================================================
+ * Sister implementations
+ * ===========================================================================
+ */
+ .global artMterpAsmSisterStart
+ .type artMterpAsmSisterStart, %function
+ .text
+ .balign 4
+artMterpAsmSisterStart:
+
+/* continuation for op_float_to_int */
+.Lop_float_to_int_trunc:
+ trunc.w.s f0, f0
+ mfc1 t0, f0
+.Lop_float_to_int_done:
+ /* Can't include fcvtFooter.S after break */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG t0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* continuation for op_float_to_long */
+.Lop_float_to_long_trunc:
+ trunc.l.s f0, f0
+ dmfc1 t0, f0
+.Lop_float_to_long_done:
+ /* Can't include fcvtFooter.S after break */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE t0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* continuation for op_double_to_int */
+.Lop_double_to_int_trunc:
+ trunc.w.d f0, f0
+ mfc1 t0, f0
+.Lop_double_to_int_done:
+ /* Can't include fcvtFooter.S after break */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG t0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+/* continuation for op_double_to_long */
+.Lop_double_to_long_trunc:
+ trunc.l.d f0, f0
+ dmfc1 t0, f0
+.Lop_double_to_long_done:
+ /* Can't include fcvtFooter.S after break */
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ SET_VREG_WIDE t0, a1
+ GOTO_OPCODE v0 # jump to next instruction
+
+ .size artMterpAsmSisterStart, .-artMterpAsmSisterStart
+ .global artMterpAsmSisterEnd
+artMterpAsmSisterEnd:
+
+
+ .global artMterpAsmAltInstructionStart
+ .type artMterpAsmAltInstructionStart, %function
+ .text
+
+artMterpAsmAltInstructionStart = .L_ALT_op_nop
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_nop: /* 0x00 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (0 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move: /* 0x01 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (1 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_from16: /* 0x02 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (2 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_16: /* 0x03 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (3 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_wide: /* 0x04 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (4 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_wide_from16: /* 0x05 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (5 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_wide_16: /* 0x06 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (6 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_object: /* 0x07 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (7 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_object_from16: /* 0x08 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (8 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_object_16: /* 0x09 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (9 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_result: /* 0x0a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (10 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_result_wide: /* 0x0b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (11 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_result_object: /* 0x0c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (12 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_exception: /* 0x0d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (13 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_void: /* 0x0e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (14 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return: /* 0x0f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (15 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_wide: /* 0x10 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (16 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_object: /* 0x11 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (17 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_4: /* 0x12 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (18 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_16: /* 0x13 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (19 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const: /* 0x14 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (20 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_high16: /* 0x15 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (21 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide_16: /* 0x16 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (22 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide_32: /* 0x17 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (23 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide: /* 0x18 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (24 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide_high16: /* 0x19 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (25 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_string: /* 0x1a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (26 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_string_jumbo: /* 0x1b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (27 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_class: /* 0x1c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (28 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_monitor_enter: /* 0x1d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (29 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_monitor_exit: /* 0x1e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (30 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_check_cast: /* 0x1f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (31 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_instance_of: /* 0x20 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (32 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_array_length: /* 0x21 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (33 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_new_instance: /* 0x22 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (34 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_new_array: /* 0x23 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (35 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_filled_new_array: /* 0x24 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (36 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_filled_new_array_range: /* 0x25 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (37 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_fill_array_data: /* 0x26 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (38 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_throw: /* 0x27 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (39 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_goto: /* 0x28 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (40 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_goto_16: /* 0x29 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (41 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_goto_32: /* 0x2a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (42 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_packed_switch: /* 0x2b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (43 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sparse_switch: /* 0x2c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (44 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpl_float: /* 0x2d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (45 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpg_float: /* 0x2e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (46 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpl_double: /* 0x2f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (47 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpg_double: /* 0x30 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (48 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmp_long: /* 0x31 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (49 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_eq: /* 0x32 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (50 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_ne: /* 0x33 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (51 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_lt: /* 0x34 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (52 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_ge: /* 0x35 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (53 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_gt: /* 0x36 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (54 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_le: /* 0x37 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (55 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_eqz: /* 0x38 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (56 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_nez: /* 0x39 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (57 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_ltz: /* 0x3a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (58 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_gez: /* 0x3b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (59 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_gtz: /* 0x3c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (60 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_lez: /* 0x3d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (61 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_3e: /* 0x3e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (62 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_3f: /* 0x3f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (63 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_40: /* 0x40 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (64 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_41: /* 0x41 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (65 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_42: /* 0x42 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (66 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_43: /* 0x43 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (67 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget: /* 0x44 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (68 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_wide: /* 0x45 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (69 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_object: /* 0x46 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (70 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_boolean: /* 0x47 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (71 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_byte: /* 0x48 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (72 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_char: /* 0x49 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (73 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_short: /* 0x4a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (74 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput: /* 0x4b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (75 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_wide: /* 0x4c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (76 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_object: /* 0x4d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (77 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_boolean: /* 0x4e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (78 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_byte: /* 0x4f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (79 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_char: /* 0x50 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (80 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_short: /* 0x51 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (81 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget: /* 0x52 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (82 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_wide: /* 0x53 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (83 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_object: /* 0x54 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (84 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_boolean: /* 0x55 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (85 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_byte: /* 0x56 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (86 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_char: /* 0x57 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (87 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_short: /* 0x58 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (88 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput: /* 0x59 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (89 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_wide: /* 0x5a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (90 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_object: /* 0x5b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (91 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_boolean: /* 0x5c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (92 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_byte: /* 0x5d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (93 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_char: /* 0x5e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (94 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_short: /* 0x5f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (95 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget: /* 0x60 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (96 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_wide: /* 0x61 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (97 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_object: /* 0x62 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (98 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_boolean: /* 0x63 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (99 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_byte: /* 0x64 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (100 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_char: /* 0x65 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (101 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_short: /* 0x66 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (102 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput: /* 0x67 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (103 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_wide: /* 0x68 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (104 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_object: /* 0x69 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (105 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_boolean: /* 0x6a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (106 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_byte: /* 0x6b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (107 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_char: /* 0x6c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (108 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_short: /* 0x6d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (109 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual: /* 0x6e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (110 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_super: /* 0x6f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (111 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_direct: /* 0x70 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (112 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_static: /* 0x71 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (113 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_interface: /* 0x72 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (114 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_void_no_barrier: /* 0x73 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (115 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual_range: /* 0x74 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (116 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_super_range: /* 0x75 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (117 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_direct_range: /* 0x76 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (118 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_static_range: /* 0x77 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (119 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_interface_range: /* 0x78 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (120 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_79: /* 0x79 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (121 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_7a: /* 0x7a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (122 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_int: /* 0x7b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (123 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_not_int: /* 0x7c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (124 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_long: /* 0x7d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (125 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_not_long: /* 0x7e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (126 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_float: /* 0x7f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (127 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_double: /* 0x80 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (128 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_long: /* 0x81 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (129 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_float: /* 0x82 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (130 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_double: /* 0x83 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (131 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_long_to_int: /* 0x84 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (132 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_long_to_float: /* 0x85 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (133 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_long_to_double: /* 0x86 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (134 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_float_to_int: /* 0x87 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (135 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_float_to_long: /* 0x88 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (136 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_float_to_double: /* 0x89 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (137 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_double_to_int: /* 0x8a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (138 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_double_to_long: /* 0x8b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (139 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_double_to_float: /* 0x8c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (140 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_byte: /* 0x8d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (141 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_char: /* 0x8e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (142 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_short: /* 0x8f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (143 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int: /* 0x90 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (144 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_int: /* 0x91 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (145 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int: /* 0x92 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (146 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int: /* 0x93 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (147 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int: /* 0x94 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (148 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int: /* 0x95 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (149 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int: /* 0x96 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (150 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int: /* 0x97 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (151 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_int: /* 0x98 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (152 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_int: /* 0x99 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (153 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_int: /* 0x9a */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (154 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_long: /* 0x9b */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (155 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_long: /* 0x9c */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (156 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_long: /* 0x9d */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (157 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_long: /* 0x9e */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (158 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_long: /* 0x9f */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (159 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_long: /* 0xa0 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (160 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_long: /* 0xa1 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (161 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_long: /* 0xa2 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (162 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_long: /* 0xa3 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (163 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_long: /* 0xa4 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (164 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_long: /* 0xa5 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (165 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_float: /* 0xa6 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (166 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_float: /* 0xa7 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (167 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_float: /* 0xa8 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (168 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_float: /* 0xa9 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (169 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_float: /* 0xaa */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (170 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_double: /* 0xab */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (171 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_double: /* 0xac */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (172 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_double: /* 0xad */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (173 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_double: /* 0xae */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (174 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_double: /* 0xaf */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (175 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int_2addr: /* 0xb0 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (176 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_int_2addr: /* 0xb1 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (177 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int_2addr: /* 0xb2 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (178 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int_2addr: /* 0xb3 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (179 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int_2addr: /* 0xb4 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (180 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int_2addr: /* 0xb5 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (181 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int_2addr: /* 0xb6 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (182 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int_2addr: /* 0xb7 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (183 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_int_2addr: /* 0xb8 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (184 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_int_2addr: /* 0xb9 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (185 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_int_2addr: /* 0xba */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (186 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_long_2addr: /* 0xbb */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (187 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_long_2addr: /* 0xbc */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (188 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_long_2addr: /* 0xbd */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (189 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_long_2addr: /* 0xbe */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (190 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_long_2addr: /* 0xbf */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (191 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_long_2addr: /* 0xc0 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (192 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_long_2addr: /* 0xc1 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (193 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_long_2addr: /* 0xc2 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (194 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_long_2addr: /* 0xc3 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (195 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_long_2addr: /* 0xc4 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (196 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_long_2addr: /* 0xc5 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (197 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_float_2addr: /* 0xc6 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (198 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_float_2addr: /* 0xc7 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (199 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_float_2addr: /* 0xc8 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (200 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_float_2addr: /* 0xc9 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (201 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_float_2addr: /* 0xca */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (202 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_double_2addr: /* 0xcb */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (203 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_double_2addr: /* 0xcc */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (204 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_double_2addr: /* 0xcd */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (205 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_double_2addr: /* 0xce */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (206 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_double_2addr: /* 0xcf */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (207 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int_lit16: /* 0xd0 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (208 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rsub_int: /* 0xd1 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (209 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int_lit16: /* 0xd2 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (210 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int_lit16: /* 0xd3 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (211 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int_lit16: /* 0xd4 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (212 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int_lit16: /* 0xd5 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (213 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int_lit16: /* 0xd6 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (214 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int_lit16: /* 0xd7 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (215 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int_lit8: /* 0xd8 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (216 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rsub_int_lit8: /* 0xd9 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (217 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int_lit8: /* 0xda */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (218 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int_lit8: /* 0xdb */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (219 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int_lit8: /* 0xdc */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (220 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int_lit8: /* 0xdd */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (221 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int_lit8: /* 0xde */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (222 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int_lit8: /* 0xdf */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (223 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_int_lit8: /* 0xe0 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (224 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_int_lit8: /* 0xe1 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (225 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_int_lit8: /* 0xe2 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (226 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_quick: /* 0xe3 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (227 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_wide_quick: /* 0xe4 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (228 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_object_quick: /* 0xe5 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (229 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_quick: /* 0xe6 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (230 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_wide_quick: /* 0xe7 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (231 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_object_quick: /* 0xe8 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (232 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual_quick: /* 0xe9 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (233 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual_range_quick: /* 0xea */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (234 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_boolean_quick: /* 0xeb */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (235 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_byte_quick: /* 0xec */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (236 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_char_quick: /* 0xed */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (237 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_short_quick: /* 0xee */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (238 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_boolean_quick: /* 0xef */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (239 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_byte_quick: /* 0xf0 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (240 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_char_quick: /* 0xf1 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (241 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_short_quick: /* 0xf2 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (242 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_lambda: /* 0xf3 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (243 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_f4: /* 0xf4 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (244 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_capture_variable: /* 0xf5 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (245 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_create_lambda: /* 0xf6 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (246 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_liberate_variable: /* 0xf7 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (247 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_box_lambda: /* 0xf8 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (248 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unbox_lambda: /* 0xf9 */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (249 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fa: /* 0xfa */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (250 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fb: /* 0xfb */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (251 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fc: /* 0xfc */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (252 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fd: /* 0xfd */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (253 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fe: /* 0xfe */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (254 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_ff: /* 0xff */
+/* File: mips64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Note that the call to MterpCheckBefore is done as a tail call.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ dla ra, artMterpAsmInstructionStart
+ dla t9, MterpCheckBefore
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ daddu ra, ra, (255 * 128) # Addr of primary handler.
+ jalr zero, t9 # (self, shadow_frame) Note: tail call.
+
+ .balign 128
+ .size artMterpAsmAltInstructionStart, .-artMterpAsmAltInstructionStart
+ .global artMterpAsmAltInstructionEnd
+artMterpAsmAltInstructionEnd:
+/* File: mips64/footer.S */
+/*
+ * We've detected a condition that will result in an exception, but the exception
+ * has not yet been thrown. Just bail out to the reference interpreter to deal with it.
+ * TUNING: for consistency, we may want to just go ahead and handle these here.
+ */
+
+ .extern MterpLogDivideByZeroException
+common_errDivideByZero:
+ EXPORT_PC
+#if MTERP_LOGGING
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpLogDivideByZeroException
+#endif
+ b MterpCommonFallback
+
+ .extern MterpLogArrayIndexException
+common_errArrayIndex:
+ EXPORT_PC
+#if MTERP_LOGGING
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpLogArrayIndexException
+#endif
+ b MterpCommonFallback
+
+ .extern MterpLogNullObjectException
+common_errNullObject:
+ EXPORT_PC
+#if MTERP_LOGGING
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpLogNullObjectException
+#endif
+ b MterpCommonFallback
+
+/*
+ * If we're here, something is out of the ordinary. If there is a pending
+ * exception, handle it. Otherwise, roll back and retry with the reference
+ * interpreter.
+ */
+MterpPossibleException:
+ ld a0, THREAD_EXCEPTION_OFFSET(rSELF)
+ beqzc a0, MterpFallback # If not, fall back to reference interpreter.
+ /* intentional fallthrough - handle pending exception. */
+/*
+ * On return from a runtime helper routine, we've found a pending exception.
+ * Can we handle it here - or need to bail out to caller?
+ *
+ */
+ .extern MterpHandleException
+MterpException:
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpHandleException # (self, shadow_frame)
+ beqzc v0, MterpExceptionReturn # no local catch, back to caller.
+ ld a0, OFF_FP_CODE_ITEM(rFP)
+ lwu a1, OFF_FP_DEX_PC(rFP)
+ REFRESH_IBASE
+ daddu rPC, a0, CODEITEM_INSNS_OFFSET
+ dlsa rPC, a1, rPC, 1 # generate new dex_pc_ptr
+ sd rPC, OFF_FP_DEX_PC_PTR(rFP)
+ /* resume execution at catch block */
+ FETCH_INST
+ GET_INST_OPCODE v0
+ GOTO_OPCODE v0
+ /* NOTE: no fallthrough */
+
+/*
+ * Check for suspend check request. Assumes rINST already loaded, rPC advanced and
+ * still needs to get the opcode and branch to it, and flags are in ra.
+ */
+ .extern MterpSuspendCheck
+MterpCheckSuspendAndContinue:
+ REFRESH_IBASE
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ bnez ra, check1
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+check1:
+ EXPORT_PC
+ move a0, rSELF
+ jal MterpSuspendCheck # (self)
+ GET_INST_OPCODE v0 # extract opcode from rINST
+ GOTO_OPCODE v0 # jump to next instruction
+
+/*
+ * Bail out to reference interpreter.
+ */
+ .extern MterpLogFallback
+MterpFallback:
+ EXPORT_PC
+#if MTERP_LOGGING
+ move a0, rSELF
+ daddu a1, rFP, OFF_FP_SHADOWFRAME
+ jal MterpLogFallback
+#endif
+MterpCommonFallback:
+ li v0, 0 # signal retry with reference interpreter.
+ b MterpDone
+
+/*
+ * We pushed some registers on the stack in ExecuteMterpImpl, then saved
+ * SP and RA. Here we restore SP, restore the registers, and then restore
+ * RA to PC.
+ *
+ * On entry:
+ * uint32_t* rFP (should still be live, pointer to base of vregs)
+ */
+MterpExceptionReturn:
+ li v0, 1 # signal return to caller.
+ b MterpDone
+/*
+ * Returned value is expected in a0 and if it's not 64-bit, the 32 most
+ * significant bits of a0 must be 0.
+ */
+MterpReturn:
+ ld a2, OFF_FP_RESULT_REGISTER(rFP)
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ sd a0, 0(a2)
+ move a0, rSELF
+ and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
+ beqzc ra, check2
+ jal MterpSuspendCheck # (self)
+check2:
+ li v0, 1 # signal return to caller.
+MterpDone:
+ ld s5, STACK_OFFSET_S5(sp)
+ .cfi_restore 21
+ ld s4, STACK_OFFSET_S4(sp)
+ .cfi_restore 20
+ ld s3, STACK_OFFSET_S3(sp)
+ .cfi_restore 19
+ ld s2, STACK_OFFSET_S2(sp)
+ .cfi_restore 18
+ ld s1, STACK_OFFSET_S1(sp)
+ .cfi_restore 17
+ ld s0, STACK_OFFSET_S0(sp)
+ .cfi_restore 16
+
+ ld ra, STACK_OFFSET_RA(sp)
+ .cfi_restore 31
+
+ ld t8, STACK_OFFSET_GP(sp)
+ .cpreturn
+ .cfi_restore 28
+
+ .set noreorder
+ jr ra
+ daddu sp, sp, STACK_SIZE
+ .cfi_adjust_cfa_offset -STACK_SIZE
+
+ .cfi_endproc
+ .size ExecuteMterpImpl, .-ExecuteMterpImpl
+
diff --git a/runtime/interpreter/mterp/out/mterp_x86.S b/runtime/interpreter/mterp/out/mterp_x86.S
index 567550f..ebac5fc 100644
--- a/runtime/interpreter/mterp/out/mterp_x86.S
+++ b/runtime/interpreter/mterp/out/mterp_x86.S
@@ -112,25 +112,32 @@
#define SYMBOL(name) name
#endif
+.macro PUSH _reg
+ pushl \_reg
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset \_reg, 0
+.endm
+
+.macro POP _reg
+ popl \_reg
+ .cfi_adjust_cfa_offset -4
+ .cfi_restore \_reg
+.endm
+
/* Frame size must be 16-byte aligned.
- * Remember about 4 bytes for return address
+ * Remember about 4 bytes for return address + 4 * 4 for spills
*/
-#define FRAME_SIZE 44
+#define FRAME_SIZE 28
/* Frame diagram while executing ExecuteMterpImpl, high to low addresses */
-#define IN_ARG3 (FRAME_SIZE + 16)
-#define IN_ARG2 (FRAME_SIZE + 12)
-#define IN_ARG1 (FRAME_SIZE + 8)
-#define IN_ARG0 (FRAME_SIZE + 4)
-#define CALLER_RP (FRAME_SIZE + 0)
+#define IN_ARG3 (FRAME_SIZE + 16 + 16)
+#define IN_ARG2 (FRAME_SIZE + 16 + 12)
+#define IN_ARG1 (FRAME_SIZE + 16 + 8)
+#define IN_ARG0 (FRAME_SIZE + 16 + 4)
/* Spill offsets relative to %esp */
-#define EBP_SPILL (FRAME_SIZE - 4)
-#define EDI_SPILL (FRAME_SIZE - 8)
-#define ESI_SPILL (FRAME_SIZE - 12)
-#define EBX_SPILL (FRAME_SIZE - 16)
-#define LOCAL0 (FRAME_SIZE - 20)
-#define LOCAL1 (FRAME_SIZE - 24)
-#define LOCAL2 (FRAME_SIZE - 28)
+#define LOCAL0 (FRAME_SIZE - 4)
+#define LOCAL1 (FRAME_SIZE - 8)
+#define LOCAL2 (FRAME_SIZE - 12)
/* Out Arg offsets, relative to %esp */
#define OUT_ARG3 ( 12)
#define OUT_ARG2 ( 8)
@@ -360,16 +367,18 @@
SYMBOL(ExecuteMterpImpl):
.cfi_startproc
+ .cfi_def_cfa esp, 4
+
+ /* Spill callee save regs */
+ PUSH %ebp
+ PUSH %edi
+ PUSH %esi
+ PUSH %ebx
+
/* Allocate frame */
subl $FRAME_SIZE, %esp
.cfi_adjust_cfa_offset FRAME_SIZE
- /* Spill callee save regs */
- movl %ebp, EBP_SPILL(%esp)
- movl %edi, EDI_SPILL(%esp)
- movl %esi, ESI_SPILL(%esp)
- movl %ebx, EBX_SPILL(%esp)
-
/* Load ShadowFrame pointer */
movl IN_ARG2(%esp), %edx
@@ -12985,17 +12994,16 @@
movl %ecx, 4(%edx)
mov $1, %eax
MterpDone:
- /* Restore callee save register */
- movl EBP_SPILL(%esp), %ebp
- movl EDI_SPILL(%esp), %edi
- movl ESI_SPILL(%esp), %esi
- movl EBX_SPILL(%esp), %ebx
-
/* pop up frame */
addl $FRAME_SIZE, %esp
.cfi_adjust_cfa_offset -FRAME_SIZE
- ret
+ /* Restore callee save register */
+ POP %ebx
+ POP %esi
+ POP %edi
+ POP %ebp
+ ret
.cfi_endproc
SIZE(ExecuteMterpImpl,ExecuteMterpImpl)
diff --git a/runtime/interpreter/mterp/out/mterp_x86_64.S b/runtime/interpreter/mterp/out/mterp_x86_64.S
new file mode 100644
index 0000000..a1360e0
--- /dev/null
+++ b/runtime/interpreter/mterp/out/mterp_x86_64.S
@@ -0,0 +1,11960 @@
+/*
+ * This file was generated automatically by gen-mterp.py for 'x86_64'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: x86_64/header.S */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ Art assembly interpreter notes:
+
+ First validate assembly code by implementing ExecuteXXXImpl() style body (doesn't
+ handle invoke, allows higher-level code to create frame & shadow frame.
+
+ Once that's working, support direct entry code & eliminate shadow frame (and
+ excess locals allocation.
+
+ Some (hopefully) temporary ugliness. We'll treat rFP as pointing to the
+ base of the vreg array within the shadow frame. Access the other fields,
+ dex_pc_, method_ and number_of_vregs_ via negative offsets. For now, we'll continue
+ the shadow frame mechanism of double-storing object references - via rFP &
+ number_of_vregs_.
+
+ */
+
+/*
+x86_64 ABI general notes:
+
+Caller save set:
+ rax, rdx, rcx, rsi, rdi, r8-r11, st(0)-st(7)
+Callee save set:
+ rbx, rbp, r12-r15
+Return regs:
+ 32-bit in eax
+ 64-bit in rax
+ fp on xmm0
+
+First 8 fp parameters came in xmm0-xmm7.
+First 6 non-fp parameters came in rdi, rsi, rdx, rcx, r8, r9.
+Other parameters passed on stack, pushed right-to-left. On entry to target, first
+param is at 8(%esp). Traditional entry code is:
+
+Stack must be 16-byte aligned to support SSE in native code.
+
+If we're not doing variable stack allocation (alloca), the frame pointer can be
+eliminated and all arg references adjusted to be esp relative.
+*/
+
+/*
+Mterp and x86_64 notes:
+
+Some key interpreter variables will be assigned to registers.
+
+ nick reg purpose
+ rSELF rbp pointer to ThreadSelf.
+ rPC r12 interpreted program counter, used for fetching instructions
+ rFP r13 interpreted frame pointer, used for accessing locals and args
+ rINSTw bx first 16-bit code of current instruction
+ rINSTbl bl opcode portion of instruction word
+ rINSTbh bh high byte of inst word, usually contains src/tgt reg names
+ rIBASE r14 base of instruction handler table
+ rREFS r15 base of object references in shadow frame.
+
+Notes:
+ o High order 16 bits of ebx must be zero on entry to handler
+ o rPC, rFP, rINSTw/rINSTbl valid on handler entry and exit
+ o eax and ecx are scratch, rINSTw/ebx sometimes scratch
+
+Macros are provided for common operations. Each macro MUST emit only
+one instruction to make instruction-counting easier. They MUST NOT alter
+unspecified registers or condition codes.
+*/
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "asm_support.h"
+
+/*
+ * Handle mac compiler specific
+ */
+#if defined(__APPLE__)
+ #define MACRO_LITERAL(value) $(value)
+ #define FUNCTION_TYPE(name)
+ #define SIZE(start,end)
+ // Mac OS' symbols have an _ prefix.
+ #define SYMBOL(name) _ ## name
+#else
+ #define MACRO_LITERAL(value) $value
+ #define FUNCTION_TYPE(name) .type name, @function
+ #define SIZE(start,end) .size start, .-end
+ #define SYMBOL(name) name
+#endif
+
+.macro PUSH _reg
+ pushq \_reg
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset \_reg, 0
+.endm
+
+.macro POP _reg
+ popq \_reg
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore \_reg
+.endm
+
+/* Frame size must be 16-byte aligned.
+ * Remember about 8 bytes for return address + 6 * 8 for spills.
+ */
+#define FRAME_SIZE 8
+
+/* Frame diagram while executing ExecuteMterpImpl, high to low addresses */
+#define IN_ARG3 %rcx
+#define IN_ARG2 %rdx
+#define IN_ARG1 %rsi
+#define IN_ARG0 %rdi
+/* Out Args */
+#define OUT_ARG3 %rcx
+#define OUT_ARG2 %rdx
+#define OUT_ARG1 %rsi
+#define OUT_ARG0 %rdi
+#define OUT_32_ARG3 %ecx
+#define OUT_32_ARG2 %edx
+#define OUT_32_ARG1 %esi
+#define OUT_32_ARG0 %edi
+#define OUT_FP_ARG1 %xmm1
+#define OUT_FP_ARG0 %xmm0
+
+/* During bringup, we'll use the shadow frame model instead of rFP */
+/* single-purpose registers, given names for clarity */
+#define rSELF %rbp
+#define rPC %r12
+#define rFP %r13
+#define rINST %ebx
+#define rINSTq %rbx
+#define rINSTw %bx
+#define rINSTbh %bh
+#define rINSTbl %bl
+#define rIBASE %r14
+#define rREFS %r15
+
+/*
+ * Instead of holding a pointer to the shadow frame, we keep rFP at the base of the vregs. So,
+ * to access other shadow frame fields, we need to use a backwards offset. Define those here.
+ */
+#define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET)
+#define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET)
+#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET)
+#define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET)
+#define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET)
+#define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET)
+#define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET)
+#define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET)
+#define OFF_FP_SHADOWFRAME (-SHADOWFRAME_VREGS_OFFSET)
+
+#define MTERP_PROFILE_BRANCHES 1
+#define MTERP_LOGGING 0
+
+/*
+ * Profile branch. rINST should contain the offset. %eax is scratch.
+ */
+.macro MTERP_PROFILE_BRANCH
+#ifdef MTERP_PROFILE_BRANCHES
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movl rINST, OUT_32_ARG2
+ call SYMBOL(MterpProfileBranch)
+ testb %al, %al
+ jnz MterpOnStackReplacement
+#endif
+.endm
+
+/*
+ * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must
+ * be done *before* something throws.
+ *
+ * It's okay to do this more than once.
+ *
+ * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped
+ * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction
+ * offset into the code_items_[] array. For effiency, we will "export" the
+ * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC
+ * to convert to a dex pc when needed.
+ */
+.macro EXPORT_PC
+ movq rPC, OFF_FP_DEX_PC_PTR(rFP)
+.endm
+
+/*
+ * Refresh handler table.
+ * IBase handles uses the caller save register so we must restore it after each call.
+ * Also it is used as a result of some 64-bit operations (like imul) and we should
+ * restore it in such cases also.
+ *
+ */
+.macro REFRESH_IBASE
+ movq THREAD_CURRENT_IBASE_OFFSET(rSELF), rIBASE
+.endm
+
+/*
+ * Refresh rINST.
+ * At enter to handler rINST does not contain the opcode number.
+ * However some utilities require the full value, so this macro
+ * restores the opcode number.
+ */
+.macro REFRESH_INST _opnum
+ movb rINSTbl, rINSTbh
+ movb $\_opnum, rINSTbl
+.endm
+
+/*
+ * Fetch the next instruction from rPC into rINSTw. Does not advance rPC.
+ */
+.macro FETCH_INST
+ movzwq (rPC), rINSTq
+.endm
+
+/*
+ * Remove opcode from rINST, compute the address of handler and jump to it.
+ */
+.macro GOTO_NEXT
+ movzx rINSTbl,%eax
+ movzbl rINSTbh,rINST
+ shll MACRO_LITERAL(7), %eax
+ addq rIBASE, %rax
+ jmp *%rax
+.endm
+
+/*
+ * Advance rPC by instruction count.
+ */
+.macro ADVANCE_PC _count
+ leaq 2*\_count(rPC), rPC
+.endm
+
+/*
+ * Advance rPC by instruction count, fetch instruction and jump to handler.
+ */
+.macro ADVANCE_PC_FETCH_AND_GOTO_NEXT _count
+ ADVANCE_PC \_count
+ FETCH_INST
+ GOTO_NEXT
+.endm
+
+/*
+ * Get/set the 32-bit value from a Dalvik register.
+ */
+#define VREG_ADDRESS(_vreg) (rFP,_vreg,4)
+#define VREG_REF_ADDRESS(_vreg) (rREFS,_vreg,4)
+
+.macro GET_VREG _reg _vreg
+ movl (rFP,\_vreg,4), \_reg
+.endm
+
+/* Read wide value. */
+.macro GET_WIDE_VREG _reg _vreg
+ movq (rFP,\_vreg,4), \_reg
+.endm
+
+.macro SET_VREG _reg _vreg
+ movl \_reg, (rFP,\_vreg,4)
+ movl MACRO_LITERAL(0), (rREFS,\_vreg,4)
+.endm
+
+/* Write wide value. reg is clobbered. */
+.macro SET_WIDE_VREG _reg _vreg
+ movq \_reg, (rFP,\_vreg,4)
+ xorq \_reg, \_reg
+ movq \_reg, (rREFS,\_vreg,4)
+.endm
+
+.macro SET_VREG_OBJECT _reg _vreg
+ movl \_reg, (rFP,\_vreg,4)
+ movl \_reg, (rREFS,\_vreg,4)
+.endm
+
+.macro GET_VREG_HIGH _reg _vreg
+ movl 4(rFP,\_vreg,4), \_reg
+.endm
+
+.macro SET_VREG_HIGH _reg _vreg
+ movl \_reg, 4(rFP,\_vreg,4)
+ movl MACRO_LITERAL(0), 4(rREFS,\_vreg,4)
+.endm
+
+.macro CLEAR_REF _vreg
+ movl MACRO_LITERAL(0), (rREFS,\_vreg,4)
+.endm
+
+.macro CLEAR_WIDE_REF _vreg
+ movl MACRO_LITERAL(0), (rREFS,\_vreg,4)
+ movl MACRO_LITERAL(0), 4(rREFS,\_vreg,4)
+.endm
+
+/* File: x86_64/entry.S */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Interpreter entry point.
+ */
+
+ .text
+ .global SYMBOL(ExecuteMterpImpl)
+ FUNCTION_TYPE(ExecuteMterpImpl)
+
+/*
+ * On entry:
+ * 0 Thread* self
+ * 1 code_item
+ * 2 ShadowFrame
+ * 3 JValue* result_register
+ *
+ */
+
+SYMBOL(ExecuteMterpImpl):
+ .cfi_startproc
+ .cfi_def_cfa rsp, 8
+
+ /* Spill callee save regs */
+ PUSH %rbx
+ PUSH %rbp
+ PUSH %r12
+ PUSH %r13
+ PUSH %r14
+ PUSH %r15
+
+ /* Allocate frame */
+ subq $FRAME_SIZE, %rsp
+ .cfi_adjust_cfa_offset FRAME_SIZE
+
+ /* Remember the return register */
+ movq IN_ARG3, SHADOWFRAME_RESULT_REGISTER_OFFSET(IN_ARG2)
+
+ /* Remember the code_item */
+ movq IN_ARG1, SHADOWFRAME_CODE_ITEM_OFFSET(IN_ARG2)
+
+ /* set up "named" registers */
+ movl SHADOWFRAME_NUMBER_OF_VREGS_OFFSET(IN_ARG2), %eax
+ leaq SHADOWFRAME_VREGS_OFFSET(IN_ARG2), rFP
+ leaq (rFP, %rax, 4), rREFS
+ movl SHADOWFRAME_DEX_PC_OFFSET(IN_ARG2), %eax
+ leaq CODEITEM_INSNS_OFFSET(IN_ARG1), rPC
+ leaq (rPC, %rax, 2), rPC
+ EXPORT_PC
+
+ /* Starting ibase */
+ movq IN_ARG0, rSELF
+ REFRESH_IBASE
+
+ /* start executing the instruction at rPC */
+ FETCH_INST
+ GOTO_NEXT
+ /* NOTE: no fallthrough */
+
+
+ .global SYMBOL(artMterpAsmInstructionStart)
+ FUNCTION_TYPE(SYMBOL(artMterpAsmInstructionStart))
+SYMBOL(artMterpAsmInstructionStart) = .L_op_nop
+ .text
+
+/* ------------------------------ */
+ .balign 128
+.L_op_nop: /* 0x00 */
+/* File: x86_64/op_nop.S */
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move: /* 0x01 */
+/* File: x86_64/op_move.S */
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ movl rINST, %eax # eax <- BA
+ andb $0xf, %al # eax <- A
+ shrl $4, rINST # rINST <- B
+ GET_VREG %edx, rINSTq
+ .if 0
+ SET_VREG_OBJECT %edx, %rax # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, %rax # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_from16: /* 0x02 */
+/* File: x86_64/op_move_from16.S */
+ /* for: move/from16, move-object/from16 */
+ /* op vAA, vBBBB */
+ movzwq 2(rPC), %rax # eax <- BBBB
+ GET_VREG %edx, %rax # edx <- fp[BBBB]
+ .if 0
+ SET_VREG_OBJECT %edx, rINSTq # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, rINSTq # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_16: /* 0x03 */
+/* File: x86_64/op_move_16.S */
+ /* for: move/16, move-object/16 */
+ /* op vAAAA, vBBBB */
+ movzwq 4(rPC), %rcx # ecx <- BBBB
+ movzwq 2(rPC), %rax # eax <- AAAA
+ GET_VREG %edx, %rcx
+ .if 0
+ SET_VREG_OBJECT %edx, %rax # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, %rax # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_wide: /* 0x04 */
+/* File: x86_64/op_move_wide.S */
+ /* move-wide vA, vB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ movl rINST, %ecx # ecx <- BA
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rdx, rINSTq # rdx <- v[B]
+ SET_WIDE_VREG %rdx, %rcx # v[A] <- rdx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_wide_from16: /* 0x05 */
+/* File: x86_64/op_move_wide_from16.S */
+ /* move-wide/from16 vAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ movzwl 2(rPC), %ecx # ecx <- BBBB
+ GET_WIDE_VREG %rdx, %rcx # rdx <- v[B]
+ SET_WIDE_VREG %rdx, rINSTq # v[A] <- rdx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_wide_16: /* 0x06 */
+/* File: x86_64/op_move_wide_16.S */
+ /* move-wide/16 vAAAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ movzwq 4(rPC), %rcx # ecx<- BBBB
+ movzwq 2(rPC), %rax # eax<- AAAA
+ GET_WIDE_VREG %rdx, %rcx # rdx <- v[B]
+ SET_WIDE_VREG %rdx, %rax # v[A] <- rdx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_object: /* 0x07 */
+/* File: x86_64/op_move_object.S */
+/* File: x86_64/op_move.S */
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ movl rINST, %eax # eax <- BA
+ andb $0xf, %al # eax <- A
+ shrl $4, rINST # rINST <- B
+ GET_VREG %edx, rINSTq
+ .if 1
+ SET_VREG_OBJECT %edx, %rax # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, %rax # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_object_from16: /* 0x08 */
+/* File: x86_64/op_move_object_from16.S */
+/* File: x86_64/op_move_from16.S */
+ /* for: move/from16, move-object/from16 */
+ /* op vAA, vBBBB */
+ movzwq 2(rPC), %rax # eax <- BBBB
+ GET_VREG %edx, %rax # edx <- fp[BBBB]
+ .if 1
+ SET_VREG_OBJECT %edx, rINSTq # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, rINSTq # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_object_16: /* 0x09 */
+/* File: x86_64/op_move_object_16.S */
+/* File: x86_64/op_move_16.S */
+ /* for: move/16, move-object/16 */
+ /* op vAAAA, vBBBB */
+ movzwq 4(rPC), %rcx # ecx <- BBBB
+ movzwq 2(rPC), %rax # eax <- AAAA
+ GET_VREG %edx, %rcx
+ .if 1
+ SET_VREG_OBJECT %edx, %rax # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, %rax # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_result: /* 0x0a */
+/* File: x86_64/op_move_result.S */
+ /* for: move-result, move-result-object */
+ /* op vAA */
+ movq OFF_FP_RESULT_REGISTER(rFP), %rax # get pointer to result JType.
+ movl (%rax), %eax # r0 <- result.i.
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- fp[B]
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_result_wide: /* 0x0b */
+/* File: x86_64/op_move_result_wide.S */
+ /* move-result-wide vAA */
+ movq OFF_FP_RESULT_REGISTER(rFP), %rax # get pointer to result JType.
+ movq (%rax), %rdx # Get wide
+ SET_WIDE_VREG %rdx, rINSTq # v[AA] <- rdx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_result_object: /* 0x0c */
+/* File: x86_64/op_move_result_object.S */
+/* File: x86_64/op_move_result.S */
+ /* for: move-result, move-result-object */
+ /* op vAA */
+ movq OFF_FP_RESULT_REGISTER(rFP), %rax # get pointer to result JType.
+ movl (%rax), %eax # r0 <- result.i.
+ .if 1
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- fp[B]
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_move_exception: /* 0x0d */
+/* File: x86_64/op_move_exception.S */
+ /* move-exception vAA */
+ movl THREAD_EXCEPTION_OFFSET(rSELF), %eax
+ SET_VREG_OBJECT %eax, rINSTq # fp[AA] <- exception object
+ movl $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_void: /* 0x0e */
+/* File: x86_64/op_return_void.S */
+ .extern MterpThreadFenceForConstructor
+ call SYMBOL(MterpThreadFenceForConstructor)
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ xorq %rax, %rax
+ jmp MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return: /* 0x0f */
+/* File: x86_64/op_return.S */
+/*
+ * Return a 32-bit value.
+ *
+ * for: return, return-object
+ */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ call SYMBOL(MterpThreadFenceForConstructor)
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ GET_VREG %eax, rINSTq # eax <- vAA
+ jmp MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_wide: /* 0x10 */
+/* File: x86_64/op_return_wide.S */
+/*
+ * Return a 64-bit value.
+ */
+ /* return-wide vAA */
+ .extern MterpThreadFenceForConstructor
+ call SYMBOL(MterpThreadFenceForConstructor)
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ GET_WIDE_VREG %rax, rINSTq # eax <- v[AA]
+ jmp MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_object: /* 0x11 */
+/* File: x86_64/op_return_object.S */
+/* File: x86_64/op_return.S */
+/*
+ * Return a 32-bit value.
+ *
+ * for: return, return-object
+ */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ call SYMBOL(MterpThreadFenceForConstructor)
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ GET_VREG %eax, rINSTq # eax <- vAA
+ jmp MterpReturn
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_4: /* 0x12 */
+/* File: x86_64/op_const_4.S */
+ /* const/4 vA, #+B */
+ movsbl rINSTbl, %eax # eax <-ssssssBx
+ movl $0xf, rINST
+ andl %eax, rINST # rINST <- A
+ sarl $4, %eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_16: /* 0x13 */
+/* File: x86_64/op_const_16.S */
+ /* const/16 vAA, #+BBBB */
+ movswl 2(rPC), %ecx # ecx <- ssssBBBB
+ SET_VREG %ecx, rINSTq # vAA <- ssssBBBB
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const: /* 0x14 */
+/* File: x86_64/op_const.S */
+ /* const vAA, #+BBBBbbbb */
+ movl 2(rPC), %eax # grab all 32 bits at once
+ SET_VREG %eax, rINSTq # vAA<- eax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_high16: /* 0x15 */
+/* File: x86_64/op_const_high16.S */
+ /* const/high16 vAA, #+BBBB0000 */
+ movzwl 2(rPC), %eax # eax <- 0000BBBB
+ sall $16, %eax # eax <- BBBB0000
+ SET_VREG %eax, rINSTq # vAA <- eax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide_16: /* 0x16 */
+/* File: x86_64/op_const_wide_16.S */
+ /* const-wide/16 vAA, #+BBBB */
+ movswq 2(rPC), %rax # rax <- ssssBBBB
+ SET_WIDE_VREG %rax, rINSTq # store
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide_32: /* 0x17 */
+/* File: x86_64/op_const_wide_32.S */
+ /* const-wide/32 vAA, #+BBBBbbbb */
+ movslq 2(rPC), %rax # eax <- ssssssssBBBBbbbb
+ SET_WIDE_VREG %rax, rINSTq # store
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide: /* 0x18 */
+/* File: x86_64/op_const_wide.S */
+ /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
+ movq 2(rPC), %rax # rax <- HHHHhhhhBBBBbbbb
+ SET_WIDE_VREG %rax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 5
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_wide_high16: /* 0x19 */
+/* File: x86_64/op_const_wide_high16.S */
+ /* const-wide/high16 vAA, #+BBBB000000000000 */
+ movzwq 2(rPC), %rax # eax <- 0000BBBB
+ salq $48, %rax # eax <- BBBB0000
+ SET_WIDE_VREG %rax, rINSTq # v[AA+0] <- eax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_string: /* 0x1a */
+/* File: x86_64/op_const_string.S */
+ /* const/string vAA, String@BBBB */
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # OUT_ARG0 <- BBBB
+ movq rINSTq, OUT_ARG1
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpConstString) # (index, tgt_reg, shadow_frame, self)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_string_jumbo: /* 0x1b */
+/* File: x86_64/op_const_string_jumbo.S */
+ /* const/string vAA, String@BBBBBBBB */
+ EXPORT_PC
+ movl 2(rPC), OUT_32_ARG0 # OUT_32_ARG0 <- BBBB
+ movq rINSTq, OUT_ARG1
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpConstString) # (index, tgt_reg, shadow_frame, self)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+/* ------------------------------ */
+ .balign 128
+.L_op_const_class: /* 0x1c */
+/* File: x86_64/op_const_class.S */
+ /* const/class vAA, Class@BBBB */
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # eax <- OUT_ARG0
+ movq rINSTq, OUT_ARG1
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpConstClass) # (index, tgt_reg, shadow_frame, self)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_monitor_enter: /* 0x1d */
+/* File: x86_64/op_monitor_enter.S */
+/*
+ * Synchronize on an object.
+ */
+ /* monitor-enter vAA */
+ EXPORT_PC
+ GET_VREG OUT_32_ARG0, rINSTq
+ movq rSELF, OUT_ARG1
+ call SYMBOL(artLockObjectFromCode) # (object, self)
+ testq %rax, %rax
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_monitor_exit: /* 0x1e */
+/* File: x86_64/op_monitor_exit.S */
+/*
+ * Unlock an object.
+ *
+ * Exceptions that occur when unlocking a monitor need to appear as
+ * if they happened at the following instruction. See the Dalvik
+ * instruction spec.
+ */
+ /* monitor-exit vAA */
+ EXPORT_PC
+ GET_VREG OUT_32_ARG0, rINSTq
+ movq rSELF, OUT_ARG1
+ call SYMBOL(artUnlockObjectFromCode) # (object, self)
+ testq %rax, %rax
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_check_cast: /* 0x1f */
+/* File: x86_64/op_check_cast.S */
+/*
+ * Check to see if a cast from one class to another is allowed.
+ */
+ /* check-cast vAA, class@BBBB */
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # OUT_ARG0 <- BBBB
+ leaq VREG_ADDRESS(rINSTq), OUT_ARG1
+ movq OFF_FP_METHOD(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpCheckCast) # (index, &obj, method, self)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_instance_of: /* 0x20 */
+/* File: x86_64/op_instance_of.S */
+/*
+ * Check to see if an object reference is an instance of a class.
+ *
+ * Most common situation is a non-null object, being compared against
+ * an already-resolved class.
+ */
+ /* instance-of vA, vB, class@CCCC */
+ EXPORT_PC
+ movzwl 2(rPC), OUT_32_ARG0 # OUT_32_ARG0 <- CCCC
+ movl rINST, %eax # eax <- BA
+ sarl $4, %eax # eax <- B
+ leaq VREG_ADDRESS(%rax), OUT_ARG1 # Get object address
+ movq OFF_FP_METHOD(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpInstanceOf) # (index, &obj, method, self)
+ movsbl %al, %eax
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ andb $0xf, rINSTbl # rINSTbl <- A
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_array_length: /* 0x21 */
+/* File: x86_64/op_array_length.S */
+/*
+ * Return the length of an array.
+ */
+ movl rINST, %eax # eax <- BA
+ sarl $4, rINST # rINST <- B
+ GET_VREG %ecx, rINSTq # ecx <- vB (object ref)
+ testl %ecx, %ecx # is null?
+ je common_errNullObject
+ andb $0xf, %al # eax <- A
+ movl MIRROR_ARRAY_LENGTH_OFFSET(%rcx), rINST
+ SET_VREG rINST, %rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_new_instance: /* 0x22 */
+/* File: x86_64/op_new_instance.S */
+/*
+ * Create a new instance of a class.
+ */
+ /* new-instance vAA, class@BBBB */
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rSELF, OUT_ARG1
+ REFRESH_INST 34
+ movq rINSTq, OUT_ARG2
+ call SYMBOL(MterpNewInstance)
+ testb %al, %al # 0 means an exception is thrown
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_new_array: /* 0x23 */
+/* File: x86_64/op_new_array.S */
+/*
+ * Allocate an array of objects, specified with the array class
+ * and a count.
+ *
+ * The verifier guarantees that this is an array class, so we don't
+ * check for it here.
+ */
+ /* new-array vA, vB, class@CCCC */
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST 35
+ movq rINSTq, OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpNewArray)
+ testb %al, %al # 0 means an exception is thrown
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_filled_new_array: /* 0x24 */
+/* File: x86_64/op_filled_new_array.S */
+/*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
+ .extern MterpFilledNewArray
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ movq rSELF, OUT_ARG2
+ call SYMBOL(MterpFilledNewArray)
+ testb %al, %al # 0 means an exception is thrown
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+/* ------------------------------ */
+ .balign 128
+.L_op_filled_new_array_range: /* 0x25 */
+/* File: x86_64/op_filled_new_array_range.S */
+/* File: x86_64/op_filled_new_array.S */
+/*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
+ .extern MterpFilledNewArrayRange
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ movq rSELF, OUT_ARG2
+ call SYMBOL(MterpFilledNewArrayRange)
+ testb %al, %al # 0 means an exception is thrown
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_fill_array_data: /* 0x26 */
+/* File: x86_64/op_fill_array_data.S */
+ /* fill-array-data vAA, +BBBBBBBB */
+ EXPORT_PC
+ movl 2(rPC), %ecx # ecx <- BBBBbbbb
+ leaq (rPC,%rcx,2), OUT_ARG1 # OUT_ARG1 <- PC + BBBBbbbb*2
+ GET_VREG OUT_32_ARG0, rINSTq # OUT_ARG0 <- vAA (array object)
+ call SYMBOL(MterpFillArrayData) # (obj, payload)
+ testb %al, %al # 0 means an exception is thrown
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
+
+/* ------------------------------ */
+ .balign 128
+.L_op_throw: /* 0x27 */
+/* File: x86_64/op_throw.S */
+/*
+ * Throw an exception object in the current thread.
+ */
+ /* throw vAA */
+ EXPORT_PC
+ GET_VREG %eax, rINSTq # eax<- vAA (exception object)
+ testb %al, %al
+ jz common_errNullObject
+ movq %rax, THREAD_EXCEPTION_OFFSET(rSELF)
+ jmp MterpException
+
+/* ------------------------------ */
+ .balign 128
+.L_op_goto: /* 0x28 */
+/* File: x86_64/op_goto.S */
+/*
+ * Unconditional branch, 8-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto +AA */
+ movsbq rINSTbl, rINSTq # rINSTq <- ssssssAA
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+/* ------------------------------ */
+ .balign 128
+.L_op_goto_16: /* 0x29 */
+/* File: x86_64/op_goto_16.S */
+/*
+ * Unconditional branch, 16-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto/16 +AAAA */
+ movswq 2(rPC), rINSTq # rINSTq <- ssssAAAA
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+/* ------------------------------ */
+ .balign 128
+.L_op_goto_32: /* 0x2a */
+/* File: x86_64/op_goto_32.S */
+/*
+ * Unconditional branch, 32-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ *
+ * Because we need the SF bit set, we'll use an adds
+ * to convert from Dalvik offset to byte offset.
+ */
+ /* goto/32 +AAAAAAAA */
+ movslq 2(rPC), rINSTq # rINSTq <- AAAAAAAA
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+/* ------------------------------ */
+ .balign 128
+.L_op_packed_switch: /* 0x2b */
+/* File: x86_64/op_packed_switch.S */
+/*
+ * Handle a packed-switch or sparse-switch instruction. In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+ /* op vAA, +BBBB */
+ movslq 2(rPC), OUT_ARG0 # rcx <- BBBBbbbb
+ leaq (rPC,OUT_ARG0,2), OUT_ARG0 # rcx <- PC + BBBBbbbb*2
+ GET_VREG OUT_32_ARG1, rINSTq # eax <- vAA
+ call SYMBOL(MterpDoPackedSwitch)
+ movslq %eax, rINSTq
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue
+ GOTO_NEXT
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sparse_switch: /* 0x2c */
+/* File: x86_64/op_sparse_switch.S */
+/* File: x86_64/op_packed_switch.S */
+/*
+ * Handle a packed-switch or sparse-switch instruction. In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+ /* op vAA, +BBBB */
+ movslq 2(rPC), OUT_ARG0 # rcx <- BBBBbbbb
+ leaq (rPC,OUT_ARG0,2), OUT_ARG0 # rcx <- PC + BBBBbbbb*2
+ GET_VREG OUT_32_ARG1, rINSTq # eax <- vAA
+ call SYMBOL(MterpDoSparseSwitch)
+ movslq %eax, rINSTq
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpl_float: /* 0x2d */
+/* File: x86_64/op_cmpl_float.S */
+/* File: x86_64/fpcmp.S */
+/*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * int compare(x, y) {
+ * if (x == y) {
+ * return 0;
+ * } else if (x < y) {
+ * return -1;
+ * } else if (x > y) {
+ * return 1;
+ * } else {
+ * return nanval ? 1 : -1;
+ * }
+ * }
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 3(rPC), %rcx # ecx<- CC
+ movzbq 2(rPC), %rax # eax<- BB
+ movss VREG_ADDRESS(%rax), %xmm0
+ xor %eax, %eax
+ ucomiss VREG_ADDRESS(%rcx), %xmm0
+ jp .Lop_cmpl_float_nan_is_neg
+ je .Lop_cmpl_float_finish
+ jb .Lop_cmpl_float_less
+.Lop_cmpl_float_nan_is_pos:
+ addb $1, %al
+ jmp .Lop_cmpl_float_finish
+.Lop_cmpl_float_nan_is_neg:
+.Lop_cmpl_float_less:
+ movl $-1, %eax
+.Lop_cmpl_float_finish:
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpg_float: /* 0x2e */
+/* File: x86_64/op_cmpg_float.S */
+/* File: x86_64/fpcmp.S */
+/*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * int compare(x, y) {
+ * if (x == y) {
+ * return 0;
+ * } else if (x < y) {
+ * return -1;
+ * } else if (x > y) {
+ * return 1;
+ * } else {
+ * return nanval ? 1 : -1;
+ * }
+ * }
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 3(rPC), %rcx # ecx<- CC
+ movzbq 2(rPC), %rax # eax<- BB
+ movss VREG_ADDRESS(%rax), %xmm0
+ xor %eax, %eax
+ ucomiss VREG_ADDRESS(%rcx), %xmm0
+ jp .Lop_cmpg_float_nan_is_pos
+ je .Lop_cmpg_float_finish
+ jb .Lop_cmpg_float_less
+.Lop_cmpg_float_nan_is_pos:
+ addb $1, %al
+ jmp .Lop_cmpg_float_finish
+.Lop_cmpg_float_nan_is_neg:
+.Lop_cmpg_float_less:
+ movl $-1, %eax
+.Lop_cmpg_float_finish:
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpl_double: /* 0x2f */
+/* File: x86_64/op_cmpl_double.S */
+/* File: x86_64/fpcmp.S */
+/*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * int compare(x, y) {
+ * if (x == y) {
+ * return 0;
+ * } else if (x < y) {
+ * return -1;
+ * } else if (x > y) {
+ * return 1;
+ * } else {
+ * return nanval ? 1 : -1;
+ * }
+ * }
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 3(rPC), %rcx # ecx<- CC
+ movzbq 2(rPC), %rax # eax<- BB
+ movsd VREG_ADDRESS(%rax), %xmm0
+ xor %eax, %eax
+ ucomisd VREG_ADDRESS(%rcx), %xmm0
+ jp .Lop_cmpl_double_nan_is_neg
+ je .Lop_cmpl_double_finish
+ jb .Lop_cmpl_double_less
+.Lop_cmpl_double_nan_is_pos:
+ addb $1, %al
+ jmp .Lop_cmpl_double_finish
+.Lop_cmpl_double_nan_is_neg:
+.Lop_cmpl_double_less:
+ movl $-1, %eax
+.Lop_cmpl_double_finish:
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmpg_double: /* 0x30 */
+/* File: x86_64/op_cmpg_double.S */
+/* File: x86_64/fpcmp.S */
+/*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * int compare(x, y) {
+ * if (x == y) {
+ * return 0;
+ * } else if (x < y) {
+ * return -1;
+ * } else if (x > y) {
+ * return 1;
+ * } else {
+ * return nanval ? 1 : -1;
+ * }
+ * }
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 3(rPC), %rcx # ecx<- CC
+ movzbq 2(rPC), %rax # eax<- BB
+ movsd VREG_ADDRESS(%rax), %xmm0
+ xor %eax, %eax
+ ucomisd VREG_ADDRESS(%rcx), %xmm0
+ jp .Lop_cmpg_double_nan_is_pos
+ je .Lop_cmpg_double_finish
+ jb .Lop_cmpg_double_less
+.Lop_cmpg_double_nan_is_pos:
+ addb $1, %al
+ jmp .Lop_cmpg_double_finish
+.Lop_cmpg_double_nan_is_neg:
+.Lop_cmpg_double_less:
+ movl $-1, %eax
+.Lop_cmpg_double_finish:
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_cmp_long: /* 0x31 */
+/* File: x86_64/op_cmp_long.S */
+/*
+ * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
+ * register based on the results of the comparison.
+ */
+ /* cmp-long vAA, vBB, vCC */
+ movzbq 2(rPC), %rdx # edx <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_WIDE_VREG %rdx, %rdx # rdx <- v[BB]
+ xorl %eax, %eax
+ xorl %edi, %edi
+ addb $1, %al
+ movl $-1, %esi
+ cmpq VREG_ADDRESS(%rcx), %rdx
+ cmovl %esi, %edi
+ cmovg %eax, %edi
+ SET_VREG %edi, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_eq: /* 0x32 */
+/* File: x86_64/op_if_eq.S */
+/* File: x86_64/bincmp.S */
+/*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # rcx <- A
+ GET_VREG %eax, %rcx # eax <- vA
+ cmpl VREG_ADDRESS(rINSTq), %eax # compare (vA, vB)
+ movl $2, rINST # assume not taken
+ jne 1f
+ movswq 2(rPC), rINSTq # Get signed branch offset
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rax <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_ne: /* 0x33 */
+/* File: x86_64/op_if_ne.S */
+/* File: x86_64/bincmp.S */
+/*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # rcx <- A
+ GET_VREG %eax, %rcx # eax <- vA
+ cmpl VREG_ADDRESS(rINSTq), %eax # compare (vA, vB)
+ movl $2, rINST # assume not taken
+ je 1f
+ movswq 2(rPC), rINSTq # Get signed branch offset
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rax <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_lt: /* 0x34 */
+/* File: x86_64/op_if_lt.S */
+/* File: x86_64/bincmp.S */
+/*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # rcx <- A
+ GET_VREG %eax, %rcx # eax <- vA
+ cmpl VREG_ADDRESS(rINSTq), %eax # compare (vA, vB)
+ movl $2, rINST # assume not taken
+ jge 1f
+ movswq 2(rPC), rINSTq # Get signed branch offset
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rax <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_ge: /* 0x35 */
+/* File: x86_64/op_if_ge.S */
+/* File: x86_64/bincmp.S */
+/*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # rcx <- A
+ GET_VREG %eax, %rcx # eax <- vA
+ cmpl VREG_ADDRESS(rINSTq), %eax # compare (vA, vB)
+ movl $2, rINST # assume not taken
+ jl 1f
+ movswq 2(rPC), rINSTq # Get signed branch offset
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rax <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_gt: /* 0x36 */
+/* File: x86_64/op_if_gt.S */
+/* File: x86_64/bincmp.S */
+/*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # rcx <- A
+ GET_VREG %eax, %rcx # eax <- vA
+ cmpl VREG_ADDRESS(rINSTq), %eax # compare (vA, vB)
+ movl $2, rINST # assume not taken
+ jle 1f
+ movswq 2(rPC), rINSTq # Get signed branch offset
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rax <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_le: /* 0x37 */
+/* File: x86_64/op_if_le.S */
+/* File: x86_64/bincmp.S */
+/*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # rcx <- A
+ GET_VREG %eax, %rcx # eax <- vA
+ cmpl VREG_ADDRESS(rINSTq), %eax # compare (vA, vB)
+ movl $2, rINST # assume not taken
+ jg 1f
+ movswq 2(rPC), rINSTq # Get signed branch offset
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rax <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_eqz: /* 0x38 */
+/* File: x86_64/op_if_eqz.S */
+/* File: x86_64/zcmp.S */
+/*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ cmpl $0, VREG_ADDRESS(rINSTq) # compare (vA, 0)
+ movl $2, rINST # assume branch not taken
+ jne 1f
+ movswq 2(rPC), rINSTq # fetch signed displacement
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_nez: /* 0x39 */
+/* File: x86_64/op_if_nez.S */
+/* File: x86_64/zcmp.S */
+/*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ cmpl $0, VREG_ADDRESS(rINSTq) # compare (vA, 0)
+ movl $2, rINST # assume branch not taken
+ je 1f
+ movswq 2(rPC), rINSTq # fetch signed displacement
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_ltz: /* 0x3a */
+/* File: x86_64/op_if_ltz.S */
+/* File: x86_64/zcmp.S */
+/*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ cmpl $0, VREG_ADDRESS(rINSTq) # compare (vA, 0)
+ movl $2, rINST # assume branch not taken
+ jge 1f
+ movswq 2(rPC), rINSTq # fetch signed displacement
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_gez: /* 0x3b */
+/* File: x86_64/op_if_gez.S */
+/* File: x86_64/zcmp.S */
+/*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ cmpl $0, VREG_ADDRESS(rINSTq) # compare (vA, 0)
+ movl $2, rINST # assume branch not taken
+ jl 1f
+ movswq 2(rPC), rINSTq # fetch signed displacement
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_gtz: /* 0x3c */
+/* File: x86_64/op_if_gtz.S */
+/* File: x86_64/zcmp.S */
+/*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ cmpl $0, VREG_ADDRESS(rINSTq) # compare (vA, 0)
+ movl $2, rINST # assume branch not taken
+ jle 1f
+ movswq 2(rPC), rINSTq # fetch signed displacement
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_if_lez: /* 0x3d */
+/* File: x86_64/op_if_lez.S */
+/* File: x86_64/zcmp.S */
+/*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ cmpl $0, VREG_ADDRESS(rINSTq) # compare (vA, 0)
+ movl $2, rINST # assume branch not taken
+ jg 1f
+ movswq 2(rPC), rINSTq # fetch signed displacement
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_3e: /* 0x3e */
+/* File: x86_64/op_unused_3e.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_3f: /* 0x3f */
+/* File: x86_64/op_unused_3f.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_40: /* 0x40 */
+/* File: x86_64/op_unused_40.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_41: /* 0x41 */
+/* File: x86_64/op_unused_41.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_42: /* 0x42 */
+/* File: x86_64/op_unused_42.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_43: /* 0x43 */
+/* File: x86_64/op_unused_43.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget: /* 0x44 */
+/* File: x86_64/op_aget.S */
+/*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ movq MIRROR_INT_ARRAY_DATA_OFFSET(%rax,%rcx,8), %rax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ movl MIRROR_INT_ARRAY_DATA_OFFSET(%rax,%rcx,4), %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_wide: /* 0x45 */
+/* File: x86_64/op_aget_wide.S */
+/* File: x86_64/op_aget.S */
+/*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 1
+ movq MIRROR_WIDE_ARRAY_DATA_OFFSET(%rax,%rcx,8), %rax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ movq MIRROR_WIDE_ARRAY_DATA_OFFSET(%rax,%rcx,8), %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_object: /* 0x46 */
+/* File: x86_64/op_aget_object.S */
+/*
+ * Array object get. vAA <- vBB[vCC].
+ *
+ * for: aget-object
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG OUT_32_ARG0, %rax # eax <- vBB (array object)
+ GET_VREG OUT_32_ARG1, %rcx # ecx <- vCC (requested index)
+ EXPORT_PC
+ call SYMBOL(artAGetObjectFromMterp) # (array, index)
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ SET_VREG_OBJECT %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_boolean: /* 0x47 */
+/* File: x86_64/op_aget_boolean.S */
+/* File: x86_64/op_aget.S */
+/*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ movq MIRROR_BOOLEAN_ARRAY_DATA_OFFSET(%rax,%rcx,8), %rax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ movzbl MIRROR_BOOLEAN_ARRAY_DATA_OFFSET(%rax,%rcx,1), %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_byte: /* 0x48 */
+/* File: x86_64/op_aget_byte.S */
+/* File: x86_64/op_aget.S */
+/*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ movq MIRROR_BYTE_ARRAY_DATA_OFFSET(%rax,%rcx,8), %rax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ movsbl MIRROR_BYTE_ARRAY_DATA_OFFSET(%rax,%rcx,1), %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_char: /* 0x49 */
+/* File: x86_64/op_aget_char.S */
+/* File: x86_64/op_aget.S */
+/*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ movq MIRROR_CHAR_ARRAY_DATA_OFFSET(%rax,%rcx,8), %rax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ movzwl MIRROR_CHAR_ARRAY_DATA_OFFSET(%rax,%rcx,2), %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aget_short: /* 0x4a */
+/* File: x86_64/op_aget_short.S */
+/* File: x86_64/op_aget.S */
+/*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ movq MIRROR_SHORT_ARRAY_DATA_OFFSET(%rax,%rcx,8), %rax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ movswl MIRROR_SHORT_ARRAY_DATA_OFFSET(%rax,%rcx,2), %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput: /* 0x4b */
+/* File: x86_64/op_aput.S */
+/*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ GET_WIDE_VREG rINSTq, rINSTq
+ .else
+ GET_VREG rINST, rINSTq
+ .endif
+ movl rINST, MIRROR_INT_ARRAY_DATA_OFFSET(%rax,%rcx,4)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_wide: /* 0x4c */
+/* File: x86_64/op_aput_wide.S */
+/* File: x86_64/op_aput.S */
+/*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 1
+ GET_WIDE_VREG rINSTq, rINSTq
+ .else
+ GET_VREG rINST, rINSTq
+ .endif
+ movq rINSTq, MIRROR_WIDE_ARRAY_DATA_OFFSET(%rax,%rcx,8)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_object: /* 0x4d */
+/* File: x86_64/op_aput_object.S */
+/*
+ * Store an object into an array. vBB[vCC] <- vAA.
+ */
+ /* op vAA, vBB, vCC */
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST 77
+ movq rINSTq, OUT_ARG2
+ call SYMBOL(MterpAputObject) # (array, index)
+ testb %al, %al
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_boolean: /* 0x4e */
+/* File: x86_64/op_aput_boolean.S */
+/* File: x86_64/op_aput.S */
+/*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ GET_WIDE_VREG rINSTq, rINSTq
+ .else
+ GET_VREG rINST, rINSTq
+ .endif
+ movb rINSTbl, MIRROR_BOOLEAN_ARRAY_DATA_OFFSET(%rax,%rcx,1)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_byte: /* 0x4f */
+/* File: x86_64/op_aput_byte.S */
+/* File: x86_64/op_aput.S */
+/*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ GET_WIDE_VREG rINSTq, rINSTq
+ .else
+ GET_VREG rINST, rINSTq
+ .endif
+ movb rINSTbl, MIRROR_BYTE_ARRAY_DATA_OFFSET(%rax,%rcx,1)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_char: /* 0x50 */
+/* File: x86_64/op_aput_char.S */
+/* File: x86_64/op_aput.S */
+/*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ GET_WIDE_VREG rINSTq, rINSTq
+ .else
+ GET_VREG rINST, rINSTq
+ .endif
+ movw rINSTw, MIRROR_CHAR_ARRAY_DATA_OFFSET(%rax,%rcx,2)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_aput_short: /* 0x51 */
+/* File: x86_64/op_aput_short.S */
+/* File: x86_64/op_aput.S */
+/*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if 0
+ GET_WIDE_VREG rINSTq, rINSTq
+ .else
+ GET_VREG rINST, rINSTq
+ .endif
+ movw rINSTw, MIRROR_SHORT_ARRAY_DATA_OFFSET(%rax,%rcx,2)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget: /* 0x52 */
+/* File: x86_64/op_iget.S */
+/*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide
+ */
+ EXPORT_PC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC
+ sarl $4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3
+ call SYMBOL(artGet32InstanceFromCode)
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <-value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <-value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_wide: /* 0x53 */
+/* File: x86_64/op_iget_wide.S */
+/* File: x86_64/op_iget.S */
+/*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide
+ */
+ EXPORT_PC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC
+ sarl $4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3
+ call SYMBOL(artGet64InstanceFromCode)
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value
+ .else
+ .if 1
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <-value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <-value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_object: /* 0x54 */
+/* File: x86_64/op_iget_object.S */
+/* File: x86_64/op_iget.S */
+/*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide
+ */
+ EXPORT_PC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC
+ sarl $4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3
+ call SYMBOL(artGetObjInstanceFromCode)
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $0xf, rINSTbl # rINST <- A
+ .if 1
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <-value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <-value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_boolean: /* 0x55 */
+/* File: x86_64/op_iget_boolean.S */
+/* File: x86_64/op_iget.S */
+/*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide
+ */
+ EXPORT_PC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC
+ sarl $4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3
+ call SYMBOL(artGetBooleanInstanceFromCode)
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <-value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <-value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_byte: /* 0x56 */
+/* File: x86_64/op_iget_byte.S */
+/* File: x86_64/op_iget.S */
+/*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide
+ */
+ EXPORT_PC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC
+ sarl $4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3
+ call SYMBOL(artGetByteInstanceFromCode)
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <-value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <-value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_char: /* 0x57 */
+/* File: x86_64/op_iget_char.S */
+/* File: x86_64/op_iget.S */
+/*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide
+ */
+ EXPORT_PC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC
+ sarl $4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3
+ call SYMBOL(artGetCharInstanceFromCode)
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <-value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <-value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_short: /* 0x58 */
+/* File: x86_64/op_iget_short.S */
+/* File: x86_64/op_iget.S */
+/*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide
+ */
+ EXPORT_PC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC
+ sarl $4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3
+ call SYMBOL(artGetShortInstanceFromCode)
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <-value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <-value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput: /* 0x59 */
+/* File: x86_64/op_iput.S */
+/*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field@CCCC */
+ .extern artSet32InstanceFromMterp
+ EXPORT_PC
+ movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC
+ movzbq rINSTbl, %rcx # rcx<- BA
+ sarl $4, %ecx # ecx<- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ andb $0xf, rINSTbl # rINST<- A
+ GET_VREG OUT_32_ARG2, rINSTq # fp[A]
+ movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer
+ call SYMBOL(artSet32InstanceFromMterp)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_wide: /* 0x5a */
+/* File: x86_64/op_iput_wide.S */
+ /* iput-wide vA, vB, field@CCCC */
+ .extern artSet64InstanceFromMterp
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ andb $0xf, rINSTbl # rINST <- A
+ leaq VREG_ADDRESS(rINSTq), OUT_ARG2 # &fp[A]
+ movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer
+ call SYMBOL(artSet64InstanceFromMterp)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_object: /* 0x5b */
+/* File: x86_64/op_iput_object.S */
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST 91
+ movl rINST, OUT_32_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpIputObject)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_boolean: /* 0x5c */
+/* File: x86_64/op_iput_boolean.S */
+/* File: x86_64/op_iput.S */
+/*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field@CCCC */
+ .extern artSet8InstanceFromMterp
+ EXPORT_PC
+ movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC
+ movzbq rINSTbl, %rcx # rcx<- BA
+ sarl $4, %ecx # ecx<- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ andb $0xf, rINSTbl # rINST<- A
+ GET_VREG OUT_32_ARG2, rINSTq # fp[A]
+ movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer
+ call SYMBOL(artSet8InstanceFromMterp)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_byte: /* 0x5d */
+/* File: x86_64/op_iput_byte.S */
+/* File: x86_64/op_iput.S */
+/*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field@CCCC */
+ .extern artSet8InstanceFromMterp
+ EXPORT_PC
+ movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC
+ movzbq rINSTbl, %rcx # rcx<- BA
+ sarl $4, %ecx # ecx<- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ andb $0xf, rINSTbl # rINST<- A
+ GET_VREG OUT_32_ARG2, rINSTq # fp[A]
+ movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer
+ call SYMBOL(artSet8InstanceFromMterp)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_char: /* 0x5e */
+/* File: x86_64/op_iput_char.S */
+/* File: x86_64/op_iput.S */
+/*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field@CCCC */
+ .extern artSet16InstanceFromMterp
+ EXPORT_PC
+ movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC
+ movzbq rINSTbl, %rcx # rcx<- BA
+ sarl $4, %ecx # ecx<- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ andb $0xf, rINSTbl # rINST<- A
+ GET_VREG OUT_32_ARG2, rINSTq # fp[A]
+ movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer
+ call SYMBOL(artSet16InstanceFromMterp)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_short: /* 0x5f */
+/* File: x86_64/op_iput_short.S */
+/* File: x86_64/op_iput.S */
+/*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field@CCCC */
+ .extern artSet16InstanceFromMterp
+ EXPORT_PC
+ movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC
+ movzbq rINSTbl, %rcx # rcx<- BA
+ sarl $4, %ecx # ecx<- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ andb $0xf, rINSTbl # rINST<- A
+ GET_VREG OUT_32_ARG2, rINSTq # fp[A]
+ movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer
+ call SYMBOL(artSet16InstanceFromMterp)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget: /* 0x60 */
+/* File: x86_64/op_sget.S */
+/*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
+ */
+ /* op vAA, field@BBBB */
+ .extern artGet32StaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ movq rSELF, OUT_ARG2 # self
+ call SYMBOL(artGet32StaticFromCode)
+ cmpl $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_wide: /* 0x61 */
+/* File: x86_64/op_sget_wide.S */
+/* File: x86_64/op_sget.S */
+/*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
+ */
+ /* op vAA, field@BBBB */
+ .extern artGet64StaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ movq rSELF, OUT_ARG2 # self
+ call SYMBOL(artGet64StaticFromCode)
+ cmpl $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ .else
+ .if 1
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_object: /* 0x62 */
+/* File: x86_64/op_sget_object.S */
+/* File: x86_64/op_sget.S */
+/*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
+ */
+ /* op vAA, field@BBBB */
+ .extern artGetObjStaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ movq rSELF, OUT_ARG2 # self
+ call SYMBOL(artGetObjStaticFromCode)
+ cmpl $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ .if 1
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_boolean: /* 0x63 */
+/* File: x86_64/op_sget_boolean.S */
+/* File: x86_64/op_sget.S */
+/*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
+ */
+ /* op vAA, field@BBBB */
+ .extern artGetBooleanStaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ movq rSELF, OUT_ARG2 # self
+ call SYMBOL(artGetBooleanStaticFromCode)
+ cmpl $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_byte: /* 0x64 */
+/* File: x86_64/op_sget_byte.S */
+/* File: x86_64/op_sget.S */
+/*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
+ */
+ /* op vAA, field@BBBB */
+ .extern artGetByteStaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ movq rSELF, OUT_ARG2 # self
+ call SYMBOL(artGetByteStaticFromCode)
+ cmpl $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_char: /* 0x65 */
+/* File: x86_64/op_sget_char.S */
+/* File: x86_64/op_sget.S */
+/*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
+ */
+ /* op vAA, field@BBBB */
+ .extern artGetCharStaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ movq rSELF, OUT_ARG2 # self
+ call SYMBOL(artGetCharStaticFromCode)
+ cmpl $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sget_short: /* 0x66 */
+/* File: x86_64/op_sget_short.S */
+/* File: x86_64/op_sget.S */
+/*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
+ */
+ /* op vAA, field@BBBB */
+ .extern artGetShortStaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ movq rSELF, OUT_ARG2 # self
+ call SYMBOL(artGetShortStaticFromCode)
+ cmpl $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ .if 0
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ .else
+ .if 0
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput: /* 0x67 */
+/* File: x86_64/op_sput.S */
+/*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field@BBBB */
+ .extern artSet32StaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref BBBB
+ GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3 # self
+ call SYMBOL(artSet32StaticFromCode)
+ testb %al, %al
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_wide: /* 0x68 */
+/* File: x86_64/op_sput_wide.S */
+/*
+ * SPUT_WIDE handler wrapper.
+ *
+ */
+ /* sput-wide vAA, field@BBBB */
+ .extern artSet64IndirectStaticFromMterp
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref BBBB
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ leaq VREG_ADDRESS(rINSTq), OUT_ARG2 # &fp[AA]
+ movq rSELF, OUT_ARG3 # self
+ call SYMBOL(artSet64IndirectStaticFromMterp)
+ testb %al, %al
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_object: /* 0x69 */
+/* File: x86_64/op_sput_object.S */
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST 105
+ movq rINSTq, OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpSputObject)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_boolean: /* 0x6a */
+/* File: x86_64/op_sput_boolean.S */
+/* File: x86_64/op_sput.S */
+/*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field@BBBB */
+ .extern artSet8StaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref BBBB
+ GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3 # self
+ call SYMBOL(artSet8StaticFromCode)
+ testb %al, %al
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_byte: /* 0x6b */
+/* File: x86_64/op_sput_byte.S */
+/* File: x86_64/op_sput.S */
+/*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field@BBBB */
+ .extern artSet8StaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref BBBB
+ GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3 # self
+ call SYMBOL(artSet8StaticFromCode)
+ testb %al, %al
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_char: /* 0x6c */
+/* File: x86_64/op_sput_char.S */
+/* File: x86_64/op_sput.S */
+/*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field@BBBB */
+ .extern artSet16StaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref BBBB
+ GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3 # self
+ call SYMBOL(artSet16StaticFromCode)
+ testb %al, %al
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sput_short: /* 0x6d */
+/* File: x86_64/op_sput_short.S */
+/* File: x86_64/op_sput.S */
+/*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field@BBBB */
+ .extern artSet16StaticFromCode
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref BBBB
+ GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3 # self
+ call SYMBOL(artSet16StaticFromCode)
+ testb %al, %al
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual: /* 0x6e */
+/* File: x86_64/op_invoke_virtual.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeVirtual
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 110
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeVirtual)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+/*
+ * Handle a virtual method call.
+ *
+ * for: invoke-virtual, invoke-virtual/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_super: /* 0x6f */
+/* File: x86_64/op_invoke_super.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeSuper
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 111
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeSuper)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+/*
+ * Handle a "super" method call.
+ *
+ * for: invoke-super, invoke-super/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_direct: /* 0x70 */
+/* File: x86_64/op_invoke_direct.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeDirect
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 112
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeDirect)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_static: /* 0x71 */
+/* File: x86_64/op_invoke_static.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeStatic
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 113
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeStatic)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_interface: /* 0x72 */
+/* File: x86_64/op_invoke_interface.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeInterface
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 114
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeInterface)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+/*
+ * Handle an interface method call.
+ *
+ * for: invoke-interface, invoke-interface/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+
+/* ------------------------------ */
+ .balign 128
+.L_op_return_void_no_barrier: /* 0x73 */
+/* File: x86_64/op_return_void_no_barrier.S */
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ xorq %rax, %rax
+ jmp MterpReturn
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual_range: /* 0x74 */
+/* File: x86_64/op_invoke_virtual_range.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeVirtualRange
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 116
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeVirtualRange)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_super_range: /* 0x75 */
+/* File: x86_64/op_invoke_super_range.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeSuperRange
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 117
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeSuperRange)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_direct_range: /* 0x76 */
+/* File: x86_64/op_invoke_direct_range.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeDirectRange
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 118
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeDirectRange)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_static_range: /* 0x77 */
+/* File: x86_64/op_invoke_static_range.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeStaticRange
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 119
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeStaticRange)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_interface_range: /* 0x78 */
+/* File: x86_64/op_invoke_interface_range.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeInterfaceRange
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 120
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeInterfaceRange)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_79: /* 0x79 */
+/* File: x86_64/op_unused_79.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_7a: /* 0x7a */
+/* File: x86_64/op_unused_7a.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_int: /* 0x7b */
+/* File: x86_64/op_neg_int.S */
+/* File: x86_64/unop.S */
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4,rINST # rINST <- B
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $0xf,%cl # ecx <- A
+
+ negl %eax
+ .if 0
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_not_int: /* 0x7c */
+/* File: x86_64/op_not_int.S */
+/* File: x86_64/unop.S */
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4,rINST # rINST <- B
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $0xf,%cl # ecx <- A
+
+ notl %eax
+ .if 0
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_long: /* 0x7d */
+/* File: x86_64/op_neg_long.S */
+/* File: x86_64/unop.S */
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4,rINST # rINST <- B
+ .if 1
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $0xf,%cl # ecx <- A
+
+ negq %rax
+ .if 1
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_not_long: /* 0x7e */
+/* File: x86_64/op_not_long.S */
+/* File: x86_64/unop.S */
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4,rINST # rINST <- B
+ .if 1
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $0xf,%cl # ecx <- A
+
+ notq %rax
+ .if 1
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_float: /* 0x7f */
+/* File: x86_64/op_neg_float.S */
+/* File: x86_64/unop.S */
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4,rINST # rINST <- B
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $0xf,%cl # ecx <- A
+
+ xorl $0x80000000, %eax
+ .if 0
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_neg_double: /* 0x80 */
+/* File: x86_64/op_neg_double.S */
+/* File: x86_64/unop.S */
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4,rINST # rINST <- B
+ .if 1
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $0xf,%cl # ecx <- A
+ movq $0x8000000000000000, %rsi
+ xorq %rsi, %rax
+ .if 1
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_long: /* 0x81 */
+/* File: x86_64/op_int_to_long.S */
+ /* int to long vA, vB */
+ movzbq rINSTbl, %rax # rax <- +A
+ sarl $4, %eax # eax <- B
+ andb $0xf, rINSTbl # rINST <- A
+ movslq VREG_ADDRESS(%rax), %rax
+ SET_WIDE_VREG %rax, rINSTq # v[A] <- %rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_float: /* 0x82 */
+/* File: x86_64/op_int_to_float.S */
+/* File: x86_64/fpcvt.S */
+/*
+ * Generic 32-bit FP conversion operation.
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ cvtsi2ssl VREG_ADDRESS(rINSTq), %xmm0
+ .if 0
+ movsd %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_WIDE_REF %rcx
+ .else
+ movss %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_REF %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_double: /* 0x83 */
+/* File: x86_64/op_int_to_double.S */
+/* File: x86_64/fpcvt.S */
+/*
+ * Generic 32-bit FP conversion operation.
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ cvtsi2sdl VREG_ADDRESS(rINSTq), %xmm0
+ .if 1
+ movsd %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_WIDE_REF %rcx
+ .else
+ movss %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_REF %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_long_to_int: /* 0x84 */
+/* File: x86_64/op_long_to_int.S */
+/* we ignore the high word, making this equivalent to a 32-bit reg move */
+/* File: x86_64/op_move.S */
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ movl rINST, %eax # eax <- BA
+ andb $0xf, %al # eax <- A
+ shrl $4, rINST # rINST <- B
+ GET_VREG %edx, rINSTq
+ .if 0
+ SET_VREG_OBJECT %edx, %rax # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, %rax # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_long_to_float: /* 0x85 */
+/* File: x86_64/op_long_to_float.S */
+/* File: x86_64/fpcvt.S */
+/*
+ * Generic 32-bit FP conversion operation.
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ cvtsi2ssq VREG_ADDRESS(rINSTq), %xmm0
+ .if 0
+ movsd %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_WIDE_REF %rcx
+ .else
+ movss %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_REF %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_long_to_double: /* 0x86 */
+/* File: x86_64/op_long_to_double.S */
+/* File: x86_64/fpcvt.S */
+/*
+ * Generic 32-bit FP conversion operation.
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ cvtsi2sdq VREG_ADDRESS(rINSTq), %xmm0
+ .if 1
+ movsd %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_WIDE_REF %rcx
+ .else
+ movss %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_REF %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_float_to_int: /* 0x87 */
+/* File: x86_64/op_float_to_int.S */
+/* File: x86_64/cvtfp_int.S */
+/* On fp to int conversions, Java requires that
+ * if the result > maxint, it should be clamped to maxint. If it is less
+ * than minint, it should be clamped to minint. If it is a nan, the result
+ * should be zero. Further, the rounding mode is to truncate.
+ */
+ /* float/double to int/long vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ movss VREG_ADDRESS(rINSTq), %xmm0
+ movl $0x7fffffff, %eax
+ cvtsi2ssl %eax, %xmm1
+ comiss %xmm1, %xmm0
+ jae 1f
+ jp 2f
+ cvttss2sil %xmm0, %eax
+ jmp 1f
+2:
+ xorl %eax, %eax
+1:
+ .if 0
+ SET_WIDE_VREG %eax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_float_to_long: /* 0x88 */
+/* File: x86_64/op_float_to_long.S */
+/* File: x86_64/cvtfp_int.S */
+/* On fp to int conversions, Java requires that
+ * if the result > maxint, it should be clamped to maxint. If it is less
+ * than minint, it should be clamped to minint. If it is a nan, the result
+ * should be zero. Further, the rounding mode is to truncate.
+ */
+ /* float/double to int/long vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ movss VREG_ADDRESS(rINSTq), %xmm0
+ movq $0x7fffffffffffffff, %rax
+ cvtsi2ssq %rax, %xmm1
+ comiss %xmm1, %xmm0
+ jae 1f
+ jp 2f
+ cvttss2siq %xmm0, %rax
+ jmp 1f
+2:
+ xorq %rax, %rax
+1:
+ .if 1
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %rax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_float_to_double: /* 0x89 */
+/* File: x86_64/op_float_to_double.S */
+/* File: x86_64/fpcvt.S */
+/*
+ * Generic 32-bit FP conversion operation.
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ cvtss2sd VREG_ADDRESS(rINSTq), %xmm0
+ .if 1
+ movsd %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_WIDE_REF %rcx
+ .else
+ movss %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_REF %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_double_to_int: /* 0x8a */
+/* File: x86_64/op_double_to_int.S */
+/* File: x86_64/cvtfp_int.S */
+/* On fp to int conversions, Java requires that
+ * if the result > maxint, it should be clamped to maxint. If it is less
+ * than minint, it should be clamped to minint. If it is a nan, the result
+ * should be zero. Further, the rounding mode is to truncate.
+ */
+ /* float/double to int/long vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ movsd VREG_ADDRESS(rINSTq), %xmm0
+ movl $0x7fffffff, %eax
+ cvtsi2sdl %eax, %xmm1
+ comisd %xmm1, %xmm0
+ jae 1f
+ jp 2f
+ cvttsd2sil %xmm0, %eax
+ jmp 1f
+2:
+ xorl %eax, %eax
+1:
+ .if 0
+ SET_WIDE_VREG %eax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_double_to_long: /* 0x8b */
+/* File: x86_64/op_double_to_long.S */
+/* File: x86_64/cvtfp_int.S */
+/* On fp to int conversions, Java requires that
+ * if the result > maxint, it should be clamped to maxint. If it is less
+ * than minint, it should be clamped to minint. If it is a nan, the result
+ * should be zero. Further, the rounding mode is to truncate.
+ */
+ /* float/double to int/long vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ movsd VREG_ADDRESS(rINSTq), %xmm0
+ movq $0x7fffffffffffffff, %rax
+ cvtsi2sdq %rax, %xmm1
+ comisd %xmm1, %xmm0
+ jae 1f
+ jp 2f
+ cvttsd2siq %xmm0, %rax
+ jmp 1f
+2:
+ xorq %rax, %rax
+1:
+ .if 1
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %rax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_double_to_float: /* 0x8c */
+/* File: x86_64/op_double_to_float.S */
+/* File: x86_64/fpcvt.S */
+/*
+ * Generic 32-bit FP conversion operation.
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ cvtsd2ss VREG_ADDRESS(rINSTq), %xmm0
+ .if 0
+ movsd %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_WIDE_REF %rcx
+ .else
+ movss %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_REF %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_byte: /* 0x8d */
+/* File: x86_64/op_int_to_byte.S */
+/* File: x86_64/unop.S */
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4,rINST # rINST <- B
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $0xf,%cl # ecx <- A
+
+movsbl %al, %eax
+ .if 0
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_char: /* 0x8e */
+/* File: x86_64/op_int_to_char.S */
+/* File: x86_64/unop.S */
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4,rINST # rINST <- B
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $0xf,%cl # ecx <- A
+
+movzwl %ax,%eax
+ .if 0
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_int_to_short: /* 0x8f */
+/* File: x86_64/op_int_to_short.S */
+/* File: x86_64/unop.S */
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4,rINST # rINST <- B
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $0xf,%cl # ecx <- A
+
+movswl %ax, %eax
+ .if 0
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int: /* 0x90 */
+/* File: x86_64/op_add_int.S */
+/* File: x86_64/binop.S */
+/*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int, sub-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB
+ addl (rFP,%rcx,4), %eax # ex: addl (rFP,%rcx,4),%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_int: /* 0x91 */
+/* File: x86_64/op_sub_int.S */
+/* File: x86_64/binop.S */
+/*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int, sub-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB
+ subl (rFP,%rcx,4), %eax # ex: addl (rFP,%rcx,4),%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int: /* 0x92 */
+/* File: x86_64/op_mul_int.S */
+/* File: x86_64/binop.S */
+/*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int, sub-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB
+ imull (rFP,%rcx,4), %eax # ex: addl (rFP,%rcx,4),%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int: /* 0x93 */
+/* File: x86_64/op_div_int.S */
+/* File: x86_64/bindiv.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ .if 0
+ GET_WIDE_VREG %rax, %rax # eax <- vBB
+ GET_WIDE_VREG %ecx, %rcx # ecx <- vCC
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ GET_VREG %ecx, %rcx # ecx <- vCC
+ .endif
+ testl %ecx, %ecx
+ jz common_errDivideByZero
+ cmpl $-1, %ecx
+ je 2f
+ cdq # rdx:rax <- sign-extended of rax
+ idivl %ecx
+1:
+ .if 0
+ SET_WIDE_VREG %eax, rINSTq # eax <- vBB
+ .else
+ SET_VREG %eax, rINSTq # eax <- vBB
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if 0
+ xorl %eax, %eax
+ .else
+ negl %eax
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int: /* 0x94 */
+/* File: x86_64/op_rem_int.S */
+/* File: x86_64/bindiv.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ .if 0
+ GET_WIDE_VREG %rax, %rax # eax <- vBB
+ GET_WIDE_VREG %ecx, %rcx # ecx <- vCC
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ GET_VREG %ecx, %rcx # ecx <- vCC
+ .endif
+ testl %ecx, %ecx
+ jz common_errDivideByZero
+ cmpl $-1, %ecx
+ je 2f
+ cdq # rdx:rax <- sign-extended of rax
+ idivl %ecx
+1:
+ .if 0
+ SET_WIDE_VREG %edx, rINSTq # eax <- vBB
+ .else
+ SET_VREG %edx, rINSTq # eax <- vBB
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if 1
+ xorl %edx, %edx
+ .else
+ negl %edx
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int: /* 0x95 */
+/* File: x86_64/op_and_int.S */
+/* File: x86_64/binop.S */
+/*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int, sub-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB
+ andl (rFP,%rcx,4), %eax # ex: addl (rFP,%rcx,4),%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int: /* 0x96 */
+/* File: x86_64/op_or_int.S */
+/* File: x86_64/binop.S */
+/*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int, sub-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB
+ orl (rFP,%rcx,4), %eax # ex: addl (rFP,%rcx,4),%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int: /* 0x97 */
+/* File: x86_64/op_xor_int.S */
+/* File: x86_64/binop.S */
+/*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int, sub-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB
+ xorl (rFP,%rcx,4), %eax # ex: addl (rFP,%rcx,4),%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_int: /* 0x98 */
+/* File: x86_64/op_shl_int.S */
+/* File: x86_64/binop1.S */
+/*
+ * Generic 32-bit binary operation in which both operands loaded to
+ * registers (op0 in eax, op1 in ecx).
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %ecx, %rcx # eax <- vCC
+ .if 0
+ GET_WIDE_VREG %rax, %rax # rax <- vBB
+ sall %cl, %eax # ex: addl %ecx,%eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ sall %cl, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_int: /* 0x99 */
+/* File: x86_64/op_shr_int.S */
+/* File: x86_64/binop1.S */
+/*
+ * Generic 32-bit binary operation in which both operands loaded to
+ * registers (op0 in eax, op1 in ecx).
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %ecx, %rcx # eax <- vCC
+ .if 0
+ GET_WIDE_VREG %rax, %rax # rax <- vBB
+ sarl %cl, %eax # ex: addl %ecx,%eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ sarl %cl, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_int: /* 0x9a */
+/* File: x86_64/op_ushr_int.S */
+/* File: x86_64/binop1.S */
+/*
+ * Generic 32-bit binary operation in which both operands loaded to
+ * registers (op0 in eax, op1 in ecx).
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %ecx, %rcx # eax <- vCC
+ .if 0
+ GET_WIDE_VREG %rax, %rax # rax <- vBB
+ shrl %cl, %eax # ex: addl %ecx,%eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ shrl %cl, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_long: /* 0x9b */
+/* File: x86_64/op_add_long.S */
+/* File: x86_64/binopWide.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_WIDE_VREG %rax, %rax # rax <- v[BB]
+ addq (rFP,%rcx,4), %rax # ex: addq (rFP,%rcx,4),%rax
+ SET_WIDE_VREG %rax, rINSTq # v[AA] <- rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_long: /* 0x9c */
+/* File: x86_64/op_sub_long.S */
+/* File: x86_64/binopWide.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_WIDE_VREG %rax, %rax # rax <- v[BB]
+ subq (rFP,%rcx,4), %rax # ex: addq (rFP,%rcx,4),%rax
+ SET_WIDE_VREG %rax, rINSTq # v[AA] <- rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_long: /* 0x9d */
+/* File: x86_64/op_mul_long.S */
+/* File: x86_64/binopWide.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_WIDE_VREG %rax, %rax # rax <- v[BB]
+ imulq (rFP,%rcx,4), %rax # ex: addq (rFP,%rcx,4),%rax
+ SET_WIDE_VREG %rax, rINSTq # v[AA] <- rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_long: /* 0x9e */
+/* File: x86_64/op_div_long.S */
+/* File: x86_64/bindiv.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ .if 1
+ GET_WIDE_VREG %rax, %rax # eax <- vBB
+ GET_WIDE_VREG %rcx, %rcx # ecx <- vCC
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ GET_VREG %rcx, %rcx # ecx <- vCC
+ .endif
+ testq %rcx, %rcx
+ jz common_errDivideByZero
+ cmpq $-1, %rcx
+ je 2f
+ cqo # rdx:rax <- sign-extended of rax
+ idivq %rcx
+1:
+ .if 1
+ SET_WIDE_VREG %rax, rINSTq # eax <- vBB
+ .else
+ SET_VREG %rax, rINSTq # eax <- vBB
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if 0
+ xorq %rax, %rax
+ .else
+ negq %rax
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_long: /* 0x9f */
+/* File: x86_64/op_rem_long.S */
+/* File: x86_64/bindiv.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ .if 1
+ GET_WIDE_VREG %rax, %rax # eax <- vBB
+ GET_WIDE_VREG %rcx, %rcx # ecx <- vCC
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ GET_VREG %rcx, %rcx # ecx <- vCC
+ .endif
+ testq %rcx, %rcx
+ jz common_errDivideByZero
+ cmpq $-1, %rcx
+ je 2f
+ cqo # rdx:rax <- sign-extended of rax
+ idivq %rcx
+1:
+ .if 1
+ SET_WIDE_VREG %rdx, rINSTq # eax <- vBB
+ .else
+ SET_VREG %rdx, rINSTq # eax <- vBB
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if 1
+ xorq %rdx, %rdx
+ .else
+ negq %rdx
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_long: /* 0xa0 */
+/* File: x86_64/op_and_long.S */
+/* File: x86_64/binopWide.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_WIDE_VREG %rax, %rax # rax <- v[BB]
+ andq (rFP,%rcx,4), %rax # ex: addq (rFP,%rcx,4),%rax
+ SET_WIDE_VREG %rax, rINSTq # v[AA] <- rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_long: /* 0xa1 */
+/* File: x86_64/op_or_long.S */
+/* File: x86_64/binopWide.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_WIDE_VREG %rax, %rax # rax <- v[BB]
+ orq (rFP,%rcx,4), %rax # ex: addq (rFP,%rcx,4),%rax
+ SET_WIDE_VREG %rax, rINSTq # v[AA] <- rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_long: /* 0xa2 */
+/* File: x86_64/op_xor_long.S */
+/* File: x86_64/binopWide.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_WIDE_VREG %rax, %rax # rax <- v[BB]
+ xorq (rFP,%rcx,4), %rax # ex: addq (rFP,%rcx,4),%rax
+ SET_WIDE_VREG %rax, rINSTq # v[AA] <- rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_long: /* 0xa3 */
+/* File: x86_64/op_shl_long.S */
+/* File: x86_64/binop1.S */
+/*
+ * Generic 32-bit binary operation in which both operands loaded to
+ * registers (op0 in eax, op1 in ecx).
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %ecx, %rcx # eax <- vCC
+ .if 1
+ GET_WIDE_VREG %rax, %rax # rax <- vBB
+ salq %cl, %rax # ex: addl %ecx,%eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ salq %cl, %rax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_long: /* 0xa4 */
+/* File: x86_64/op_shr_long.S */
+/* File: x86_64/binop1.S */
+/*
+ * Generic 32-bit binary operation in which both operands loaded to
+ * registers (op0 in eax, op1 in ecx).
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %ecx, %rcx # eax <- vCC
+ .if 1
+ GET_WIDE_VREG %rax, %rax # rax <- vBB
+ sarq %cl, %rax # ex: addl %ecx,%eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ sarq %cl, %rax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_long: /* 0xa5 */
+/* File: x86_64/op_ushr_long.S */
+/* File: x86_64/binop1.S */
+/*
+ * Generic 32-bit binary operation in which both operands loaded to
+ * registers (op0 in eax, op1 in ecx).
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %ecx, %rcx # eax <- vCC
+ .if 1
+ GET_WIDE_VREG %rax, %rax # rax <- vBB
+ shrq %cl, %rax # ex: addl %ecx,%eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ shrq %cl, %rax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_float: /* 0xa6 */
+/* File: x86_64/op_add_float.S */
+/* File: x86_64/sseBinop.S */
+ movzbq 2(rPC), %rcx # ecx <- BB
+ movzbq 3(rPC), %rax # eax <- CC
+ movss VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ addss VREG_ADDRESS(%rax), %xmm0
+ movss %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
+ pxor %xmm0, %xmm0
+ movss %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_float: /* 0xa7 */
+/* File: x86_64/op_sub_float.S */
+/* File: x86_64/sseBinop.S */
+ movzbq 2(rPC), %rcx # ecx <- BB
+ movzbq 3(rPC), %rax # eax <- CC
+ movss VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ subss VREG_ADDRESS(%rax), %xmm0
+ movss %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
+ pxor %xmm0, %xmm0
+ movss %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_float: /* 0xa8 */
+/* File: x86_64/op_mul_float.S */
+/* File: x86_64/sseBinop.S */
+ movzbq 2(rPC), %rcx # ecx <- BB
+ movzbq 3(rPC), %rax # eax <- CC
+ movss VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ mulss VREG_ADDRESS(%rax), %xmm0
+ movss %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
+ pxor %xmm0, %xmm0
+ movss %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_float: /* 0xa9 */
+/* File: x86_64/op_div_float.S */
+/* File: x86_64/sseBinop.S */
+ movzbq 2(rPC), %rcx # ecx <- BB
+ movzbq 3(rPC), %rax # eax <- CC
+ movss VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ divss VREG_ADDRESS(%rax), %xmm0
+ movss %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
+ pxor %xmm0, %xmm0
+ movss %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_float: /* 0xaa */
+/* File: x86_64/op_rem_float.S */
+ /* rem_float vAA, vBB, vCC */
+ movzbq 3(rPC), %rcx # ecx <- BB
+ movzbq 2(rPC), %rax # eax <- CC
+ flds VREG_ADDRESS(%rcx) # vBB to fp stack
+ flds VREG_ADDRESS(%rax) # vCC to fp stack
+1:
+ fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ fstps VREG_ADDRESS(rINSTq) # %st to vAA
+ CLEAR_REF rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_double: /* 0xab */
+/* File: x86_64/op_add_double.S */
+/* File: x86_64/sseBinop.S */
+ movzbq 2(rPC), %rcx # ecx <- BB
+ movzbq 3(rPC), %rax # eax <- CC
+ movsd VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ addsd VREG_ADDRESS(%rax), %xmm0
+ movsd %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
+ pxor %xmm0, %xmm0
+ movsd %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_double: /* 0xac */
+/* File: x86_64/op_sub_double.S */
+/* File: x86_64/sseBinop.S */
+ movzbq 2(rPC), %rcx # ecx <- BB
+ movzbq 3(rPC), %rax # eax <- CC
+ movsd VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ subsd VREG_ADDRESS(%rax), %xmm0
+ movsd %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
+ pxor %xmm0, %xmm0
+ movsd %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_double: /* 0xad */
+/* File: x86_64/op_mul_double.S */
+/* File: x86_64/sseBinop.S */
+ movzbq 2(rPC), %rcx # ecx <- BB
+ movzbq 3(rPC), %rax # eax <- CC
+ movsd VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ mulsd VREG_ADDRESS(%rax), %xmm0
+ movsd %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
+ pxor %xmm0, %xmm0
+ movsd %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_double: /* 0xae */
+/* File: x86_64/op_div_double.S */
+/* File: x86_64/sseBinop.S */
+ movzbq 2(rPC), %rcx # ecx <- BB
+ movzbq 3(rPC), %rax # eax <- CC
+ movsd VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ divsd VREG_ADDRESS(%rax), %xmm0
+ movsd %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
+ pxor %xmm0, %xmm0
+ movsd %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_double: /* 0xaf */
+/* File: x86_64/op_rem_double.S */
+ /* rem_double vAA, vBB, vCC */
+ movzbq 3(rPC), %rcx # ecx <- BB
+ movzbq 2(rPC), %rax # eax <- CC
+ fldl VREG_ADDRESS(%rcx) # %st1 <- fp[vBB]
+ fldl VREG_ADDRESS(%rax) # %st0 <- fp[vCC]
+1:
+ fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ fstpl VREG_ADDRESS(rINSTq) # fp[vAA] <- %st
+ CLEAR_WIDE_REF rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int_2addr: /* 0xb0 */
+/* File: x86_64/op_add_int_2addr.S */
+/* File: x86_64/binop2addr.S */
+/*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = r0 op r1".
+ * This could be an instruction or a function call.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+ * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_VREG %eax, rINSTq # eax <- vB
+ addl %eax, (rFP,%rcx,4) # for ex: addl %eax,(rFP,%ecx,4)
+ CLEAR_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_int_2addr: /* 0xb1 */
+/* File: x86_64/op_sub_int_2addr.S */
+/* File: x86_64/binop2addr.S */
+/*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = r0 op r1".
+ * This could be an instruction or a function call.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+ * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_VREG %eax, rINSTq # eax <- vB
+ subl %eax, (rFP,%rcx,4) # for ex: addl %eax,(rFP,%ecx,4)
+ CLEAR_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int_2addr: /* 0xb2 */
+/* File: x86_64/op_mul_int_2addr.S */
+ /* mul vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_VREG %eax, %rcx # eax <- vA
+ imull (rFP,rINSTq,4), %eax
+ SET_VREG %eax, %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int_2addr: /* 0xb3 */
+/* File: x86_64/op_div_int_2addr.S */
+/* File: x86_64/bindiv2addr.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem/2addr vA, vB */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # rcx <- B
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # eax <- vA
+ GET_WIDE_VREG %ecx, %rcx # ecx <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vA
+ GET_VREG %ecx, %rcx # ecx <- vB
+ .endif
+ testl %ecx, %ecx
+ jz common_errDivideByZero
+ cmpl $-1, %ecx
+ je 2f
+ cdq # rdx:rax <- sign-extended of rax
+ idivl %ecx
+1:
+ .if 0
+ SET_WIDE_VREG %eax, rINSTq # vA <- result
+ .else
+ SET_VREG %eax, rINSTq # vA <- result
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+2:
+ .if 0
+ xorl %eax, %eax
+ .else
+ negl %eax
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int_2addr: /* 0xb4 */
+/* File: x86_64/op_rem_int_2addr.S */
+/* File: x86_64/bindiv2addr.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem/2addr vA, vB */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # rcx <- B
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # eax <- vA
+ GET_WIDE_VREG %ecx, %rcx # ecx <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vA
+ GET_VREG %ecx, %rcx # ecx <- vB
+ .endif
+ testl %ecx, %ecx
+ jz common_errDivideByZero
+ cmpl $-1, %ecx
+ je 2f
+ cdq # rdx:rax <- sign-extended of rax
+ idivl %ecx
+1:
+ .if 0
+ SET_WIDE_VREG %edx, rINSTq # vA <- result
+ .else
+ SET_VREG %edx, rINSTq # vA <- result
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+2:
+ .if 1
+ xorl %edx, %edx
+ .else
+ negl %edx
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int_2addr: /* 0xb5 */
+/* File: x86_64/op_and_int_2addr.S */
+/* File: x86_64/binop2addr.S */
+/*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = r0 op r1".
+ * This could be an instruction or a function call.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+ * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_VREG %eax, rINSTq # eax <- vB
+ andl %eax, (rFP,%rcx,4) # for ex: addl %eax,(rFP,%ecx,4)
+ CLEAR_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int_2addr: /* 0xb6 */
+/* File: x86_64/op_or_int_2addr.S */
+/* File: x86_64/binop2addr.S */
+/*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = r0 op r1".
+ * This could be an instruction or a function call.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+ * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_VREG %eax, rINSTq # eax <- vB
+ orl %eax, (rFP,%rcx,4) # for ex: addl %eax,(rFP,%ecx,4)
+ CLEAR_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int_2addr: /* 0xb7 */
+/* File: x86_64/op_xor_int_2addr.S */
+/* File: x86_64/binop2addr.S */
+/*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = r0 op r1".
+ * This could be an instruction or a function call.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+ * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_VREG %eax, rINSTq # eax <- vB
+ xorl %eax, (rFP,%rcx,4) # for ex: addl %eax,(rFP,%ecx,4)
+ CLEAR_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_int_2addr: /* 0xb8 */
+/* File: x86_64/op_shl_int_2addr.S */
+/* File: x86_64/shop2addr.S */
+/*
+ * Generic 32-bit "shift/2addr" operation.
+ */
+ /* shift/2addr vA, vB */
+ movl rINST, %ecx # ecx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # ecx <- vBB
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # rax <- vAA
+ sall %cl, %eax # ex: sarl %cl, %eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, rINSTq # eax <- vAA
+ sall %cl, %eax # ex: sarl %cl, %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_int_2addr: /* 0xb9 */
+/* File: x86_64/op_shr_int_2addr.S */
+/* File: x86_64/shop2addr.S */
+/*
+ * Generic 32-bit "shift/2addr" operation.
+ */
+ /* shift/2addr vA, vB */
+ movl rINST, %ecx # ecx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # ecx <- vBB
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # rax <- vAA
+ sarl %cl, %eax # ex: sarl %cl, %eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, rINSTq # eax <- vAA
+ sarl %cl, %eax # ex: sarl %cl, %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_int_2addr: /* 0xba */
+/* File: x86_64/op_ushr_int_2addr.S */
+/* File: x86_64/shop2addr.S */
+/*
+ * Generic 32-bit "shift/2addr" operation.
+ */
+ /* shift/2addr vA, vB */
+ movl rINST, %ecx # ecx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # ecx <- vBB
+ andb $0xf, rINSTbl # rINST <- A
+ .if 0
+ GET_WIDE_VREG %rax, rINSTq # rax <- vAA
+ shrl %cl, %eax # ex: sarl %cl, %eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, rINSTq # eax <- vAA
+ shrl %cl, %eax # ex: sarl %cl, %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_long_2addr: /* 0xbb */
+/* File: x86_64/op_add_long_2addr.S */
+/* File: x86_64/binopWide2addr.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ addq %rax, (rFP,%rcx,4) # for ex: addq %rax,(rFP,%rcx,4)
+ CLEAR_WIDE_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_long_2addr: /* 0xbc */
+/* File: x86_64/op_sub_long_2addr.S */
+/* File: x86_64/binopWide2addr.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ subq %rax, (rFP,%rcx,4) # for ex: addq %rax,(rFP,%rcx,4)
+ CLEAR_WIDE_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_long_2addr: /* 0xbd */
+/* File: x86_64/op_mul_long_2addr.S */
+ /* mul vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rax, %rcx # rax <- vA
+ imulq (rFP,rINSTq,4), %rax
+ SET_WIDE_VREG %rax, %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_long_2addr: /* 0xbe */
+/* File: x86_64/op_div_long_2addr.S */
+/* File: x86_64/bindiv2addr.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem/2addr vA, vB */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # rcx <- B
+ andb $0xf, rINSTbl # rINST <- A
+ .if 1
+ GET_WIDE_VREG %rax, rINSTq # eax <- vA
+ GET_WIDE_VREG %rcx, %rcx # ecx <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vA
+ GET_VREG %rcx, %rcx # ecx <- vB
+ .endif
+ testq %rcx, %rcx
+ jz common_errDivideByZero
+ cmpq $-1, %rcx
+ je 2f
+ cqo # rdx:rax <- sign-extended of rax
+ idivq %rcx
+1:
+ .if 1
+ SET_WIDE_VREG %rax, rINSTq # vA <- result
+ .else
+ SET_VREG %rax, rINSTq # vA <- result
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+2:
+ .if 0
+ xorq %rax, %rax
+ .else
+ negq %rax
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_long_2addr: /* 0xbf */
+/* File: x86_64/op_rem_long_2addr.S */
+/* File: x86_64/bindiv2addr.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem/2addr vA, vB */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # rcx <- B
+ andb $0xf, rINSTbl # rINST <- A
+ .if 1
+ GET_WIDE_VREG %rax, rINSTq # eax <- vA
+ GET_WIDE_VREG %rcx, %rcx # ecx <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vA
+ GET_VREG %rcx, %rcx # ecx <- vB
+ .endif
+ testq %rcx, %rcx
+ jz common_errDivideByZero
+ cmpq $-1, %rcx
+ je 2f
+ cqo # rdx:rax <- sign-extended of rax
+ idivq %rcx
+1:
+ .if 1
+ SET_WIDE_VREG %rdx, rINSTq # vA <- result
+ .else
+ SET_VREG %rdx, rINSTq # vA <- result
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+2:
+ .if 1
+ xorq %rdx, %rdx
+ .else
+ negq %rdx
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_long_2addr: /* 0xc0 */
+/* File: x86_64/op_and_long_2addr.S */
+/* File: x86_64/binopWide2addr.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ andq %rax, (rFP,%rcx,4) # for ex: addq %rax,(rFP,%rcx,4)
+ CLEAR_WIDE_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_long_2addr: /* 0xc1 */
+/* File: x86_64/op_or_long_2addr.S */
+/* File: x86_64/binopWide2addr.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ orq %rax, (rFP,%rcx,4) # for ex: addq %rax,(rFP,%rcx,4)
+ CLEAR_WIDE_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_long_2addr: /* 0xc2 */
+/* File: x86_64/op_xor_long_2addr.S */
+/* File: x86_64/binopWide2addr.S */
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $4, rINST # rINST <- B
+ andb $0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ xorq %rax, (rFP,%rcx,4) # for ex: addq %rax,(rFP,%rcx,4)
+ CLEAR_WIDE_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_long_2addr: /* 0xc3 */
+/* File: x86_64/op_shl_long_2addr.S */
+/* File: x86_64/shop2addr.S */
+/*
+ * Generic 32-bit "shift/2addr" operation.
+ */
+ /* shift/2addr vA, vB */
+ movl rINST, %ecx # ecx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # ecx <- vBB
+ andb $0xf, rINSTbl # rINST <- A
+ .if 1
+ GET_WIDE_VREG %rax, rINSTq # rax <- vAA
+ salq %cl, %rax # ex: sarl %cl, %eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, rINSTq # eax <- vAA
+ salq %cl, %rax # ex: sarl %cl, %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_long_2addr: /* 0xc4 */
+/* File: x86_64/op_shr_long_2addr.S */
+/* File: x86_64/shop2addr.S */
+/*
+ * Generic 32-bit "shift/2addr" operation.
+ */
+ /* shift/2addr vA, vB */
+ movl rINST, %ecx # ecx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # ecx <- vBB
+ andb $0xf, rINSTbl # rINST <- A
+ .if 1
+ GET_WIDE_VREG %rax, rINSTq # rax <- vAA
+ sarq %cl, %rax # ex: sarl %cl, %eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, rINSTq # eax <- vAA
+ sarq %cl, %rax # ex: sarl %cl, %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_long_2addr: /* 0xc5 */
+/* File: x86_64/op_ushr_long_2addr.S */
+/* File: x86_64/shop2addr.S */
+/*
+ * Generic 32-bit "shift/2addr" operation.
+ */
+ /* shift/2addr vA, vB */
+ movl rINST, %ecx # ecx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # ecx <- vBB
+ andb $0xf, rINSTbl # rINST <- A
+ .if 1
+ GET_WIDE_VREG %rax, rINSTq # rax <- vAA
+ shrq %cl, %rax # ex: sarl %cl, %eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, rINSTq # eax <- vAA
+ shrq %cl, %rax # ex: sarl %cl, %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_float_2addr: /* 0xc6 */
+/* File: x86_64/op_add_float_2addr.S */
+/* File: x86_64/sseBinop2Addr.S */
+ movl rINST, %ecx # ecx <- A+
+ andl $0xf, %ecx # ecx <- A
+ movss VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ sarl $4, rINST # rINST<- B
+ addss VREG_ADDRESS(rINSTq), %xmm0
+ movss %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
+ pxor %xmm0, %xmm0
+ movss %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_float_2addr: /* 0xc7 */
+/* File: x86_64/op_sub_float_2addr.S */
+/* File: x86_64/sseBinop2Addr.S */
+ movl rINST, %ecx # ecx <- A+
+ andl $0xf, %ecx # ecx <- A
+ movss VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ sarl $4, rINST # rINST<- B
+ subss VREG_ADDRESS(rINSTq), %xmm0
+ movss %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
+ pxor %xmm0, %xmm0
+ movss %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_float_2addr: /* 0xc8 */
+/* File: x86_64/op_mul_float_2addr.S */
+/* File: x86_64/sseBinop2Addr.S */
+ movl rINST, %ecx # ecx <- A+
+ andl $0xf, %ecx # ecx <- A
+ movss VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ sarl $4, rINST # rINST<- B
+ mulss VREG_ADDRESS(rINSTq), %xmm0
+ movss %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
+ pxor %xmm0, %xmm0
+ movss %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_float_2addr: /* 0xc9 */
+/* File: x86_64/op_div_float_2addr.S */
+/* File: x86_64/sseBinop2Addr.S */
+ movl rINST, %ecx # ecx <- A+
+ andl $0xf, %ecx # ecx <- A
+ movss VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ sarl $4, rINST # rINST<- B
+ divss VREG_ADDRESS(rINSTq), %xmm0
+ movss %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
+ pxor %xmm0, %xmm0
+ movss %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_float_2addr: /* 0xca */
+/* File: x86_64/op_rem_float_2addr.S */
+ /* rem_float/2addr vA, vB */
+ movzbq rINSTbl, %rcx # ecx <- A+
+ sarl $4, rINST # rINST <- B
+ flds VREG_ADDRESS(rINSTq) # vB to fp stack
+ andb $0xf, %cl # ecx <- A
+ flds VREG_ADDRESS(%rcx) # vA to fp stack
+1:
+ fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ fstps VREG_ADDRESS(%rcx) # %st to vA
+ CLEAR_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_double_2addr: /* 0xcb */
+/* File: x86_64/op_add_double_2addr.S */
+/* File: x86_64/sseBinop2Addr.S */
+ movl rINST, %ecx # ecx <- A+
+ andl $0xf, %ecx # ecx <- A
+ movsd VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ sarl $4, rINST # rINST<- B
+ addsd VREG_ADDRESS(rINSTq), %xmm0
+ movsd %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
+ pxor %xmm0, %xmm0
+ movsd %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_sub_double_2addr: /* 0xcc */
+/* File: x86_64/op_sub_double_2addr.S */
+/* File: x86_64/sseBinop2Addr.S */
+ movl rINST, %ecx # ecx <- A+
+ andl $0xf, %ecx # ecx <- A
+ movsd VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ sarl $4, rINST # rINST<- B
+ subsd VREG_ADDRESS(rINSTq), %xmm0
+ movsd %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
+ pxor %xmm0, %xmm0
+ movsd %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_double_2addr: /* 0xcd */
+/* File: x86_64/op_mul_double_2addr.S */
+/* File: x86_64/sseBinop2Addr.S */
+ movl rINST, %ecx # ecx <- A+
+ andl $0xf, %ecx # ecx <- A
+ movsd VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ sarl $4, rINST # rINST<- B
+ mulsd VREG_ADDRESS(rINSTq), %xmm0
+ movsd %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
+ pxor %xmm0, %xmm0
+ movsd %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_double_2addr: /* 0xce */
+/* File: x86_64/op_div_double_2addr.S */
+/* File: x86_64/sseBinop2Addr.S */
+ movl rINST, %ecx # ecx <- A+
+ andl $0xf, %ecx # ecx <- A
+ movsd VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ sarl $4, rINST # rINST<- B
+ divsd VREG_ADDRESS(rINSTq), %xmm0
+ movsd %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
+ pxor %xmm0, %xmm0
+ movsd %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_double_2addr: /* 0xcf */
+/* File: x86_64/op_rem_double_2addr.S */
+ /* rem_double/2addr vA, vB */
+ movzbq rINSTbl, %rcx # ecx <- A+
+ sarl $4, rINST # rINST <- B
+ fldl VREG_ADDRESS(rINSTq) # vB to fp stack
+ andb $0xf, %cl # ecx <- A
+ fldl VREG_ADDRESS(%rcx) # vA to fp stack
+1:
+ fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ fstpl VREG_ADDRESS(%rcx) # %st to vA
+ CLEAR_WIDE_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int_lit16: /* 0xd0 */
+/* File: x86_64/op_add_int_lit16.S */
+/* File: x86_64/binopLit16.S */
+/*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int/lit16, rsub-int,
+ * and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ andb $0xf, rINSTbl # rINST <- A
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ addl %ecx, %eax # for example: addl %ecx, %eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rsub_int: /* 0xd1 */
+/* File: x86_64/op_rsub_int.S */
+/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
+/* File: x86_64/binopLit16.S */
+/*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int/lit16, rsub-int,
+ * and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ andb $0xf, rINSTbl # rINST <- A
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ subl %eax, %ecx # for example: addl %ecx, %eax
+ SET_VREG %ecx, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int_lit16: /* 0xd2 */
+/* File: x86_64/op_mul_int_lit16.S */
+/* File: x86_64/binopLit16.S */
+/*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int/lit16, rsub-int,
+ * and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ andb $0xf, rINSTbl # rINST <- A
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ imull %ecx, %eax # for example: addl %ecx, %eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int_lit16: /* 0xd3 */
+/* File: x86_64/op_div_int_lit16.S */
+/* File: x86_64/bindivLit16.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem/lit16 vA, vB, #+CCCC */
+ /* Need A in rINST, ssssCCCC in ecx, vB in eax */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ andb $0xf, rINSTbl # rINST <- A
+ testl %ecx, %ecx
+ jz common_errDivideByZero
+ cmpl $-1, %ecx
+ je 2f
+ cdq # rax <- sign-extended of eax
+ idivl %ecx
+1:
+ SET_VREG %eax, rINSTq # vA <- result
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if 0
+ xorl %eax, %eax
+ .else
+ negl %eax
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int_lit16: /* 0xd4 */
+/* File: x86_64/op_rem_int_lit16.S */
+/* File: x86_64/bindivLit16.S */
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem/lit16 vA, vB, #+CCCC */
+ /* Need A in rINST, ssssCCCC in ecx, vB in eax */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ andb $0xf, rINSTbl # rINST <- A
+ testl %ecx, %ecx
+ jz common_errDivideByZero
+ cmpl $-1, %ecx
+ je 2f
+ cdq # rax <- sign-extended of eax
+ idivl %ecx
+1:
+ SET_VREG %edx, rINSTq # vA <- result
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if 1
+ xorl %edx, %edx
+ .else
+ negl %edx
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int_lit16: /* 0xd5 */
+/* File: x86_64/op_and_int_lit16.S */
+/* File: x86_64/binopLit16.S */
+/*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int/lit16, rsub-int,
+ * and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ andb $0xf, rINSTbl # rINST <- A
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ andl %ecx, %eax # for example: addl %ecx, %eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int_lit16: /* 0xd6 */
+/* File: x86_64/op_or_int_lit16.S */
+/* File: x86_64/binopLit16.S */
+/*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int/lit16, rsub-int,
+ * and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ andb $0xf, rINSTbl # rINST <- A
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ orl %ecx, %eax # for example: addl %ecx, %eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int_lit16: /* 0xd7 */
+/* File: x86_64/op_xor_int_lit16.S */
+/* File: x86_64/binopLit16.S */
+/*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int/lit16, rsub-int,
+ * and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ andb $0xf, rINSTbl # rINST <- A
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ xorl %ecx, %eax # for example: addl %ecx, %eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_add_int_lit8: /* 0xd8 */
+/* File: x86_64/op_add_int_lit8.S */
+/* File: x86_64/binopLit8.S */
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ addl %ecx, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rsub_int_lit8: /* 0xd9 */
+/* File: x86_64/op_rsub_int_lit8.S */
+/* File: x86_64/binopLit8.S */
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ subl %eax, %ecx # ex: addl %ecx,%eax
+ SET_VREG %ecx, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_mul_int_lit8: /* 0xda */
+/* File: x86_64/op_mul_int_lit8.S */
+/* File: x86_64/binopLit8.S */
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ imull %ecx, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_div_int_lit8: /* 0xdb */
+/* File: x86_64/op_div_int_lit8.S */
+/* File: x86_64/bindivLit8.S */
+/*
+ * 32-bit div/rem "lit8" binary operation. Handles special case of
+ * op0=minint & op1=-1
+ */
+ /* div/rem/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movsbl 3(rPC), %ecx # ecx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ testl %ecx, %ecx
+ je common_errDivideByZero
+ cmpl $-1, %ecx
+ je 2f
+ cdq # rax <- sign-extended of eax
+ idivl %ecx
+1:
+ SET_VREG %eax, rINSTq # vA <- result
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if 0
+ xorl %eax, %eax
+ .else
+ negl %eax
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_rem_int_lit8: /* 0xdc */
+/* File: x86_64/op_rem_int_lit8.S */
+/* File: x86_64/bindivLit8.S */
+/*
+ * 32-bit div/rem "lit8" binary operation. Handles special case of
+ * op0=minint & op1=-1
+ */
+ /* div/rem/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movsbl 3(rPC), %ecx # ecx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ testl %ecx, %ecx
+ je common_errDivideByZero
+ cmpl $-1, %ecx
+ je 2f
+ cdq # rax <- sign-extended of eax
+ idivl %ecx
+1:
+ SET_VREG %edx, rINSTq # vA <- result
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if 1
+ xorl %edx, %edx
+ .else
+ negl %edx
+ .endif
+ jmp 1b
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_and_int_lit8: /* 0xdd */
+/* File: x86_64/op_and_int_lit8.S */
+/* File: x86_64/binopLit8.S */
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ andl %ecx, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_or_int_lit8: /* 0xde */
+/* File: x86_64/op_or_int_lit8.S */
+/* File: x86_64/binopLit8.S */
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ orl %ecx, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_xor_int_lit8: /* 0xdf */
+/* File: x86_64/op_xor_int_lit8.S */
+/* File: x86_64/binopLit8.S */
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ xorl %ecx, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shl_int_lit8: /* 0xe0 */
+/* File: x86_64/op_shl_int_lit8.S */
+/* File: x86_64/binopLit8.S */
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ sall %cl, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_shr_int_lit8: /* 0xe1 */
+/* File: x86_64/op_shr_int_lit8.S */
+/* File: x86_64/binopLit8.S */
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ sarl %cl, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_ushr_int_lit8: /* 0xe2 */
+/* File: x86_64/op_ushr_int_lit8.S */
+/* File: x86_64/binopLit8.S */
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ shrl %cl, %eax # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_quick: /* 0xe3 */
+/* File: x86_64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
+ /* op vA, vB, offset@CCCC */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ movzwq 2(rPC), %rax # eax <- field byte offset
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf,rINSTbl # rINST <- A
+ .if 0
+ movq (%rcx,%rax,1), %rax
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ movl (%rcx,%rax,1), %eax
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_wide_quick: /* 0xe4 */
+/* File: x86_64/op_iget_wide_quick.S */
+/* File: x86_64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
+ /* op vA, vB, offset@CCCC */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ movzwq 2(rPC), %rax # eax <- field byte offset
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf,rINSTbl # rINST <- A
+ .if 1
+ movq (%rcx,%rax,1), %rax
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ movswl (%rcx,%rax,1), %eax
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_object_quick: /* 0xe5 */
+/* File: x86_64/op_iget_object_quick.S */
+ /* For: iget-object-quick */
+ /* op vA, vB, offset@CCCC */
+ .extern artIGetObjectFromMterp
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG0, %rcx # vB (object we're operating on)
+ movzwl 2(rPC), OUT_32_ARG1 # eax <- field byte offset
+ EXPORT_PC
+ callq SYMBOL(artIGetObjectFromMterp) # (obj, offset)
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $0xf, rINSTbl # rINST <- A
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_quick: /* 0xe6 */
+/* File: x86_64/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ /* op vA, vB, offset@CCCC */
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf, rINSTbl # rINST <- A
+ GET_VREG rINST, rINSTq # rINST <- v[A]
+ movzwq 2(rPC), %rax # rax <- field byte offset
+ movl rINST, (%rcx,%rax,1)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_wide_quick: /* 0xe7 */
+/* File: x86_64/op_iput_wide_quick.S */
+ /* iput-wide-quick vA, vB, offset@CCCC */
+ movzbq rINSTbl, %rcx # rcx<- BA
+ sarl $4, %ecx # ecx<- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ movzwq 2(rPC), %rax # rax<- field byte offset
+ leaq (%rcx,%rax,1), %rcx # ecx<- Address of 64-bit target
+ andb $0xf, rINSTbl # rINST<- A
+ GET_WIDE_VREG %rax, rINSTq # rax<- fp[A]/fp[A+1]
+ movq %rax, (%rcx) # obj.field<- r0/r1
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_object_quick: /* 0xe8 */
+/* File: x86_64/op_iput_object_quick.S */
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST 232
+ movl rINST, OUT_32_ARG2
+ call SYMBOL(MterpIputObjectQuick)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual_quick: /* 0xe9 */
+/* File: x86_64/op_invoke_virtual_quick.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeVirtualQuick
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 233
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeVirtualQuick)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_virtual_range_quick: /* 0xea */
+/* File: x86_64/op_invoke_virtual_range_quick.S */
+/* File: x86_64/invoke.S */
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern MterpInvokeVirtualQuickRange
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST 234
+ movl rINST, OUT_32_ARG3
+ call SYMBOL(MterpInvokeVirtualQuickRange)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_boolean_quick: /* 0xeb */
+/* File: x86_64/op_iput_boolean_quick.S */
+/* File: x86_64/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ /* op vA, vB, offset@CCCC */
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf, rINSTbl # rINST <- A
+ GET_VREG rINST, rINSTq # rINST <- v[A]
+ movzwq 2(rPC), %rax # rax <- field byte offset
+ movb rINSTbl, (%rcx,%rax,1)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_byte_quick: /* 0xec */
+/* File: x86_64/op_iput_byte_quick.S */
+/* File: x86_64/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ /* op vA, vB, offset@CCCC */
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf, rINSTbl # rINST <- A
+ GET_VREG rINST, rINSTq # rINST <- v[A]
+ movzwq 2(rPC), %rax # rax <- field byte offset
+ movb rINSTbl, (%rcx,%rax,1)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_char_quick: /* 0xed */
+/* File: x86_64/op_iput_char_quick.S */
+/* File: x86_64/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ /* op vA, vB, offset@CCCC */
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf, rINSTbl # rINST <- A
+ GET_VREG rINST, rINSTq # rINST <- v[A]
+ movzwq 2(rPC), %rax # rax <- field byte offset
+ movw rINSTw, (%rcx,%rax,1)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iput_short_quick: /* 0xee */
+/* File: x86_64/op_iput_short_quick.S */
+/* File: x86_64/op_iput_quick.S */
+ /* For: iput-quick, iput-object-quick */
+ /* op vA, vB, offset@CCCC */
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf, rINSTbl # rINST <- A
+ GET_VREG rINST, rINSTq # rINST <- v[A]
+ movzwq 2(rPC), %rax # rax <- field byte offset
+ movw rINSTw, (%rcx,%rax,1)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_boolean_quick: /* 0xef */
+/* File: x86_64/op_iget_boolean_quick.S */
+/* File: x86_64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
+ /* op vA, vB, offset@CCCC */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ movzwq 2(rPC), %rax # eax <- field byte offset
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf,rINSTbl # rINST <- A
+ .if 0
+ movq (%rcx,%rax,1), %rax
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ movsbl (%rcx,%rax,1), %eax
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_byte_quick: /* 0xf0 */
+/* File: x86_64/op_iget_byte_quick.S */
+/* File: x86_64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
+ /* op vA, vB, offset@CCCC */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ movzwq 2(rPC), %rax # eax <- field byte offset
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf,rINSTbl # rINST <- A
+ .if 0
+ movq (%rcx,%rax,1), %rax
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ movsbl (%rcx,%rax,1), %eax
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_char_quick: /* 0xf1 */
+/* File: x86_64/op_iget_char_quick.S */
+/* File: x86_64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
+ /* op vA, vB, offset@CCCC */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ movzwq 2(rPC), %rax # eax <- field byte offset
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf,rINSTbl # rINST <- A
+ .if 0
+ movq (%rcx,%rax,1), %rax
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ movzwl (%rcx,%rax,1), %eax
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_iget_short_quick: /* 0xf2 */
+/* File: x86_64/op_iget_short_quick.S */
+/* File: x86_64/op_iget_quick.S */
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
+ /* op vA, vB, offset@CCCC */
+ movl rINST, %ecx # rcx <- BA
+ sarl $4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ movzwq 2(rPC), %rax # eax <- field byte offset
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $0xf,rINSTbl # rINST <- A
+ .if 0
+ movq (%rcx,%rax,1), %rax
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ movswl (%rcx,%rax,1), %eax
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_invoke_lambda: /* 0xf3 */
+/* Transfer stub to alternate interpreter */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_f4: /* 0xf4 */
+/* File: x86_64/op_unused_f4.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_capture_variable: /* 0xf5 */
+/* Transfer stub to alternate interpreter */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_create_lambda: /* 0xf6 */
+/* Transfer stub to alternate interpreter */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_liberate_variable: /* 0xf7 */
+/* Transfer stub to alternate interpreter */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_box_lambda: /* 0xf8 */
+/* Transfer stub to alternate interpreter */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unbox_lambda: /* 0xf9 */
+/* Transfer stub to alternate interpreter */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fa: /* 0xfa */
+/* File: x86_64/op_unused_fa.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fb: /* 0xfb */
+/* File: x86_64/op_unused_fb.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fc: /* 0xfc */
+/* File: x86_64/op_unused_fc.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fd: /* 0xfd */
+/* File: x86_64/op_unused_fd.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_fe: /* 0xfe */
+/* File: x86_64/op_unused_fe.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+/* ------------------------------ */
+ .balign 128
+.L_op_unused_ff: /* 0xff */
+/* File: x86_64/op_unused_ff.S */
+/* File: x86_64/unused.S */
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
+
+
+ .balign 128
+ SIZE(SYMBOL(artMterpAsmInstructionStart),SYMBOL(artMterpAsmInstructionStart))
+ .global SYMBOL(artMterpAsmInstructionEnd)
+SYMBOL(artMterpAsmInstructionEnd):
+
+/*
+ * ===========================================================================
+ * Sister implementations
+ * ===========================================================================
+ */
+ .global SYMBOL(artMterpAsmSisterStart)
+ FUNCTION_TYPE(SYMBOL(artMterpAsmSisterStart))
+ .text
+ .balign 4
+SYMBOL(artMterpAsmSisterStart):
+
+ SIZE(SYMBOL(artMterpAsmSisterStart),SYMBOL(artMterpAsmSisterStart))
+ .global SYMBOL(artMterpAsmSisterEnd)
+SYMBOL(artMterpAsmSisterEnd):
+
+
+ .global SYMBOL(artMterpAsmAltInstructionStart)
+ FUNCTION_TYPE(SYMBOL(artMterpAsmAltInstructionStart))
+ .text
+
+SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_nop: /* 0x00 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(0*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move: /* 0x01 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(1*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_from16: /* 0x02 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(2*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_16: /* 0x03 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(3*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_wide: /* 0x04 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(4*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_wide_from16: /* 0x05 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(5*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_wide_16: /* 0x06 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(6*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_object: /* 0x07 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(7*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_object_from16: /* 0x08 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(8*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_object_16: /* 0x09 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(9*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_result: /* 0x0a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(10*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_result_wide: /* 0x0b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(11*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_result_object: /* 0x0c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(12*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_move_exception: /* 0x0d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(13*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_void: /* 0x0e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(14*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return: /* 0x0f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(15*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_wide: /* 0x10 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(16*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_object: /* 0x11 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(17*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_4: /* 0x12 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(18*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_16: /* 0x13 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(19*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const: /* 0x14 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(20*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_high16: /* 0x15 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(21*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide_16: /* 0x16 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(22*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide_32: /* 0x17 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(23*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide: /* 0x18 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(24*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_wide_high16: /* 0x19 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(25*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_string: /* 0x1a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(26*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_string_jumbo: /* 0x1b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(27*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_const_class: /* 0x1c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(28*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_monitor_enter: /* 0x1d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(29*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_monitor_exit: /* 0x1e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(30*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_check_cast: /* 0x1f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(31*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_instance_of: /* 0x20 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(32*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_array_length: /* 0x21 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(33*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_new_instance: /* 0x22 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(34*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_new_array: /* 0x23 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(35*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_filled_new_array: /* 0x24 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(36*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_filled_new_array_range: /* 0x25 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(37*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_fill_array_data: /* 0x26 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(38*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_throw: /* 0x27 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(39*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_goto: /* 0x28 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(40*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_goto_16: /* 0x29 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(41*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_goto_32: /* 0x2a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(42*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_packed_switch: /* 0x2b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(43*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sparse_switch: /* 0x2c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(44*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpl_float: /* 0x2d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(45*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpg_float: /* 0x2e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(46*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpl_double: /* 0x2f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(47*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmpg_double: /* 0x30 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(48*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_cmp_long: /* 0x31 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(49*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_eq: /* 0x32 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(50*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_ne: /* 0x33 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(51*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_lt: /* 0x34 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(52*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_ge: /* 0x35 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(53*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_gt: /* 0x36 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(54*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_le: /* 0x37 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(55*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_eqz: /* 0x38 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(56*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_nez: /* 0x39 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(57*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_ltz: /* 0x3a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(58*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_gez: /* 0x3b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(59*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_gtz: /* 0x3c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(60*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_if_lez: /* 0x3d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(61*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_3e: /* 0x3e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(62*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_3f: /* 0x3f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(63*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_40: /* 0x40 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(64*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_41: /* 0x41 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(65*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_42: /* 0x42 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(66*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_43: /* 0x43 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(67*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget: /* 0x44 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(68*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_wide: /* 0x45 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(69*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_object: /* 0x46 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(70*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_boolean: /* 0x47 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(71*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_byte: /* 0x48 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(72*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_char: /* 0x49 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(73*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aget_short: /* 0x4a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(74*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput: /* 0x4b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(75*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_wide: /* 0x4c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(76*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_object: /* 0x4d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(77*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_boolean: /* 0x4e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(78*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_byte: /* 0x4f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(79*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_char: /* 0x50 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(80*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_aput_short: /* 0x51 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(81*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget: /* 0x52 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(82*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_wide: /* 0x53 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(83*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_object: /* 0x54 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(84*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_boolean: /* 0x55 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(85*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_byte: /* 0x56 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(86*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_char: /* 0x57 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(87*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_short: /* 0x58 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(88*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput: /* 0x59 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(89*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_wide: /* 0x5a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(90*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_object: /* 0x5b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(91*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_boolean: /* 0x5c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(92*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_byte: /* 0x5d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(93*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_char: /* 0x5e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(94*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_short: /* 0x5f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(95*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget: /* 0x60 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(96*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_wide: /* 0x61 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(97*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_object: /* 0x62 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(98*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_boolean: /* 0x63 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(99*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_byte: /* 0x64 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(100*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_char: /* 0x65 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(101*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sget_short: /* 0x66 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(102*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput: /* 0x67 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(103*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_wide: /* 0x68 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(104*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_object: /* 0x69 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(105*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_boolean: /* 0x6a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(106*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_byte: /* 0x6b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(107*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_char: /* 0x6c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(108*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sput_short: /* 0x6d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(109*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual: /* 0x6e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(110*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_super: /* 0x6f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(111*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_direct: /* 0x70 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(112*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_static: /* 0x71 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(113*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_interface: /* 0x72 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(114*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_return_void_no_barrier: /* 0x73 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(115*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual_range: /* 0x74 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(116*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_super_range: /* 0x75 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(117*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_direct_range: /* 0x76 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(118*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_static_range: /* 0x77 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(119*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_interface_range: /* 0x78 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(120*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_79: /* 0x79 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(121*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_7a: /* 0x7a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(122*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_int: /* 0x7b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(123*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_not_int: /* 0x7c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(124*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_long: /* 0x7d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(125*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_not_long: /* 0x7e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(126*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_float: /* 0x7f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(127*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_neg_double: /* 0x80 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(128*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_long: /* 0x81 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(129*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_float: /* 0x82 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(130*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_double: /* 0x83 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(131*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_long_to_int: /* 0x84 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(132*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_long_to_float: /* 0x85 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(133*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_long_to_double: /* 0x86 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(134*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_float_to_int: /* 0x87 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(135*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_float_to_long: /* 0x88 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(136*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_float_to_double: /* 0x89 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(137*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_double_to_int: /* 0x8a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(138*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_double_to_long: /* 0x8b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(139*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_double_to_float: /* 0x8c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(140*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_byte: /* 0x8d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(141*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_char: /* 0x8e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(142*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_int_to_short: /* 0x8f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(143*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int: /* 0x90 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(144*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_int: /* 0x91 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(145*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int: /* 0x92 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(146*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int: /* 0x93 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(147*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int: /* 0x94 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(148*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int: /* 0x95 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(149*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int: /* 0x96 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(150*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int: /* 0x97 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(151*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_int: /* 0x98 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(152*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_int: /* 0x99 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(153*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_int: /* 0x9a */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(154*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_long: /* 0x9b */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(155*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_long: /* 0x9c */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(156*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_long: /* 0x9d */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(157*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_long: /* 0x9e */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(158*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_long: /* 0x9f */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(159*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_long: /* 0xa0 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(160*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_long: /* 0xa1 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(161*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_long: /* 0xa2 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(162*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_long: /* 0xa3 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(163*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_long: /* 0xa4 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(164*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_long: /* 0xa5 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(165*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_float: /* 0xa6 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(166*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_float: /* 0xa7 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(167*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_float: /* 0xa8 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(168*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_float: /* 0xa9 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(169*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_float: /* 0xaa */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(170*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_double: /* 0xab */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(171*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_double: /* 0xac */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(172*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_double: /* 0xad */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(173*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_double: /* 0xae */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(174*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_double: /* 0xaf */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(175*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int_2addr: /* 0xb0 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(176*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_int_2addr: /* 0xb1 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(177*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int_2addr: /* 0xb2 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(178*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int_2addr: /* 0xb3 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(179*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int_2addr: /* 0xb4 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(180*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int_2addr: /* 0xb5 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(181*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int_2addr: /* 0xb6 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(182*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int_2addr: /* 0xb7 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(183*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_int_2addr: /* 0xb8 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(184*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_int_2addr: /* 0xb9 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(185*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_int_2addr: /* 0xba */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(186*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_long_2addr: /* 0xbb */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(187*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_long_2addr: /* 0xbc */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(188*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_long_2addr: /* 0xbd */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(189*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_long_2addr: /* 0xbe */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(190*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_long_2addr: /* 0xbf */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(191*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_long_2addr: /* 0xc0 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(192*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_long_2addr: /* 0xc1 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(193*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_long_2addr: /* 0xc2 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(194*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_long_2addr: /* 0xc3 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(195*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_long_2addr: /* 0xc4 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(196*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_long_2addr: /* 0xc5 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(197*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_float_2addr: /* 0xc6 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(198*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_float_2addr: /* 0xc7 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(199*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_float_2addr: /* 0xc8 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(200*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_float_2addr: /* 0xc9 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(201*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_float_2addr: /* 0xca */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(202*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_double_2addr: /* 0xcb */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(203*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_sub_double_2addr: /* 0xcc */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(204*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_double_2addr: /* 0xcd */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(205*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_double_2addr: /* 0xce */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(206*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_double_2addr: /* 0xcf */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(207*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int_lit16: /* 0xd0 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(208*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rsub_int: /* 0xd1 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(209*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int_lit16: /* 0xd2 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(210*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int_lit16: /* 0xd3 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(211*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int_lit16: /* 0xd4 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(212*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int_lit16: /* 0xd5 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(213*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int_lit16: /* 0xd6 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(214*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int_lit16: /* 0xd7 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(215*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_add_int_lit8: /* 0xd8 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(216*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rsub_int_lit8: /* 0xd9 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(217*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_mul_int_lit8: /* 0xda */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(218*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_div_int_lit8: /* 0xdb */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(219*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_rem_int_lit8: /* 0xdc */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(220*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_and_int_lit8: /* 0xdd */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(221*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_or_int_lit8: /* 0xde */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(222*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_xor_int_lit8: /* 0xdf */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(223*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shl_int_lit8: /* 0xe0 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(224*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_shr_int_lit8: /* 0xe1 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(225*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_ushr_int_lit8: /* 0xe2 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(226*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_quick: /* 0xe3 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(227*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_wide_quick: /* 0xe4 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(228*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_object_quick: /* 0xe5 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(229*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_quick: /* 0xe6 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(230*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_wide_quick: /* 0xe7 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(231*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_object_quick: /* 0xe8 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(232*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual_quick: /* 0xe9 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(233*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_virtual_range_quick: /* 0xea */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(234*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_boolean_quick: /* 0xeb */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(235*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_byte_quick: /* 0xec */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(236*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_char_quick: /* 0xed */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(237*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iput_short_quick: /* 0xee */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(238*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_boolean_quick: /* 0xef */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(239*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_byte_quick: /* 0xf0 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(240*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_char_quick: /* 0xf1 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(241*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_iget_short_quick: /* 0xf2 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(242*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_invoke_lambda: /* 0xf3 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(243*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_f4: /* 0xf4 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(244*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_capture_variable: /* 0xf5 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(245*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_create_lambda: /* 0xf6 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(246*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_liberate_variable: /* 0xf7 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(247*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_box_lambda: /* 0xf8 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(248*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unbox_lambda: /* 0xf9 */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(249*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fa: /* 0xfa */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(250*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fb: /* 0xfb */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(251*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fc: /* 0xfc */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(252*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fd: /* 0xfd */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(253*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_fe: /* 0xfe */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(254*128)
+
+/* ------------------------------ */
+ .balign 128
+.L_ALT_op_unused_ff: /* 0xff */
+/* File: x86_64/alt_stub.S */
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(255*128)
+
+ .balign 128
+ SIZE(SYMBOL(artMterpAsmAltInstructionStart),SYMBOL(artMterpAsmAltInstructionStart))
+ .global SYMBOL(artMterpAsmAltInstructionEnd)
+SYMBOL(artMterpAsmAltInstructionEnd):
+/* File: x86_64/footer.S */
+/*
+ * ===========================================================================
+ * Common subroutines and data
+ * ===========================================================================
+ */
+
+ .text
+ .align 2
+
+/*
+ * We've detected a condition that will result in an exception, but the exception
+ * has not yet been thrown. Just bail out to the reference interpreter to deal with it.
+ * TUNING: for consistency, we may want to just go ahead and handle these here.
+ */
+common_errDivideByZero:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogDivideByZeroException)
+#endif
+ jmp MterpCommonFallback
+
+common_errArrayIndex:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogArrayIndexException)
+#endif
+ jmp MterpCommonFallback
+
+common_errNegativeArraySize:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogNegativeArraySizeException)
+#endif
+ jmp MterpCommonFallback
+
+common_errNoSuchMethod:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogNoSuchMethodException)
+#endif
+ jmp MterpCommonFallback
+
+common_errNullObject:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogNullObjectException)
+#endif
+ jmp MterpCommonFallback
+
+common_exceptionThrown:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogExceptionThrownException)
+#endif
+ jmp MterpCommonFallback
+
+MterpSuspendFallback:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movl THREAD_FLAGS_OFFSET(rSELF), OUT_32_ARG2
+ call SYMBOL(MterpLogSuspendFallback)
+#endif
+ jmp MterpCommonFallback
+
+/*
+ * If we're here, something is out of the ordinary. If there is a pending
+ * exception, handle it. Otherwise, roll back and retry with the reference
+ * interpreter.
+ */
+MterpPossibleException:
+ cmpq $0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jz MterpFallback
+ /* intentional fallthrough - handle pending exception. */
+
+/*
+ * On return from a runtime helper routine, we've found a pending exception.
+ * Can we handle it here - or need to bail out to caller?
+ *
+ */
+MterpException:
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpHandleException)
+ testb %al, %al
+ jz MterpExceptionReturn
+ movq OFF_FP_CODE_ITEM(rFP), %rax
+ mov OFF_FP_DEX_PC(rFP), %ecx
+ leaq CODEITEM_INSNS_OFFSET(%rax), rPC
+ leaq (rPC, %rcx, 2), rPC
+ movq rPC, OFF_FP_DEX_PC_PTR(rFP)
+ /* Do we need to switch interpreters? */
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ /* resume execution at catch block */
+ REFRESH_IBASE
+ FETCH_INST
+ GOTO_NEXT
+ /* NOTE: no fallthrough */
+
+/*
+ * Check for suspend check request. Assumes rINST already loaded, rPC advanced and
+ * still needs to get the opcode and branch to it, and flags are in lr.
+ */
+MterpCheckSuspendAndContinue:
+ REFRESH_IBASE
+ testl $(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ GOTO_NEXT
+
+/*
+ * On-stack replacement has happened, and now we've returned from the compiled method.
+ */
+MterpOnStackReplacement:
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movl rINST, OUT_32_ARG2
+ call SYMBOL(MterpLogOSR)
+#endif
+ movl $1, %eax
+ jmp MterpDone
+
+/*
+ * Bail out to reference interpreter.
+ */
+MterpFallback:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogFallback)
+#endif
+MterpCommonFallback:
+ xorl %eax, %eax
+ jmp MterpDone
+
+/*
+ * On entry:
+ * uint32_t* rFP (should still be live, pointer to base of vregs)
+ */
+MterpExceptionReturn:
+ movl $1, %eax
+ jmp MterpDone
+MterpReturn:
+ movq OFF_FP_RESULT_REGISTER(rFP), %rdx
+ movq %rax, (%rdx)
+ movl $1, %eax
+MterpDone:
+ /* pop up frame */
+ addq $FRAME_SIZE, %rsp
+ .cfi_adjust_cfa_offset -FRAME_SIZE
+
+ /* Restore callee save register */
+ POP %r15
+ POP %r14
+ POP %r13
+ POP %r12
+ POP %rbp
+ POP %rbx
+ ret
+ .cfi_endproc
+ SIZE(ExecuteMterpImpl,ExecuteMterpImpl)
+
diff --git a/runtime/interpreter/mterp/rebuild.sh b/runtime/interpreter/mterp/rebuild.sh
index ac87945..ca3dcd9 100755
--- a/runtime/interpreter/mterp/rebuild.sh
+++ b/runtime/interpreter/mterp/rebuild.sh
@@ -20,5 +20,4 @@
#
set -e
-# for arch in arm x86 mips arm64 x86_64 mips64; do TARGET_ARCH_EXT=$arch make -f Makefile_mterp; done
-for arch in arm x86 arm64 ; do TARGET_ARCH_EXT=$arch make -f Makefile_mterp; done
+for arch in arm x86 mips arm64 x86_64 mips64; do TARGET_ARCH_EXT=$arch make -f Makefile_mterp; done
diff --git a/runtime/interpreter/mterp/x86/entry.S b/runtime/interpreter/mterp/x86/entry.S
index b83f7e1..785efdc 100644
--- a/runtime/interpreter/mterp/x86/entry.S
+++ b/runtime/interpreter/mterp/x86/entry.S
@@ -32,16 +32,18 @@
SYMBOL(ExecuteMterpImpl):
.cfi_startproc
+ .cfi_def_cfa esp, 4
+
+ /* Spill callee save regs */
+ PUSH %ebp
+ PUSH %edi
+ PUSH %esi
+ PUSH %ebx
+
/* Allocate frame */
subl $$FRAME_SIZE, %esp
.cfi_adjust_cfa_offset FRAME_SIZE
- /* Spill callee save regs */
- movl %ebp, EBP_SPILL(%esp)
- movl %edi, EDI_SPILL(%esp)
- movl %esi, ESI_SPILL(%esp)
- movl %ebx, EBX_SPILL(%esp)
-
/* Load ShadowFrame pointer */
movl IN_ARG2(%esp), %edx
diff --git a/runtime/interpreter/mterp/x86/footer.S b/runtime/interpreter/mterp/x86/footer.S
index 64d72d7..3965ecd 100644
--- a/runtime/interpreter/mterp/x86/footer.S
+++ b/runtime/interpreter/mterp/x86/footer.S
@@ -189,16 +189,15 @@
movl %ecx, 4(%edx)
mov $$1, %eax
MterpDone:
- /* Restore callee save register */
- movl EBP_SPILL(%esp), %ebp
- movl EDI_SPILL(%esp), %edi
- movl ESI_SPILL(%esp), %esi
- movl EBX_SPILL(%esp), %ebx
-
/* pop up frame */
addl $$FRAME_SIZE, %esp
.cfi_adjust_cfa_offset -FRAME_SIZE
- ret
+ /* Restore callee save register */
+ POP %ebx
+ POP %esi
+ POP %edi
+ POP %ebp
+ ret
.cfi_endproc
SIZE(ExecuteMterpImpl,ExecuteMterpImpl)
diff --git a/runtime/interpreter/mterp/x86/header.S b/runtime/interpreter/mterp/x86/header.S
index 6bddaf9..5729b90 100644
--- a/runtime/interpreter/mterp/x86/header.S
+++ b/runtime/interpreter/mterp/x86/header.S
@@ -105,25 +105,32 @@
#define SYMBOL(name) name
#endif
+.macro PUSH _reg
+ pushl \_reg
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset \_reg, 0
+.endm
+
+.macro POP _reg
+ popl \_reg
+ .cfi_adjust_cfa_offset -4
+ .cfi_restore \_reg
+.endm
+
/* Frame size must be 16-byte aligned.
- * Remember about 4 bytes for return address
+ * Remember about 4 bytes for return address + 4 * 4 for spills
*/
-#define FRAME_SIZE 44
+#define FRAME_SIZE 28
/* Frame diagram while executing ExecuteMterpImpl, high to low addresses */
-#define IN_ARG3 (FRAME_SIZE + 16)
-#define IN_ARG2 (FRAME_SIZE + 12)
-#define IN_ARG1 (FRAME_SIZE + 8)
-#define IN_ARG0 (FRAME_SIZE + 4)
-#define CALLER_RP (FRAME_SIZE + 0)
+#define IN_ARG3 (FRAME_SIZE + 16 + 16)
+#define IN_ARG2 (FRAME_SIZE + 16 + 12)
+#define IN_ARG1 (FRAME_SIZE + 16 + 8)
+#define IN_ARG0 (FRAME_SIZE + 16 + 4)
/* Spill offsets relative to %esp */
-#define EBP_SPILL (FRAME_SIZE - 4)
-#define EDI_SPILL (FRAME_SIZE - 8)
-#define ESI_SPILL (FRAME_SIZE - 12)
-#define EBX_SPILL (FRAME_SIZE - 16)
-#define LOCAL0 (FRAME_SIZE - 20)
-#define LOCAL1 (FRAME_SIZE - 24)
-#define LOCAL2 (FRAME_SIZE - 28)
+#define LOCAL0 (FRAME_SIZE - 4)
+#define LOCAL1 (FRAME_SIZE - 8)
+#define LOCAL2 (FRAME_SIZE - 12)
/* Out Arg offsets, relative to %esp */
#define OUT_ARG3 ( 12)
#define OUT_ARG2 ( 8)
diff --git a/runtime/interpreter/mterp/x86_64/alt_stub.S b/runtime/interpreter/mterp/x86_64/alt_stub.S
new file mode 100644
index 0000000..6fcebbb
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/alt_stub.S
@@ -0,0 +1,17 @@
+/*
+ * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle
+ * any interesting requests and then jump to the real instruction
+ * handler. Unlike the Arm handler, we can't do this as a tail call
+ * because rIBASE is caller save and we need to reload it.
+ *
+ * Note that unlike in the Arm implementation, we should never arrive
+ * here with a zero breakFlag because we always refresh rIBASE on
+ * return.
+ */
+ .extern MterpCheckBefore
+ EXPORT_PC
+ REFRESH_IBASE
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpCheckBefore) # (self, shadow_frame)
+ jmp .L_op_nop+(${opnum}*${handler_size_bytes})
diff --git a/runtime/interpreter/mterp/x86_64/bincmp.S b/runtime/interpreter/mterp/x86_64/bincmp.S
new file mode 100644
index 0000000..a16050b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/bincmp.S
@@ -0,0 +1,23 @@
+/*
+ * Generic two-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+ */
+ /* if-cmp vA, vB, +CCCC */
+ movl rINST, %ecx # rcx <- A+
+ sarl $$4, rINST # rINST <- B
+ andb $$0xf, %cl # rcx <- A
+ GET_VREG %eax, %rcx # eax <- vA
+ cmpl VREG_ADDRESS(rINSTq), %eax # compare (vA, vB)
+ movl $$2, rINST # assume not taken
+ j${revcmp} 1f
+ movswq 2(rPC), rINSTq # Get signed branch offset
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rax <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
diff --git a/runtime/interpreter/mterp/x86_64/bindiv.S b/runtime/interpreter/mterp/x86_64/bindiv.S
new file mode 100644
index 0000000..e10d1dc
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/bindiv.S
@@ -0,0 +1,34 @@
+%default {"result":"","second":"","wide":"","suffix":"","rem":"0","ext":"cdq"}
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ .if $wide
+ GET_WIDE_VREG %rax, %rax # eax <- vBB
+ GET_WIDE_VREG $second, %rcx # ecx <- vCC
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ GET_VREG $second, %rcx # ecx <- vCC
+ .endif
+ test${suffix} $second, $second
+ jz common_errDivideByZero
+ cmp${suffix} $$-1, $second
+ je 2f
+ $ext # rdx:rax <- sign-extended of rax
+ idiv${suffix} $second
+1:
+ .if $wide
+ SET_WIDE_VREG $result, rINSTq # eax <- vBB
+ .else
+ SET_VREG $result, rINSTq # eax <- vBB
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if $rem
+ xor${suffix} $result, $result
+ .else
+ neg${suffix} $result
+ .endif
+ jmp 1b
diff --git a/runtime/interpreter/mterp/x86_64/bindiv2addr.S b/runtime/interpreter/mterp/x86_64/bindiv2addr.S
new file mode 100644
index 0000000..8b9bc95
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/bindiv2addr.S
@@ -0,0 +1,35 @@
+%default {"result":"","second":"","wide":"","suffix":"","rem":"0","ext":"cdq"}
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem/2addr vA, vB */
+ movl rINST, %ecx # rcx <- BA
+ sarl $$4, %ecx # rcx <- B
+ andb $$0xf, rINSTbl # rINST <- A
+ .if $wide
+ GET_WIDE_VREG %rax, rINSTq # eax <- vA
+ GET_WIDE_VREG $second, %rcx # ecx <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vA
+ GET_VREG $second, %rcx # ecx <- vB
+ .endif
+ test${suffix} $second, $second
+ jz common_errDivideByZero
+ cmp${suffix} $$-1, $second
+ je 2f
+ $ext # rdx:rax <- sign-extended of rax
+ idiv${suffix} $second
+1:
+ .if $wide
+ SET_WIDE_VREG $result, rINSTq # vA <- result
+ .else
+ SET_VREG $result, rINSTq # vA <- result
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+2:
+ .if $rem
+ xor${suffix} $result, $result
+ .else
+ neg${suffix} $result
+ .endif
+ jmp 1b
diff --git a/runtime/interpreter/mterp/x86_64/bindivLit16.S b/runtime/interpreter/mterp/x86_64/bindivLit16.S
new file mode 100644
index 0000000..80dbce2
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/bindivLit16.S
@@ -0,0 +1,27 @@
+%default {"result":"","rem":"0"}
+/*
+ * 32-bit binary div/rem operation. Handles special case of op1=-1.
+ */
+ /* div/rem/lit16 vA, vB, #+CCCC */
+ /* Need A in rINST, ssssCCCC in ecx, vB in eax */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $$4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ andb $$0xf, rINSTbl # rINST <- A
+ testl %ecx, %ecx
+ jz common_errDivideByZero
+ cmpl $$-1, %ecx
+ je 2f
+ cdq # rax <- sign-extended of eax
+ idivl %ecx
+1:
+ SET_VREG $result, rINSTq # vA <- result
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if $rem
+ xorl $result, $result
+ .else
+ negl $result
+ .endif
+ jmp 1b
diff --git a/runtime/interpreter/mterp/x86_64/bindivLit8.S b/runtime/interpreter/mterp/x86_64/bindivLit8.S
new file mode 100644
index 0000000..ab535f3
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/bindivLit8.S
@@ -0,0 +1,25 @@
+%default {"result":"","rem":"0"}
+/*
+ * 32-bit div/rem "lit8" binary operation. Handles special case of
+ * op0=minint & op1=-1
+ */
+ /* div/rem/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movsbl 3(rPC), %ecx # ecx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ testl %ecx, %ecx
+ je common_errDivideByZero
+ cmpl $$-1, %ecx
+ je 2f
+ cdq # rax <- sign-extended of eax
+ idivl %ecx
+1:
+ SET_VREG $result, rINSTq # vA <- result
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
+2:
+ .if $rem
+ xorl $result, $result
+ .else
+ negl $result
+ .endif
+ jmp 1b
diff --git a/runtime/interpreter/mterp/x86_64/binop.S b/runtime/interpreter/mterp/x86_64/binop.S
new file mode 100644
index 0000000..962dd61
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/binop.S
@@ -0,0 +1,17 @@
+%default {"result":"%eax"}
+/*
+ * Generic 32-bit binary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int, sub-int, and-int, or-int,
+ * xor-int, shl-int, shr-int, ushr-int
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB
+ $instr # ex: addl (rFP,%rcx,4),%eax
+ SET_VREG $result, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/binop1.S b/runtime/interpreter/mterp/x86_64/binop1.S
new file mode 100644
index 0000000..bdd5732
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/binop1.S
@@ -0,0 +1,19 @@
+%default {"wide":"0"}
+/*
+ * Generic 32-bit binary operation in which both operands loaded to
+ * registers (op0 in eax, op1 in ecx).
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %ecx, %rcx # eax <- vCC
+ .if $wide
+ GET_WIDE_VREG %rax, %rax # rax <- vBB
+ $instr # ex: addl %ecx,%eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, %rax # eax <- vBB
+ $instr # ex: addl %ecx,%eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/binop2addr.S b/runtime/interpreter/mterp/x86_64/binop2addr.S
new file mode 100644
index 0000000..4448a81
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/binop2addr.S
@@ -0,0 +1,19 @@
+%default {"result":"%eax"}
+/*
+ * Generic 32-bit "/2addr" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = r0 op r1".
+ * This could be an instruction or a function call.
+ *
+ * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+ * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+ * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+ * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $$4, rINST # rINST <- B
+ andb $$0xf, %cl # ecx <- A
+ GET_VREG %eax, rINSTq # eax <- vB
+ $instr # for ex: addl %eax,(rFP,%ecx,4)
+ CLEAR_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/binopLit16.S b/runtime/interpreter/mterp/x86_64/binopLit16.S
new file mode 100644
index 0000000..de43b53
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/binopLit16.S
@@ -0,0 +1,19 @@
+%default {"result":"%eax"}
+/*
+ * Generic 32-bit "lit16" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than eax, you can override "result".)
+ *
+ * For: add-int/lit16, rsub-int,
+ * and-int/lit16, or-int/lit16, xor-int/lit16
+ */
+ /* binop/lit16 vA, vB, #+CCCC */
+ movl rINST, %eax # rax <- 000000BA
+ sarl $$4, %eax # eax <- B
+ GET_VREG %eax, %rax # eax <- vB
+ andb $$0xf, rINSTbl # rINST <- A
+ movswl 2(rPC), %ecx # ecx <- ssssCCCC
+ $instr # for example: addl %ecx, %eax
+ SET_VREG $result, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/binopLit8.S b/runtime/interpreter/mterp/x86_64/binopLit8.S
new file mode 100644
index 0000000..995002b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/binopLit8.S
@@ -0,0 +1,18 @@
+%default {"result":"%eax"}
+/*
+ * Generic 32-bit "lit8" binary operation. Provide an "instr" line
+ * that specifies an instruction that performs "result = eax op ecx".
+ * This could be an x86 instruction or a function call. (If the result
+ * comes back in a register other than r0, you can override "result".)
+ *
+ * For: add-int/lit8, rsub-int/lit8
+ * and-int/lit8, or-int/lit8, xor-int/lit8,
+ * shl-int/lit8, shr-int/lit8, ushr-int/lit8
+ */
+ /* binop/lit8 vAA, vBB, #+CC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movsbl 3(rPC), %ecx # rcx <- ssssssCC
+ GET_VREG %eax, %rax # eax <- rBB
+ $instr # ex: addl %ecx,%eax
+ SET_VREG $result, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/binopWide.S b/runtime/interpreter/mterp/x86_64/binopWide.S
new file mode 100644
index 0000000..f92f18e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/binopWide.S
@@ -0,0 +1,10 @@
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_WIDE_VREG %rax, %rax # rax <- v[BB]
+ $instr # ex: addq (rFP,%rcx,4),%rax
+ SET_WIDE_VREG %rax, rINSTq # v[AA] <- rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/binopWide2addr.S b/runtime/interpreter/mterp/x86_64/binopWide2addr.S
new file mode 100644
index 0000000..d9e6cfb
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/binopWide2addr.S
@@ -0,0 +1,11 @@
+/*
+ * Generic 64-bit binary operation.
+ */
+ /* binop/2addr vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $$4, rINST # rINST <- B
+ andb $$0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ $instr # for ex: addq %rax,(rFP,%rcx,4)
+ CLEAR_WIDE_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/cvtfp_int.S b/runtime/interpreter/mterp/x86_64/cvtfp_int.S
new file mode 100644
index 0000000..1472bd2
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/cvtfp_int.S
@@ -0,0 +1,27 @@
+%default {"fp_suffix":"","i_suffix":"","max_const":"","result_reg":"","wide":""}
+/* On fp to int conversions, Java requires that
+ * if the result > maxint, it should be clamped to maxint. If it is less
+ * than minint, it should be clamped to minint. If it is a nan, the result
+ * should be zero. Further, the rounding mode is to truncate.
+ */
+ /* float/double to int/long vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $$4, rINST # rINST <- B
+ andb $$0xf, %cl # ecx <- A
+ movs${fp_suffix} VREG_ADDRESS(rINSTq), %xmm0
+ mov${i_suffix} ${max_const}, ${result_reg}
+ cvtsi2s${fp_suffix}${i_suffix} ${result_reg}, %xmm1
+ comis${fp_suffix} %xmm1, %xmm0
+ jae 1f
+ jp 2f
+ cvtts${fp_suffix}2si${i_suffix} %xmm0, ${result_reg}
+ jmp 1f
+2:
+ xor${i_suffix} ${result_reg}, ${result_reg}
+1:
+ .if $wide
+ SET_WIDE_VREG ${result_reg}, %rcx
+ .else
+ SET_VREG ${result_reg}, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/entry.S b/runtime/interpreter/mterp/x86_64/entry.S
new file mode 100644
index 0000000..69b2371
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/entry.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Interpreter entry point.
+ */
+
+ .text
+ .global SYMBOL(ExecuteMterpImpl)
+ FUNCTION_TYPE(ExecuteMterpImpl)
+
+/*
+ * On entry:
+ * 0 Thread* self
+ * 1 code_item
+ * 2 ShadowFrame
+ * 3 JValue* result_register
+ *
+ */
+
+SYMBOL(ExecuteMterpImpl):
+ .cfi_startproc
+ .cfi_def_cfa rsp, 8
+
+ /* Spill callee save regs */
+ PUSH %rbx
+ PUSH %rbp
+ PUSH %r12
+ PUSH %r13
+ PUSH %r14
+ PUSH %r15
+
+ /* Allocate frame */
+ subq $$FRAME_SIZE, %rsp
+ .cfi_adjust_cfa_offset FRAME_SIZE
+
+ /* Remember the return register */
+ movq IN_ARG3, SHADOWFRAME_RESULT_REGISTER_OFFSET(IN_ARG2)
+
+ /* Remember the code_item */
+ movq IN_ARG1, SHADOWFRAME_CODE_ITEM_OFFSET(IN_ARG2)
+
+ /* set up "named" registers */
+ movl SHADOWFRAME_NUMBER_OF_VREGS_OFFSET(IN_ARG2), %eax
+ leaq SHADOWFRAME_VREGS_OFFSET(IN_ARG2), rFP
+ leaq (rFP, %rax, 4), rREFS
+ movl SHADOWFRAME_DEX_PC_OFFSET(IN_ARG2), %eax
+ leaq CODEITEM_INSNS_OFFSET(IN_ARG1), rPC
+ leaq (rPC, %rax, 2), rPC
+ EXPORT_PC
+
+ /* Starting ibase */
+ movq IN_ARG0, rSELF
+ REFRESH_IBASE
+
+ /* start executing the instruction at rPC */
+ FETCH_INST
+ GOTO_NEXT
+ /* NOTE: no fallthrough */
diff --git a/runtime/interpreter/mterp/x86_64/fallback.S b/runtime/interpreter/mterp/x86_64/fallback.S
new file mode 100644
index 0000000..8d61166
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/fallback.S
@@ -0,0 +1,3 @@
+/* Transfer stub to alternate interpreter */
+ jmp MterpFallback
+
diff --git a/runtime/interpreter/mterp/x86_64/footer.S b/runtime/interpreter/mterp/x86_64/footer.S
new file mode 100644
index 0000000..573256b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/footer.S
@@ -0,0 +1,181 @@
+/*
+ * ===========================================================================
+ * Common subroutines and data
+ * ===========================================================================
+ */
+
+ .text
+ .align 2
+
+/*
+ * We've detected a condition that will result in an exception, but the exception
+ * has not yet been thrown. Just bail out to the reference interpreter to deal with it.
+ * TUNING: for consistency, we may want to just go ahead and handle these here.
+ */
+common_errDivideByZero:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogDivideByZeroException)
+#endif
+ jmp MterpCommonFallback
+
+common_errArrayIndex:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogArrayIndexException)
+#endif
+ jmp MterpCommonFallback
+
+common_errNegativeArraySize:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogNegativeArraySizeException)
+#endif
+ jmp MterpCommonFallback
+
+common_errNoSuchMethod:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogNoSuchMethodException)
+#endif
+ jmp MterpCommonFallback
+
+common_errNullObject:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogNullObjectException)
+#endif
+ jmp MterpCommonFallback
+
+common_exceptionThrown:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogExceptionThrownException)
+#endif
+ jmp MterpCommonFallback
+
+MterpSuspendFallback:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movl THREAD_FLAGS_OFFSET(rSELF), OUT_32_ARG2
+ call SYMBOL(MterpLogSuspendFallback)
+#endif
+ jmp MterpCommonFallback
+
+/*
+ * If we're here, something is out of the ordinary. If there is a pending
+ * exception, handle it. Otherwise, roll back and retry with the reference
+ * interpreter.
+ */
+MterpPossibleException:
+ cmpq $$0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jz MterpFallback
+ /* intentional fallthrough - handle pending exception. */
+
+/*
+ * On return from a runtime helper routine, we've found a pending exception.
+ * Can we handle it here - or need to bail out to caller?
+ *
+ */
+MterpException:
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpHandleException)
+ testb %al, %al
+ jz MterpExceptionReturn
+ movq OFF_FP_CODE_ITEM(rFP), %rax
+ mov OFF_FP_DEX_PC(rFP), %ecx
+ leaq CODEITEM_INSNS_OFFSET(%rax), rPC
+ leaq (rPC, %rcx, 2), rPC
+ movq rPC, OFF_FP_DEX_PC_PTR(rFP)
+ /* Do we need to switch interpreters? */
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ /* resume execution at catch block */
+ REFRESH_IBASE
+ FETCH_INST
+ GOTO_NEXT
+ /* NOTE: no fallthrough */
+
+/*
+ * Check for suspend check request. Assumes rINST already loaded, rPC advanced and
+ * still needs to get the opcode and branch to it, and flags are in lr.
+ */
+MterpCheckSuspendAndContinue:
+ REFRESH_IBASE
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ GOTO_NEXT
+
+/*
+ * On-stack replacement has happened, and now we've returned from the compiled method.
+ */
+MterpOnStackReplacement:
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movl rINST, OUT_32_ARG2
+ call SYMBOL(MterpLogOSR)
+#endif
+ movl $$1, %eax
+ jmp MterpDone
+
+/*
+ * Bail out to reference interpreter.
+ */
+MterpFallback:
+ EXPORT_PC
+#if MTERP_LOGGING
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ call SYMBOL(MterpLogFallback)
+#endif
+MterpCommonFallback:
+ xorl %eax, %eax
+ jmp MterpDone
+
+/*
+ * On entry:
+ * uint32_t* rFP (should still be live, pointer to base of vregs)
+ */
+MterpExceptionReturn:
+ movl $$1, %eax
+ jmp MterpDone
+MterpReturn:
+ movq OFF_FP_RESULT_REGISTER(rFP), %rdx
+ movq %rax, (%rdx)
+ movl $$1, %eax
+MterpDone:
+ /* pop up frame */
+ addq $$FRAME_SIZE, %rsp
+ .cfi_adjust_cfa_offset -FRAME_SIZE
+
+ /* Restore callee save register */
+ POP %r15
+ POP %r14
+ POP %r13
+ POP %r12
+ POP %rbp
+ POP %rbx
+ ret
+ .cfi_endproc
+ SIZE(ExecuteMterpImpl,ExecuteMterpImpl)
diff --git a/runtime/interpreter/mterp/x86_64/fpcmp.S b/runtime/interpreter/mterp/x86_64/fpcmp.S
new file mode 100644
index 0000000..806bc2b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/fpcmp.S
@@ -0,0 +1,35 @@
+%default {"suff":"d","nanval":"pos"}
+/*
+ * Compare two floating-point values. Puts 0, 1, or -1 into the
+ * destination register based on the results of the comparison.
+ *
+ * int compare(x, y) {
+ * if (x == y) {
+ * return 0;
+ * } else if (x < y) {
+ * return -1;
+ * } else if (x > y) {
+ * return 1;
+ * } else {
+ * return nanval ? 1 : -1;
+ * }
+ * }
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 3(rPC), %rcx # ecx<- CC
+ movzbq 2(rPC), %rax # eax<- BB
+ movs${suff} VREG_ADDRESS(%rax), %xmm0
+ xor %eax, %eax
+ ucomis${suff} VREG_ADDRESS(%rcx), %xmm0
+ jp .L${opcode}_nan_is_${nanval}
+ je .L${opcode}_finish
+ jb .L${opcode}_less
+.L${opcode}_nan_is_pos:
+ addb $$1, %al
+ jmp .L${opcode}_finish
+.L${opcode}_nan_is_neg:
+.L${opcode}_less:
+ movl $$-1, %eax
+.L${opcode}_finish:
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/fpcvt.S b/runtime/interpreter/mterp/x86_64/fpcvt.S
new file mode 100644
index 0000000..657869e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/fpcvt.S
@@ -0,0 +1,17 @@
+%default {"source_suffix":"","dest_suffix":"","wide":""}
+/*
+ * Generic 32-bit FP conversion operation.
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $$4, rINST # rINST <- B
+ andb $$0xf, %cl # ecx <- A
+ cvts${source_suffix}2s${dest_suffix} VREG_ADDRESS(rINSTq), %xmm0
+ .if $wide
+ movsd %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_WIDE_REF %rcx
+ .else
+ movss %xmm0, VREG_ADDRESS(%rcx)
+ CLEAR_REF %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/header.S b/runtime/interpreter/mterp/x86_64/header.S
new file mode 100644
index 0000000..eb84ea1
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/header.S
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ Art assembly interpreter notes:
+
+ First validate assembly code by implementing ExecuteXXXImpl() style body (doesn't
+ handle invoke, allows higher-level code to create frame & shadow frame.
+
+ Once that's working, support direct entry code & eliminate shadow frame (and
+ excess locals allocation.
+
+ Some (hopefully) temporary ugliness. We'll treat rFP as pointing to the
+ base of the vreg array within the shadow frame. Access the other fields,
+ dex_pc_, method_ and number_of_vregs_ via negative offsets. For now, we'll continue
+ the shadow frame mechanism of double-storing object references - via rFP &
+ number_of_vregs_.
+
+ */
+
+/*
+x86_64 ABI general notes:
+
+Caller save set:
+ rax, rdx, rcx, rsi, rdi, r8-r11, st(0)-st(7)
+Callee save set:
+ rbx, rbp, r12-r15
+Return regs:
+ 32-bit in eax
+ 64-bit in rax
+ fp on xmm0
+
+First 8 fp parameters came in xmm0-xmm7.
+First 6 non-fp parameters came in rdi, rsi, rdx, rcx, r8, r9.
+Other parameters passed on stack, pushed right-to-left. On entry to target, first
+param is at 8(%esp). Traditional entry code is:
+
+Stack must be 16-byte aligned to support SSE in native code.
+
+If we're not doing variable stack allocation (alloca), the frame pointer can be
+eliminated and all arg references adjusted to be esp relative.
+*/
+
+/*
+Mterp and x86_64 notes:
+
+Some key interpreter variables will be assigned to registers.
+
+ nick reg purpose
+ rSELF rbp pointer to ThreadSelf.
+ rPC r12 interpreted program counter, used for fetching instructions
+ rFP r13 interpreted frame pointer, used for accessing locals and args
+ rINSTw bx first 16-bit code of current instruction
+ rINSTbl bl opcode portion of instruction word
+ rINSTbh bh high byte of inst word, usually contains src/tgt reg names
+ rIBASE r14 base of instruction handler table
+ rREFS r15 base of object references in shadow frame.
+
+Notes:
+ o High order 16 bits of ebx must be zero on entry to handler
+ o rPC, rFP, rINSTw/rINSTbl valid on handler entry and exit
+ o eax and ecx are scratch, rINSTw/ebx sometimes scratch
+
+Macros are provided for common operations. Each macro MUST emit only
+one instruction to make instruction-counting easier. They MUST NOT alter
+unspecified registers or condition codes.
+*/
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "asm_support.h"
+
+/*
+ * Handle mac compiler specific
+ */
+#if defined(__APPLE__)
+ #define MACRO_LITERAL(value) $$(value)
+ #define FUNCTION_TYPE(name)
+ #define SIZE(start,end)
+ // Mac OS' symbols have an _ prefix.
+ #define SYMBOL(name) _ ## name
+#else
+ #define MACRO_LITERAL(value) $$value
+ #define FUNCTION_TYPE(name) .type name, @function
+ #define SIZE(start,end) .size start, .-end
+ #define SYMBOL(name) name
+#endif
+
+.macro PUSH _reg
+ pushq \_reg
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset \_reg, 0
+.endm
+
+.macro POP _reg
+ popq \_reg
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore \_reg
+.endm
+
+/* Frame size must be 16-byte aligned.
+ * Remember about 8 bytes for return address + 6 * 8 for spills.
+ */
+#define FRAME_SIZE 8
+
+/* Frame diagram while executing ExecuteMterpImpl, high to low addresses */
+#define IN_ARG3 %rcx
+#define IN_ARG2 %rdx
+#define IN_ARG1 %rsi
+#define IN_ARG0 %rdi
+/* Out Args */
+#define OUT_ARG3 %rcx
+#define OUT_ARG2 %rdx
+#define OUT_ARG1 %rsi
+#define OUT_ARG0 %rdi
+#define OUT_32_ARG3 %ecx
+#define OUT_32_ARG2 %edx
+#define OUT_32_ARG1 %esi
+#define OUT_32_ARG0 %edi
+#define OUT_FP_ARG1 %xmm1
+#define OUT_FP_ARG0 %xmm0
+
+/* During bringup, we'll use the shadow frame model instead of rFP */
+/* single-purpose registers, given names for clarity */
+#define rSELF %rbp
+#define rPC %r12
+#define rFP %r13
+#define rINST %ebx
+#define rINSTq %rbx
+#define rINSTw %bx
+#define rINSTbh %bh
+#define rINSTbl %bl
+#define rIBASE %r14
+#define rREFS %r15
+
+/*
+ * Instead of holding a pointer to the shadow frame, we keep rFP at the base of the vregs. So,
+ * to access other shadow frame fields, we need to use a backwards offset. Define those here.
+ */
+#define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET)
+#define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET)
+#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET)
+#define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET)
+#define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET)
+#define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET)
+#define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET)
+#define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET)
+#define OFF_FP_SHADOWFRAME (-SHADOWFRAME_VREGS_OFFSET)
+
+#define MTERP_PROFILE_BRANCHES 1
+#define MTERP_LOGGING 0
+
+/*
+ * Profile branch. rINST should contain the offset. %eax is scratch.
+ */
+.macro MTERP_PROFILE_BRANCH
+#ifdef MTERP_PROFILE_BRANCHES
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movl rINST, OUT_32_ARG2
+ call SYMBOL(MterpProfileBranch)
+ testb %al, %al
+ jnz MterpOnStackReplacement
+#endif
+.endm
+
+/*
+ * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must
+ * be done *before* something throws.
+ *
+ * It's okay to do this more than once.
+ *
+ * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped
+ * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction
+ * offset into the code_items_[] array. For effiency, we will "export" the
+ * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC
+ * to convert to a dex pc when needed.
+ */
+.macro EXPORT_PC
+ movq rPC, OFF_FP_DEX_PC_PTR(rFP)
+.endm
+
+/*
+ * Refresh handler table.
+ * IBase handles uses the caller save register so we must restore it after each call.
+ * Also it is used as a result of some 64-bit operations (like imul) and we should
+ * restore it in such cases also.
+ *
+ */
+.macro REFRESH_IBASE
+ movq THREAD_CURRENT_IBASE_OFFSET(rSELF), rIBASE
+.endm
+
+/*
+ * Refresh rINST.
+ * At enter to handler rINST does not contain the opcode number.
+ * However some utilities require the full value, so this macro
+ * restores the opcode number.
+ */
+.macro REFRESH_INST _opnum
+ movb rINSTbl, rINSTbh
+ movb $$\_opnum, rINSTbl
+.endm
+
+/*
+ * Fetch the next instruction from rPC into rINSTw. Does not advance rPC.
+ */
+.macro FETCH_INST
+ movzwq (rPC), rINSTq
+.endm
+
+/*
+ * Remove opcode from rINST, compute the address of handler and jump to it.
+ */
+.macro GOTO_NEXT
+ movzx rINSTbl,%eax
+ movzbl rINSTbh,rINST
+ shll MACRO_LITERAL(${handler_size_bits}), %eax
+ addq rIBASE, %rax
+ jmp *%rax
+.endm
+
+/*
+ * Advance rPC by instruction count.
+ */
+.macro ADVANCE_PC _count
+ leaq 2*\_count(rPC), rPC
+.endm
+
+/*
+ * Advance rPC by instruction count, fetch instruction and jump to handler.
+ */
+.macro ADVANCE_PC_FETCH_AND_GOTO_NEXT _count
+ ADVANCE_PC \_count
+ FETCH_INST
+ GOTO_NEXT
+.endm
+
+/*
+ * Get/set the 32-bit value from a Dalvik register.
+ */
+#define VREG_ADDRESS(_vreg) (rFP,_vreg,4)
+#define VREG_REF_ADDRESS(_vreg) (rREFS,_vreg,4)
+
+.macro GET_VREG _reg _vreg
+ movl (rFP,\_vreg,4), \_reg
+.endm
+
+/* Read wide value. */
+.macro GET_WIDE_VREG _reg _vreg
+ movq (rFP,\_vreg,4), \_reg
+.endm
+
+.macro SET_VREG _reg _vreg
+ movl \_reg, (rFP,\_vreg,4)
+ movl MACRO_LITERAL(0), (rREFS,\_vreg,4)
+.endm
+
+/* Write wide value. reg is clobbered. */
+.macro SET_WIDE_VREG _reg _vreg
+ movq \_reg, (rFP,\_vreg,4)
+ xorq \_reg, \_reg
+ movq \_reg, (rREFS,\_vreg,4)
+.endm
+
+.macro SET_VREG_OBJECT _reg _vreg
+ movl \_reg, (rFP,\_vreg,4)
+ movl \_reg, (rREFS,\_vreg,4)
+.endm
+
+.macro GET_VREG_HIGH _reg _vreg
+ movl 4(rFP,\_vreg,4), \_reg
+.endm
+
+.macro SET_VREG_HIGH _reg _vreg
+ movl \_reg, 4(rFP,\_vreg,4)
+ movl MACRO_LITERAL(0), 4(rREFS,\_vreg,4)
+.endm
+
+.macro CLEAR_REF _vreg
+ movl MACRO_LITERAL(0), (rREFS,\_vreg,4)
+.endm
+
+.macro CLEAR_WIDE_REF _vreg
+ movl MACRO_LITERAL(0), (rREFS,\_vreg,4)
+ movl MACRO_LITERAL(0), 4(rREFS,\_vreg,4)
+.endm
diff --git a/runtime/interpreter/mterp/x86_64/invoke.S b/runtime/interpreter/mterp/x86_64/invoke.S
new file mode 100644
index 0000000..f7e6155
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/invoke.S
@@ -0,0 +1,22 @@
+%default { "helper":"UndefinedInvokeHandler" }
+/*
+ * Generic invoke handler wrapper.
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+ .extern $helper
+ EXPORT_PC
+ movq rSELF, OUT_ARG0
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
+ movq rPC, OUT_ARG2
+ REFRESH_INST ${opnum}
+ movl rINST, OUT_32_ARG3
+ call SYMBOL($helper)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC 3
+ call SYMBOL(MterpShouldSwitchInterpreters)
+ testb %al, %al
+ jnz MterpFallback
+ FETCH_INST
+ GOTO_NEXT
diff --git a/runtime/interpreter/mterp/x86_64/op_add_double.S b/runtime/interpreter/mterp/x86_64/op_add_double.S
new file mode 100644
index 0000000..cb462cb
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_double.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop.S" {"instr":"adds","suff":"d"}
diff --git a/runtime/interpreter/mterp/x86_64/op_add_double_2addr.S b/runtime/interpreter/mterp/x86_64/op_add_double_2addr.S
new file mode 100644
index 0000000..063bde3
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_double_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop2Addr.S" {"instr":"adds","suff":"d"}
diff --git a/runtime/interpreter/mterp/x86_64/op_add_float.S b/runtime/interpreter/mterp/x86_64/op_add_float.S
new file mode 100644
index 0000000..7753bf8
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_float.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop.S" {"instr":"adds","suff":"s"}
diff --git a/runtime/interpreter/mterp/x86_64/op_add_float_2addr.S b/runtime/interpreter/mterp/x86_64/op_add_float_2addr.S
new file mode 100644
index 0000000..6c8005b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_float_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop2Addr.S" {"instr":"adds","suff":"s"}
diff --git a/runtime/interpreter/mterp/x86_64/op_add_int.S b/runtime/interpreter/mterp/x86_64/op_add_int.S
new file mode 100644
index 0000000..e316be7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_int.S
@@ -0,0 +1 @@
+%include "x86_64/binop.S" {"instr":"addl (rFP,%rcx,4), %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_add_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_add_int_2addr.S
new file mode 100644
index 0000000..2ff8293
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binop2addr.S" {"instr":"addl %eax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/op_add_int_lit16.S b/runtime/interpreter/mterp/x86_64/op_add_int_lit16.S
new file mode 100644
index 0000000..bfeb7ca
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_int_lit16.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit16.S" {"instr":"addl %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_add_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_add_int_lit8.S
new file mode 100644
index 0000000..8954844
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit8.S" {"instr":"addl %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_add_long.S b/runtime/interpreter/mterp/x86_64/op_add_long.S
new file mode 100644
index 0000000..89131ff
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_long.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide.S" {"instr":"addq (rFP,%rcx,4), %rax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_add_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_add_long_2addr.S
new file mode 100644
index 0000000..fed98bc
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_add_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide2addr.S" {"instr":"addq %rax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/op_aget.S b/runtime/interpreter/mterp/x86_64/op_aget.S
new file mode 100644
index 0000000..58d4948
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aget.S
@@ -0,0 +1,24 @@
+%default { "load":"movl", "shift":"4", "data_offset":"MIRROR_INT_ARRAY_DATA_OFFSET", "wide":"0" }
+/*
+ * Array get, 32 bits or less. vAA <- vBB[vCC].
+ *
+ * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # eax <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if $wide
+ movq $data_offset(%rax,%rcx,8), %rax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ $load $data_offset(%rax,%rcx,$shift), %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_aget_boolean.S b/runtime/interpreter/mterp/x86_64/op_aget_boolean.S
new file mode 100644
index 0000000..cf7bdb5
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aget_boolean.S
@@ -0,0 +1 @@
+%include "x86_64/op_aget.S" { "load":"movzbl", "shift":"1", "data_offset":"MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/x86_64/op_aget_byte.S b/runtime/interpreter/mterp/x86_64/op_aget_byte.S
new file mode 100644
index 0000000..1cbb569
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aget_byte.S
@@ -0,0 +1 @@
+%include "x86_64/op_aget.S" { "load":"movsbl", "shift":"1", "data_offset":"MIRROR_BYTE_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/x86_64/op_aget_char.S b/runtime/interpreter/mterp/x86_64/op_aget_char.S
new file mode 100644
index 0000000..45c9085
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aget_char.S
@@ -0,0 +1 @@
+%include "x86_64/op_aget.S" { "load":"movzwl", "shift":"2", "data_offset":"MIRROR_CHAR_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/x86_64/op_aget_object.S b/runtime/interpreter/mterp/x86_64/op_aget_object.S
new file mode 100644
index 0000000..8baedea
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aget_object.S
@@ -0,0 +1,16 @@
+/*
+ * Array object get. vAA <- vBB[vCC].
+ *
+ * for: aget-object
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG OUT_32_ARG0, %rax # eax <- vBB (array object)
+ GET_VREG OUT_32_ARG1, %rcx # ecx <- vCC (requested index)
+ EXPORT_PC
+ call SYMBOL(artAGetObjectFromMterp) # (array, index)
+ cmpq $$0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ SET_VREG_OBJECT %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_aget_short.S b/runtime/interpreter/mterp/x86_64/op_aget_short.S
new file mode 100644
index 0000000..82c4a1d
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aget_short.S
@@ -0,0 +1 @@
+%include "x86_64/op_aget.S" { "load":"movswl", "shift":"2", "data_offset":"MIRROR_SHORT_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/x86_64/op_aget_wide.S b/runtime/interpreter/mterp/x86_64/op_aget_wide.S
new file mode 100644
index 0000000..4f2771b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aget_wide.S
@@ -0,0 +1 @@
+%include "x86_64/op_aget.S" { "load":"movq", "shift":"8", "data_offset":"MIRROR_WIDE_ARRAY_DATA_OFFSET", "wide":"1" }
diff --git a/runtime/interpreter/mterp/x86_64/op_and_int.S b/runtime/interpreter/mterp/x86_64/op_and_int.S
new file mode 100644
index 0000000..4469889
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_and_int.S
@@ -0,0 +1 @@
+%include "x86_64/binop.S" {"instr":"andl (rFP,%rcx,4), %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_and_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_and_int_2addr.S
new file mode 100644
index 0000000..16315bb
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_and_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binop2addr.S" {"instr":"andl %eax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/op_and_int_lit16.S b/runtime/interpreter/mterp/x86_64/op_and_int_lit16.S
new file mode 100644
index 0000000..63e851b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_and_int_lit16.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit16.S" {"instr":"andl %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_and_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_and_int_lit8.S
new file mode 100644
index 0000000..da7a20f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_and_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit8.S" {"instr":"andl %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_and_long.S b/runtime/interpreter/mterp/x86_64/op_and_long.S
new file mode 100644
index 0000000..ce1dd26
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_and_long.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide.S" {"instr":"andq (rFP,%rcx,4), %rax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_and_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_and_long_2addr.S
new file mode 100644
index 0000000..d17ab8d
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_and_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide2addr.S" {"instr":"andq %rax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/op_aput.S b/runtime/interpreter/mterp/x86_64/op_aput.S
new file mode 100644
index 0000000..11500ad
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aput.S
@@ -0,0 +1,23 @@
+%default { "reg":"rINST", "store":"movl", "shift":"4", "data_offset":"MIRROR_INT_ARRAY_DATA_OFFSET", "wide":"0" }
+/*
+ * Array put, 32 bits or less. vBB[vCC] <- vAA.
+ *
+ * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide
+ *
+ */
+ /* op vAA, vBB, vCC */
+ movzbq 2(rPC), %rax # rax <- BB
+ movzbq 3(rPC), %rcx # rcx <- CC
+ GET_VREG %eax, %rax # eax <- vBB (array object)
+ GET_VREG %ecx, %rcx # ecx <- vCC (requested index)
+ testl %eax, %eax # null array object?
+ je common_errNullObject # bail if so
+ cmpl MIRROR_ARRAY_LENGTH_OFFSET(%eax), %ecx
+ jae common_errArrayIndex # index >= length, bail.
+ .if $wide
+ GET_WIDE_VREG rINSTq, rINSTq
+ .else
+ GET_VREG rINST, rINSTq
+ .endif
+ $store $reg, $data_offset(%rax,%rcx,$shift)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_aput_boolean.S b/runtime/interpreter/mterp/x86_64/op_aput_boolean.S
new file mode 100644
index 0000000..7d77a86
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aput_boolean.S
@@ -0,0 +1 @@
+%include "x86_64/op_aput.S" { "reg":"rINSTbl", "store":"movb", "shift":"1", "data_offset":"MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/x86_64/op_aput_byte.S b/runtime/interpreter/mterp/x86_64/op_aput_byte.S
new file mode 100644
index 0000000..7a1723e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aput_byte.S
@@ -0,0 +1 @@
+%include "x86_64/op_aput.S" { "reg":"rINSTbl", "store":"movb", "shift":"1", "data_offset":"MIRROR_BYTE_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/x86_64/op_aput_char.S b/runtime/interpreter/mterp/x86_64/op_aput_char.S
new file mode 100644
index 0000000..f8f50a3
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aput_char.S
@@ -0,0 +1 @@
+%include "x86_64/op_aput.S" { "reg":"rINSTw", "store":"movw", "shift":"2", "data_offset":"MIRROR_CHAR_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/x86_64/op_aput_object.S b/runtime/interpreter/mterp/x86_64/op_aput_object.S
new file mode 100644
index 0000000..b1bae0f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aput_object.S
@@ -0,0 +1,13 @@
+/*
+ * Store an object into an array. vBB[vCC] <- vAA.
+ */
+ /* op vAA, vBB, vCC */
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST ${opnum}
+ movq rINSTq, OUT_ARG2
+ call SYMBOL(MterpAputObject) # (array, index)
+ testb %al, %al
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_aput_short.S b/runtime/interpreter/mterp/x86_64/op_aput_short.S
new file mode 100644
index 0000000..481fd68
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aput_short.S
@@ -0,0 +1 @@
+%include "x86_64/op_aput.S" { "reg":"rINSTw", "store":"movw", "shift":"2", "data_offset":"MIRROR_SHORT_ARRAY_DATA_OFFSET" }
diff --git a/runtime/interpreter/mterp/x86_64/op_aput_wide.S b/runtime/interpreter/mterp/x86_64/op_aput_wide.S
new file mode 100644
index 0000000..5bbd39b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_aput_wide.S
@@ -0,0 +1 @@
+%include "x86_64/op_aput.S" { "reg":"rINSTq", "store":"movq", "shift":"8", "data_offset":"MIRROR_WIDE_ARRAY_DATA_OFFSET", "wide":"1" }
diff --git a/runtime/interpreter/mterp/x86_64/op_array_length.S b/runtime/interpreter/mterp/x86_64/op_array_length.S
new file mode 100644
index 0000000..e80d665
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_array_length.S
@@ -0,0 +1,12 @@
+/*
+ * Return the length of an array.
+ */
+ movl rINST, %eax # eax <- BA
+ sarl $$4, rINST # rINST <- B
+ GET_VREG %ecx, rINSTq # ecx <- vB (object ref)
+ testl %ecx, %ecx # is null?
+ je common_errNullObject
+ andb $$0xf, %al # eax <- A
+ movl MIRROR_ARRAY_LENGTH_OFFSET(%rcx), rINST
+ SET_VREG rINST, %rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_check_cast.S b/runtime/interpreter/mterp/x86_64/op_check_cast.S
new file mode 100644
index 0000000..f8fa7b2
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_check_cast.S
@@ -0,0 +1,13 @@
+/*
+ * Check to see if a cast from one class to another is allowed.
+ */
+ /* check-cast vAA, class@BBBB */
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # OUT_ARG0 <- BBBB
+ leaq VREG_ADDRESS(rINSTq), OUT_ARG1
+ movq OFF_FP_METHOD(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpCheckCast) # (index, &obj, method, self)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_cmp_long.S b/runtime/interpreter/mterp/x86_64/op_cmp_long.S
new file mode 100644
index 0000000..23ca3e5
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_cmp_long.S
@@ -0,0 +1,17 @@
+/*
+ * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
+ * register based on the results of the comparison.
+ */
+ /* cmp-long vAA, vBB, vCC */
+ movzbq 2(rPC), %rdx # edx <- BB
+ movzbq 3(rPC), %rcx # ecx <- CC
+ GET_WIDE_VREG %rdx, %rdx # rdx <- v[BB]
+ xorl %eax, %eax
+ xorl %edi, %edi
+ addb $$1, %al
+ movl $$-1, %esi
+ cmpq VREG_ADDRESS(%rcx), %rdx
+ cmovl %esi, %edi
+ cmovg %eax, %edi
+ SET_VREG %edi, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_cmpg_double.S b/runtime/interpreter/mterp/x86_64/op_cmpg_double.S
new file mode 100644
index 0000000..7c0aa1b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_cmpg_double.S
@@ -0,0 +1 @@
+%include "x86_64/fpcmp.S" {"suff":"d","nanval":"pos"}
diff --git a/runtime/interpreter/mterp/x86_64/op_cmpg_float.S b/runtime/interpreter/mterp/x86_64/op_cmpg_float.S
new file mode 100644
index 0000000..14e8472
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_cmpg_float.S
@@ -0,0 +1 @@
+%include "x86_64/fpcmp.S" {"suff":"s","nanval":"pos"}
diff --git a/runtime/interpreter/mterp/x86_64/op_cmpl_double.S b/runtime/interpreter/mterp/x86_64/op_cmpl_double.S
new file mode 100644
index 0000000..1d4c424
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_cmpl_double.S
@@ -0,0 +1 @@
+%include "x86_64/fpcmp.S" {"suff":"d","nanval":"neg"}
diff --git a/runtime/interpreter/mterp/x86_64/op_cmpl_float.S b/runtime/interpreter/mterp/x86_64/op_cmpl_float.S
new file mode 100644
index 0000000..97a12a6
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_cmpl_float.S
@@ -0,0 +1 @@
+%include "x86_64/fpcmp.S" {"suff":"s","nanval":"neg"}
diff --git a/runtime/interpreter/mterp/x86_64/op_const.S b/runtime/interpreter/mterp/x86_64/op_const.S
new file mode 100644
index 0000000..3cfafdb
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const.S
@@ -0,0 +1,4 @@
+ /* const vAA, #+BBBBbbbb */
+ movl 2(rPC), %eax # grab all 32 bits at once
+ SET_VREG %eax, rINSTq # vAA<- eax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
diff --git a/runtime/interpreter/mterp/x86_64/op_const_16.S b/runtime/interpreter/mterp/x86_64/op_const_16.S
new file mode 100644
index 0000000..1a139c6
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_16.S
@@ -0,0 +1,4 @@
+ /* const/16 vAA, #+BBBB */
+ movswl 2(rPC), %ecx # ecx <- ssssBBBB
+ SET_VREG %ecx, rINSTq # vAA <- ssssBBBB
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_const_4.S b/runtime/interpreter/mterp/x86_64/op_const_4.S
new file mode 100644
index 0000000..23c4816
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_4.S
@@ -0,0 +1,7 @@
+ /* const/4 vA, #+B */
+ movsbl rINSTbl, %eax # eax <-ssssssBx
+ movl $$0xf, rINST
+ andl %eax, rINST # rINST <- A
+ sarl $$4, %eax
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_const_class.S b/runtime/interpreter/mterp/x86_64/op_const_class.S
new file mode 100644
index 0000000..494920a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_class.S
@@ -0,0 +1,10 @@
+ /* const/class vAA, Class@BBBB */
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # eax <- OUT_ARG0
+ movq rINSTq, OUT_ARG1
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpConstClass) # (index, tgt_reg, shadow_frame, self)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_const_high16.S b/runtime/interpreter/mterp/x86_64/op_const_high16.S
new file mode 100644
index 0000000..64e633c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_high16.S
@@ -0,0 +1,5 @@
+ /* const/high16 vAA, #+BBBB0000 */
+ movzwl 2(rPC), %eax # eax <- 0000BBBB
+ sall $$16, %eax # eax <- BBBB0000
+ SET_VREG %eax, rINSTq # vAA <- eax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_const_string.S b/runtime/interpreter/mterp/x86_64/op_const_string.S
new file mode 100644
index 0000000..7c199ec
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_string.S
@@ -0,0 +1,10 @@
+ /* const/string vAA, String@BBBB */
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # OUT_ARG0 <- BBBB
+ movq rINSTq, OUT_ARG1
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpConstString) # (index, tgt_reg, shadow_frame, self)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_const_string_jumbo.S b/runtime/interpreter/mterp/x86_64/op_const_string_jumbo.S
new file mode 100644
index 0000000..ae03d20
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_string_jumbo.S
@@ -0,0 +1,10 @@
+ /* const/string vAA, String@BBBBBBBB */
+ EXPORT_PC
+ movl 2(rPC), OUT_32_ARG0 # OUT_32_ARG0 <- BBBB
+ movq rINSTq, OUT_ARG1
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpConstString) # (index, tgt_reg, shadow_frame, self)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
diff --git a/runtime/interpreter/mterp/x86_64/op_const_wide.S b/runtime/interpreter/mterp/x86_64/op_const_wide.S
new file mode 100644
index 0000000..5615177
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_wide.S
@@ -0,0 +1,4 @@
+ /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
+ movq 2(rPC), %rax # rax <- HHHHhhhhBBBBbbbb
+ SET_WIDE_VREG %rax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 5
diff --git a/runtime/interpreter/mterp/x86_64/op_const_wide_16.S b/runtime/interpreter/mterp/x86_64/op_const_wide_16.S
new file mode 100644
index 0000000..593b624
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_wide_16.S
@@ -0,0 +1,4 @@
+ /* const-wide/16 vAA, #+BBBB */
+ movswq 2(rPC), %rax # rax <- ssssBBBB
+ SET_WIDE_VREG %rax, rINSTq # store
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_const_wide_32.S b/runtime/interpreter/mterp/x86_64/op_const_wide_32.S
new file mode 100644
index 0000000..5ef3636
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_wide_32.S
@@ -0,0 +1,4 @@
+ /* const-wide/32 vAA, #+BBBBbbbb */
+ movslq 2(rPC), %rax # eax <- ssssssssBBBBbbbb
+ SET_WIDE_VREG %rax, rINSTq # store
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
diff --git a/runtime/interpreter/mterp/x86_64/op_const_wide_high16.S b/runtime/interpreter/mterp/x86_64/op_const_wide_high16.S
new file mode 100644
index 0000000..b86b4e5
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_const_wide_high16.S
@@ -0,0 +1,5 @@
+ /* const-wide/high16 vAA, #+BBBB000000000000 */
+ movzwq 2(rPC), %rax # eax <- 0000BBBB
+ salq $$48, %rax # eax <- BBBB0000
+ SET_WIDE_VREG %rax, rINSTq # v[AA+0] <- eax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_div_double.S b/runtime/interpreter/mterp/x86_64/op_div_double.S
new file mode 100644
index 0000000..45c700c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_double.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop.S" {"instr":"divs","suff":"d"}
diff --git a/runtime/interpreter/mterp/x86_64/op_div_double_2addr.S b/runtime/interpreter/mterp/x86_64/op_div_double_2addr.S
new file mode 100644
index 0000000..83f270e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_double_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop2Addr.S" {"instr":"divs","suff":"d"}
diff --git a/runtime/interpreter/mterp/x86_64/op_div_float.S b/runtime/interpreter/mterp/x86_64/op_div_float.S
new file mode 100644
index 0000000..aa90b24
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_float.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop.S" {"instr":"divs","suff":"s"}
diff --git a/runtime/interpreter/mterp/x86_64/op_div_float_2addr.S b/runtime/interpreter/mterp/x86_64/op_div_float_2addr.S
new file mode 100644
index 0000000..f0f8f1a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_float_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop2Addr.S" {"instr":"divs","suff":"s"}
diff --git a/runtime/interpreter/mterp/x86_64/op_div_int.S b/runtime/interpreter/mterp/x86_64/op_div_int.S
new file mode 100644
index 0000000..bba5a17
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_int.S
@@ -0,0 +1 @@
+%include "x86_64/bindiv.S" {"result":"%eax","second":"%ecx","wide":"0","suffix":"l"}
diff --git a/runtime/interpreter/mterp/x86_64/op_div_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_div_int_2addr.S
new file mode 100644
index 0000000..fa4255d
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/bindiv2addr.S" {"result":"%eax","second":"%ecx","wide":"0","suffix":"l"}
diff --git a/runtime/interpreter/mterp/x86_64/op_div_int_lit16.S b/runtime/interpreter/mterp/x86_64/op_div_int_lit16.S
new file mode 100644
index 0000000..3fa1e09
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_int_lit16.S
@@ -0,0 +1 @@
+%include "x86_64/bindivLit16.S" {"result":"%eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_div_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_div_int_lit8.S
new file mode 100644
index 0000000..859883e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/bindivLit8.S" {"result":"%eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_div_long.S b/runtime/interpreter/mterp/x86_64/op_div_long.S
new file mode 100644
index 0000000..a061a88
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_long.S
@@ -0,0 +1 @@
+%include "x86_64/bindiv.S" {"result":"%rax","second":"%rcx","wide":"1","suffix":"q","ext":"cqo"}
diff --git a/runtime/interpreter/mterp/x86_64/op_div_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_div_long_2addr.S
new file mode 100644
index 0000000..8886e68
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_div_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/bindiv2addr.S" {"result":"%rax","second":"%rcx","wide":"1","suffix":"q","ext":"cqo"}
diff --git a/runtime/interpreter/mterp/x86_64/op_double_to_float.S b/runtime/interpreter/mterp/x86_64/op_double_to_float.S
new file mode 100644
index 0000000..cea1482
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_double_to_float.S
@@ -0,0 +1 @@
+%include "x86_64/fpcvt.S" {"source_suffix":"d","dest_suffix":"s","wide":"0"}
diff --git a/runtime/interpreter/mterp/x86_64/op_double_to_int.S b/runtime/interpreter/mterp/x86_64/op_double_to_int.S
new file mode 100644
index 0000000..a9965ed
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_double_to_int.S
@@ -0,0 +1 @@
+%include "x86_64/cvtfp_int.S" {"fp_suffix":"d","i_suffix":"l","max_const":"$0x7fffffff","result_reg":"%eax","wide":"0"}
diff --git a/runtime/interpreter/mterp/x86_64/op_double_to_long.S b/runtime/interpreter/mterp/x86_64/op_double_to_long.S
new file mode 100644
index 0000000..179e6a1
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_double_to_long.S
@@ -0,0 +1 @@
+%include "x86_64/cvtfp_int.S" {"fp_suffix":"d","i_suffix":"q","max_const":"$0x7fffffffffffffff","result_reg":"%rax","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_fill_array_data.S b/runtime/interpreter/mterp/x86_64/op_fill_array_data.S
new file mode 100644
index 0000000..626bad4
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_fill_array_data.S
@@ -0,0 +1,9 @@
+ /* fill-array-data vAA, +BBBBBBBB */
+ EXPORT_PC
+ movl 2(rPC), %ecx # ecx <- BBBBbbbb
+ leaq (rPC,%rcx,2), OUT_ARG1 # OUT_ARG1 <- PC + BBBBbbbb*2
+ GET_VREG OUT_32_ARG0, rINSTq # OUT_ARG0 <- vAA (array object)
+ call SYMBOL(MterpFillArrayData) # (obj, payload)
+ testb %al, %al # 0 means an exception is thrown
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
diff --git a/runtime/interpreter/mterp/x86_64/op_filled_new_array.S b/runtime/interpreter/mterp/x86_64/op_filled_new_array.S
new file mode 100644
index 0000000..a7f7ddc
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_filled_new_array.S
@@ -0,0 +1,17 @@
+%default { "helper":"MterpFilledNewArray" }
+/*
+ * Create a new array with elements filled from registers.
+ *
+ * for: filled-new-array, filled-new-array/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
+ .extern $helper
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ movq rSELF, OUT_ARG2
+ call SYMBOL($helper)
+ testb %al, %al # 0 means an exception is thrown
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
diff --git a/runtime/interpreter/mterp/x86_64/op_filled_new_array_range.S b/runtime/interpreter/mterp/x86_64/op_filled_new_array_range.S
new file mode 100644
index 0000000..4ca79a3
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_filled_new_array_range.S
@@ -0,0 +1 @@
+%include "x86_64/op_filled_new_array.S" { "helper":"MterpFilledNewArrayRange" }
diff --git a/runtime/interpreter/mterp/x86_64/op_float_to_double.S b/runtime/interpreter/mterp/x86_64/op_float_to_double.S
new file mode 100644
index 0000000..7855205
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_float_to_double.S
@@ -0,0 +1 @@
+%include "x86_64/fpcvt.S" {"source_suffix":"s","dest_suffix":"d","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_float_to_int.S b/runtime/interpreter/mterp/x86_64/op_float_to_int.S
new file mode 100644
index 0000000..cb90555
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_float_to_int.S
@@ -0,0 +1 @@
+%include "x86_64/cvtfp_int.S" {"fp_suffix":"s","i_suffix":"l","max_const":"$0x7fffffff","result_reg":"%eax","wide":"0"}
diff --git a/runtime/interpreter/mterp/x86_64/op_float_to_long.S b/runtime/interpreter/mterp/x86_64/op_float_to_long.S
new file mode 100644
index 0000000..96bb4ee
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_float_to_long.S
@@ -0,0 +1 @@
+%include "x86_64/cvtfp_int.S" {"fp_suffix":"s","i_suffix":"q","max_const":"$0x7fffffffffffffff","result_reg":"%rax","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_goto.S b/runtime/interpreter/mterp/x86_64/op_goto.S
new file mode 100644
index 0000000..c4fc976
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_goto.S
@@ -0,0 +1,14 @@
+/*
+ * Unconditional branch, 8-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto +AA */
+ movsbq rINSTbl, rINSTq # rINSTq <- ssssssAA
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
diff --git a/runtime/interpreter/mterp/x86_64/op_goto_16.S b/runtime/interpreter/mterp/x86_64/op_goto_16.S
new file mode 100644
index 0000000..8cb9a5c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_goto_16.S
@@ -0,0 +1,14 @@
+/*
+ * Unconditional branch, 16-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ */
+ /* goto/16 +AAAA */
+ movswq 2(rPC), rINSTq # rINSTq <- ssssAAAA
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
diff --git a/runtime/interpreter/mterp/x86_64/op_goto_32.S b/runtime/interpreter/mterp/x86_64/op_goto_32.S
new file mode 100644
index 0000000..4ecdacd
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_goto_32.S
@@ -0,0 +1,17 @@
+/*
+ * Unconditional branch, 32-bit offset.
+ *
+ * The branch distance is a signed code-unit offset, which we need to
+ * double to get a byte offset.
+ *
+ * Because we need the SF bit set, we'll use an adds
+ * to convert from Dalvik offset to byte offset.
+ */
+ /* goto/32 +AAAAAAAA */
+ movslq 2(rPC), rINSTq # rINSTq <- AAAAAAAA
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
diff --git a/runtime/interpreter/mterp/x86_64/op_if_eq.S b/runtime/interpreter/mterp/x86_64/op_if_eq.S
new file mode 100644
index 0000000..d56ce72
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_eq.S
@@ -0,0 +1 @@
+%include "x86_64/bincmp.S" { "revcmp":"ne" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_eqz.S b/runtime/interpreter/mterp/x86_64/op_if_eqz.S
new file mode 100644
index 0000000..a0fc444
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_eqz.S
@@ -0,0 +1 @@
+%include "x86_64/zcmp.S" { "revcmp":"ne" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_ge.S b/runtime/interpreter/mterp/x86_64/op_if_ge.S
new file mode 100644
index 0000000..a7832ef
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_ge.S
@@ -0,0 +1 @@
+%include "x86_64/bincmp.S" { "revcmp":"l" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_gez.S b/runtime/interpreter/mterp/x86_64/op_if_gez.S
new file mode 100644
index 0000000..f9af5db
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_gez.S
@@ -0,0 +1 @@
+%include "x86_64/zcmp.S" { "revcmp":"l" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_gt.S b/runtime/interpreter/mterp/x86_64/op_if_gt.S
new file mode 100644
index 0000000..70f2b9e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_gt.S
@@ -0,0 +1 @@
+%include "x86_64/bincmp.S" { "revcmp":"le" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_gtz.S b/runtime/interpreter/mterp/x86_64/op_if_gtz.S
new file mode 100644
index 0000000..2fb0d50
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_gtz.S
@@ -0,0 +1 @@
+%include "x86_64/zcmp.S" { "revcmp":"le" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_le.S b/runtime/interpreter/mterp/x86_64/op_if_le.S
new file mode 100644
index 0000000..321962a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_le.S
@@ -0,0 +1 @@
+%include "x86_64/bincmp.S" { "revcmp":"g" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_lez.S b/runtime/interpreter/mterp/x86_64/op_if_lez.S
new file mode 100644
index 0000000..d3dc334
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_lez.S
@@ -0,0 +1 @@
+%include "x86_64/zcmp.S" { "revcmp":"g" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_lt.S b/runtime/interpreter/mterp/x86_64/op_if_lt.S
new file mode 100644
index 0000000..f028005
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_lt.S
@@ -0,0 +1 @@
+%include "x86_64/bincmp.S" { "revcmp":"ge" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_ltz.S b/runtime/interpreter/mterp/x86_64/op_if_ltz.S
new file mode 100644
index 0000000..383d73a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_ltz.S
@@ -0,0 +1 @@
+%include "x86_64/zcmp.S" { "revcmp":"ge" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_ne.S b/runtime/interpreter/mterp/x86_64/op_if_ne.S
new file mode 100644
index 0000000..ac6e063
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_ne.S
@@ -0,0 +1 @@
+%include "x86_64/bincmp.S" { "revcmp":"e" }
diff --git a/runtime/interpreter/mterp/x86_64/op_if_nez.S b/runtime/interpreter/mterp/x86_64/op_if_nez.S
new file mode 100644
index 0000000..c96e4f3
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_if_nez.S
@@ -0,0 +1 @@
+%include "x86_64/zcmp.S" { "revcmp":"e" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget.S b/runtime/interpreter/mterp/x86_64/op_iget.S
new file mode 100644
index 0000000..a0d0faf
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget.S
@@ -0,0 +1,27 @@
+%default { "is_object":"0", "helper":"artGet32InstanceFromCode", "wide":"0"}
+/*
+ * General instance field get.
+ *
+ * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide
+ */
+ EXPORT_PC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC
+ sarl $$4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3
+ call SYMBOL($helper)
+ cmpq $$0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $$0xf, rINSTbl # rINST <- A
+ .if $is_object
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value
+ .else
+ .if $wide
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <-value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <-value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_boolean.S b/runtime/interpreter/mterp/x86_64/op_iget_boolean.S
new file mode 100644
index 0000000..6ac5523
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_boolean.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget.S" { "helper":"artGetBooleanInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_boolean_quick.S b/runtime/interpreter/mterp/x86_64/op_iget_boolean_quick.S
new file mode 100644
index 0000000..07139c7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_boolean_quick.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget_quick.S" { "load":"movsbl" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_byte.S b/runtime/interpreter/mterp/x86_64/op_iget_byte.S
new file mode 100644
index 0000000..6a861b1
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_byte.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget.S" { "helper":"artGetByteInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_byte_quick.S b/runtime/interpreter/mterp/x86_64/op_iget_byte_quick.S
new file mode 100644
index 0000000..07139c7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_byte_quick.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget_quick.S" { "load":"movsbl" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_char.S b/runtime/interpreter/mterp/x86_64/op_iget_char.S
new file mode 100644
index 0000000..021a0f1
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_char.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget.S" { "helper":"artGetCharInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_char_quick.S b/runtime/interpreter/mterp/x86_64/op_iget_char_quick.S
new file mode 100644
index 0000000..8cb3be3
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_char_quick.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget_quick.S" { "load":"movzwl" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_object.S b/runtime/interpreter/mterp/x86_64/op_iget_object.S
new file mode 100644
index 0000000..d92bc9c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_object.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget.S" { "is_object":"1", "helper":"artGetObjInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_object_quick.S b/runtime/interpreter/mterp/x86_64/op_iget_object_quick.S
new file mode 100644
index 0000000..964d20a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_object_quick.S
@@ -0,0 +1,14 @@
+ /* For: iget-object-quick */
+ /* op vA, vB, offset@CCCC */
+ .extern artIGetObjectFromMterp
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $$4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG0, %rcx # vB (object we're operating on)
+ movzwl 2(rPC), OUT_32_ARG1 # eax <- field byte offset
+ EXPORT_PC
+ callq SYMBOL(artIGetObjectFromMterp) # (obj, offset)
+ cmpq $$0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException # bail out
+ andb $$0xf, rINSTbl # rINST <- A
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_quick.S b/runtime/interpreter/mterp/x86_64/op_iget_quick.S
new file mode 100644
index 0000000..bfb7530
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_quick.S
@@ -0,0 +1,18 @@
+%default { "load":"movl", "wide":"0"}
+ /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick, iget-wide-quick */
+ /* op vA, vB, offset@CCCC */
+ movl rINST, %ecx # rcx <- BA
+ sarl $$4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ movzwq 2(rPC), %rax # eax <- field byte offset
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $$0xf,rINSTbl # rINST <- A
+ .if $wide
+ movq (%rcx,%rax,1), %rax
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ ${load} (%rcx,%rax,1), %eax
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_short.S b/runtime/interpreter/mterp/x86_64/op_iget_short.S
new file mode 100644
index 0000000..f158bea
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_short.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget.S" { "helper":"artGetShortInstanceFromCode" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_short_quick.S b/runtime/interpreter/mterp/x86_64/op_iget_short_quick.S
new file mode 100644
index 0000000..56ca858
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_short_quick.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget_quick.S" { "load":"movswl" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_wide.S b/runtime/interpreter/mterp/x86_64/op_iget_wide.S
new file mode 100644
index 0000000..74bb9ff
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_wide.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget.S" { "helper":"artGet64InstanceFromCode", "wide":"1" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iget_wide_quick.S b/runtime/interpreter/mterp/x86_64/op_iget_wide_quick.S
new file mode 100644
index 0000000..169d625
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iget_wide_quick.S
@@ -0,0 +1 @@
+%include "x86_64/op_iget_quick.S" { "load":"movswl", "wide":"1" }
diff --git a/runtime/interpreter/mterp/x86_64/op_instance_of.S b/runtime/interpreter/mterp/x86_64/op_instance_of.S
new file mode 100644
index 0000000..6be37f9
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_instance_of.S
@@ -0,0 +1,21 @@
+/*
+ * Check to see if an object reference is an instance of a class.
+ *
+ * Most common situation is a non-null object, being compared against
+ * an already-resolved class.
+ */
+ /* instance-of vA, vB, class@CCCC */
+ EXPORT_PC
+ movzwl 2(rPC), OUT_32_ARG0 # OUT_32_ARG0 <- CCCC
+ movl rINST, %eax # eax <- BA
+ sarl $$4, %eax # eax <- B
+ leaq VREG_ADDRESS(%rax), OUT_ARG1 # Get object address
+ movq OFF_FP_METHOD(rFP), OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpInstanceOf) # (index, &obj, method, self)
+ movsbl %al, %eax
+ cmpq $$0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ andb $$0xf, rINSTbl # rINSTbl <- A
+ SET_VREG %eax, rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_int_to_byte.S b/runtime/interpreter/mterp/x86_64/op_int_to_byte.S
new file mode 100644
index 0000000..f4e578f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_int_to_byte.S
@@ -0,0 +1 @@
+%include "x86_64/unop.S" {"instr":"movsbl %al, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_int_to_char.S b/runtime/interpreter/mterp/x86_64/op_int_to_char.S
new file mode 100644
index 0000000..c1bf17f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_int_to_char.S
@@ -0,0 +1 @@
+%include "x86_64/unop.S" {"instr":"movzwl %ax,%eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_int_to_double.S b/runtime/interpreter/mterp/x86_64/op_int_to_double.S
new file mode 100644
index 0000000..27ebf42
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_int_to_double.S
@@ -0,0 +1 @@
+%include "x86_64/fpcvt.S" {"source_suffix":"i","dest_suffix":"dl","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_int_to_float.S b/runtime/interpreter/mterp/x86_64/op_int_to_float.S
new file mode 100644
index 0000000..5a98d44
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_int_to_float.S
@@ -0,0 +1 @@
+%include "x86_64/fpcvt.S" {"source_suffix":"i","dest_suffix":"sl","wide":"0"}
diff --git a/runtime/interpreter/mterp/x86_64/op_int_to_long.S b/runtime/interpreter/mterp/x86_64/op_int_to_long.S
new file mode 100644
index 0000000..9281137
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_int_to_long.S
@@ -0,0 +1,8 @@
+ /* int to long vA, vB */
+ movzbq rINSTbl, %rax # rax <- +A
+ sarl $$4, %eax # eax <- B
+ andb $$0xf, rINSTbl # rINST <- A
+ movslq VREG_ADDRESS(%rax), %rax
+ SET_WIDE_VREG %rax, rINSTq # v[A] <- %rax
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
+
diff --git a/runtime/interpreter/mterp/x86_64/op_int_to_short.S b/runtime/interpreter/mterp/x86_64/op_int_to_short.S
new file mode 100644
index 0000000..6ae6b50
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_int_to_short.S
@@ -0,0 +1 @@
+%include "x86_64/unop.S" {"instr":"movswl %ax, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_direct.S b/runtime/interpreter/mterp/x86_64/op_invoke_direct.S
new file mode 100644
index 0000000..9628589
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_direct.S
@@ -0,0 +1 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeDirect" }
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_direct_range.S b/runtime/interpreter/mterp/x86_64/op_invoke_direct_range.S
new file mode 100644
index 0000000..09ac881
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_direct_range.S
@@ -0,0 +1 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeDirectRange" }
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_interface.S b/runtime/interpreter/mterp/x86_64/op_invoke_interface.S
new file mode 100644
index 0000000..76d9cd4
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_interface.S
@@ -0,0 +1,8 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeInterface" }
+/*
+ * Handle an interface method call.
+ *
+ * for: invoke-interface, invoke-interface/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_interface_range.S b/runtime/interpreter/mterp/x86_64/op_invoke_interface_range.S
new file mode 100644
index 0000000..785b43c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_interface_range.S
@@ -0,0 +1 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeInterfaceRange" }
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_static.S b/runtime/interpreter/mterp/x86_64/op_invoke_static.S
new file mode 100644
index 0000000..dd8027d
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_static.S
@@ -0,0 +1,2 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeStatic" }
+
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_static_range.S b/runtime/interpreter/mterp/x86_64/op_invoke_static_range.S
new file mode 100644
index 0000000..ee26074
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_static_range.S
@@ -0,0 +1 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeStaticRange" }
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_super.S b/runtime/interpreter/mterp/x86_64/op_invoke_super.S
new file mode 100644
index 0000000..d07f8d5
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_super.S
@@ -0,0 +1,8 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeSuper" }
+/*
+ * Handle a "super" method call.
+ *
+ * for: invoke-super, invoke-super/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_super_range.S b/runtime/interpreter/mterp/x86_64/op_invoke_super_range.S
new file mode 100644
index 0000000..7245cfd
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_super_range.S
@@ -0,0 +1 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeSuperRange" }
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_virtual.S b/runtime/interpreter/mterp/x86_64/op_invoke_virtual.S
new file mode 100644
index 0000000..19c708b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_virtual.S
@@ -0,0 +1,8 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeVirtual" }
+/*
+ * Handle a virtual method call.
+ *
+ * for: invoke-virtual, invoke-virtual/range
+ */
+ /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+ /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_virtual_quick.S b/runtime/interpreter/mterp/x86_64/op_invoke_virtual_quick.S
new file mode 100644
index 0000000..313bd05
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_virtual_quick.S
@@ -0,0 +1 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeVirtualQuick" }
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_virtual_range.S b/runtime/interpreter/mterp/x86_64/op_invoke_virtual_range.S
new file mode 100644
index 0000000..424ad32
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_virtual_range.S
@@ -0,0 +1 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeVirtualRange" }
diff --git a/runtime/interpreter/mterp/x86_64/op_invoke_virtual_range_quick.S b/runtime/interpreter/mterp/x86_64/op_invoke_virtual_range_quick.S
new file mode 100644
index 0000000..556f718
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_invoke_virtual_range_quick.S
@@ -0,0 +1 @@
+%include "x86_64/invoke.S" { "helper":"MterpInvokeVirtualQuickRange" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iput.S b/runtime/interpreter/mterp/x86_64/op_iput.S
new file mode 100644
index 0000000..6b7cb1c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput.S
@@ -0,0 +1,20 @@
+%default { "handler":"artSet32InstanceFromMterp"}
+/*
+ * General 32-bit instance field put.
+ *
+ * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ */
+ /* op vA, vB, field@CCCC */
+ .extern $handler
+ EXPORT_PC
+ movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC
+ movzbq rINSTbl, %rcx # rcx<- BA
+ sarl $$4, %ecx # ecx<- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ andb $$0xf, rINSTbl # rINST<- A
+ GET_VREG OUT_32_ARG2, rINSTq # fp[A]
+ movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer
+ call SYMBOL($handler)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_boolean.S b/runtime/interpreter/mterp/x86_64/op_iput_boolean.S
new file mode 100644
index 0000000..cb4b1cd
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_boolean.S
@@ -0,0 +1 @@
+%include "x86_64/op_iput.S" { "handler":"artSet8InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_boolean_quick.S b/runtime/interpreter/mterp/x86_64/op_iput_boolean_quick.S
new file mode 100644
index 0000000..6bd060e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_boolean_quick.S
@@ -0,0 +1 @@
+%include "x86_64/op_iput_quick.S" { "reg":"rINSTbl", "store":"movb" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_byte.S b/runtime/interpreter/mterp/x86_64/op_iput_byte.S
new file mode 100644
index 0000000..cb4b1cd
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_byte.S
@@ -0,0 +1 @@
+%include "x86_64/op_iput.S" { "handler":"artSet8InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_byte_quick.S b/runtime/interpreter/mterp/x86_64/op_iput_byte_quick.S
new file mode 100644
index 0000000..6bd060e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_byte_quick.S
@@ -0,0 +1 @@
+%include "x86_64/op_iput_quick.S" { "reg":"rINSTbl", "store":"movb" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_char.S b/runtime/interpreter/mterp/x86_64/op_iput_char.S
new file mode 100644
index 0000000..b4e147c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_char.S
@@ -0,0 +1 @@
+%include "x86_64/op_iput.S" { "handler":"artSet16InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_char_quick.S b/runtime/interpreter/mterp/x86_64/op_iput_char_quick.S
new file mode 100644
index 0000000..3da96d5
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_char_quick.S
@@ -0,0 +1 @@
+%include "x86_64/op_iput_quick.S" { "reg":"rINSTw", "store":"movw" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_object.S b/runtime/interpreter/mterp/x86_64/op_iput_object.S
new file mode 100644
index 0000000..828712d
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_object.S
@@ -0,0 +1,10 @@
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST ${opnum}
+ movl rINST, OUT_32_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpIputObject)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_object_quick.S b/runtime/interpreter/mterp/x86_64/op_iput_object_quick.S
new file mode 100644
index 0000000..b5b128a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_object_quick.S
@@ -0,0 +1,9 @@
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST ${opnum}
+ movl rINST, OUT_32_ARG2
+ call SYMBOL(MterpIputObjectQuick)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_quick.S b/runtime/interpreter/mterp/x86_64/op_iput_quick.S
new file mode 100644
index 0000000..ecaf98e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_quick.S
@@ -0,0 +1,13 @@
+%default { "reg":"rINST", "store":"movl" }
+ /* For: iput-quick, iput-object-quick */
+ /* op vA, vB, offset@CCCC */
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $$4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ andb $$0xf, rINSTbl # rINST <- A
+ GET_VREG rINST, rINSTq # rINST <- v[A]
+ movzwq 2(rPC), %rax # rax <- field byte offset
+ ${store} ${reg}, (%rcx,%rax,1)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_short.S b/runtime/interpreter/mterp/x86_64/op_iput_short.S
new file mode 100644
index 0000000..b4e147c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_short.S
@@ -0,0 +1 @@
+%include "x86_64/op_iput.S" { "handler":"artSet16InstanceFromMterp" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_short_quick.S b/runtime/interpreter/mterp/x86_64/op_iput_short_quick.S
new file mode 100644
index 0000000..3da96d5
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_short_quick.S
@@ -0,0 +1 @@
+%include "x86_64/op_iput_quick.S" { "reg":"rINSTw", "store":"movw" }
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_wide.S b/runtime/interpreter/mterp/x86_64/op_iput_wide.S
new file mode 100644
index 0000000..e59717b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_wide.S
@@ -0,0 +1,14 @@
+ /* iput-wide vA, vB, field@CCCC */
+ .extern artSet64InstanceFromMterp
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movzbq rINSTbl, %rcx # rcx <- BA
+ sarl $$4, %ecx # ecx <- B
+ GET_VREG OUT_32_ARG1, %rcx # the object pointer
+ andb $$0xf, rINSTbl # rINST <- A
+ leaq VREG_ADDRESS(rINSTq), OUT_ARG2 # &fp[A]
+ movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer
+ call SYMBOL(artSet64InstanceFromMterp)
+ testb %al, %al
+ jnz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_iput_wide_quick.S b/runtime/interpreter/mterp/x86_64/op_iput_wide_quick.S
new file mode 100644
index 0000000..473189d
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_iput_wide_quick.S
@@ -0,0 +1,12 @@
+ /* iput-wide-quick vA, vB, offset@CCCC */
+ movzbq rINSTbl, %rcx # rcx<- BA
+ sarl $$4, %ecx # ecx<- B
+ GET_VREG %ecx, %rcx # vB (object we're operating on)
+ testl %ecx, %ecx # is object null?
+ je common_errNullObject
+ movzwq 2(rPC), %rax # rax<- field byte offset
+ leaq (%rcx,%rax,1), %rcx # ecx<- Address of 64-bit target
+ andb $$0xf, rINSTbl # rINST<- A
+ GET_WIDE_VREG %rax, rINSTq # rax<- fp[A]/fp[A+1]
+ movq %rax, (%rcx) # obj.field<- r0/r1
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_long_to_double.S b/runtime/interpreter/mterp/x86_64/op_long_to_double.S
new file mode 100644
index 0000000..7cdae32
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_long_to_double.S
@@ -0,0 +1 @@
+%include "x86_64/fpcvt.S" {"source_suffix":"i","dest_suffix":"dq","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_long_to_float.S b/runtime/interpreter/mterp/x86_64/op_long_to_float.S
new file mode 100644
index 0000000..7553348
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_long_to_float.S
@@ -0,0 +1 @@
+%include "x86_64/fpcvt.S" {"source_suffix":"i","dest_suffix":"sq","wide":"0"}
diff --git a/runtime/interpreter/mterp/x86_64/op_long_to_int.S b/runtime/interpreter/mterp/x86_64/op_long_to_int.S
new file mode 100644
index 0000000..7b50c8e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_long_to_int.S
@@ -0,0 +1,2 @@
+/* we ignore the high word, making this equivalent to a 32-bit reg move */
+%include "x86_64/op_move.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_monitor_enter.S b/runtime/interpreter/mterp/x86_64/op_monitor_enter.S
new file mode 100644
index 0000000..411091f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_monitor_enter.S
@@ -0,0 +1,11 @@
+/*
+ * Synchronize on an object.
+ */
+ /* monitor-enter vAA */
+ EXPORT_PC
+ GET_VREG OUT_32_ARG0, rINSTq
+ movq rSELF, OUT_ARG1
+ call SYMBOL(artLockObjectFromCode) # (object, self)
+ testq %rax, %rax
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_monitor_exit.S b/runtime/interpreter/mterp/x86_64/op_monitor_exit.S
new file mode 100644
index 0000000..72d9a23
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_monitor_exit.S
@@ -0,0 +1,15 @@
+/*
+ * Unlock an object.
+ *
+ * Exceptions that occur when unlocking a monitor need to appear as
+ * if they happened at the following instruction. See the Dalvik
+ * instruction spec.
+ */
+ /* monitor-exit vAA */
+ EXPORT_PC
+ GET_VREG OUT_32_ARG0, rINSTq
+ movq rSELF, OUT_ARG1
+ call SYMBOL(artUnlockObjectFromCode) # (object, self)
+ testq %rax, %rax
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_move.S b/runtime/interpreter/mterp/x86_64/op_move.S
new file mode 100644
index 0000000..ccaac2c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move.S
@@ -0,0 +1,13 @@
+%default { "is_object":"0" }
+ /* for move, move-object, long-to-int */
+ /* op vA, vB */
+ movl rINST, %eax # eax <- BA
+ andb $$0xf, %al # eax <- A
+ shrl $$4, rINST # rINST <- B
+ GET_VREG %edx, rINSTq
+ .if $is_object
+ SET_VREG_OBJECT %edx, %rax # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, %rax # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_move_16.S b/runtime/interpreter/mterp/x86_64/op_move_16.S
new file mode 100644
index 0000000..6a813eb
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_16.S
@@ -0,0 +1,12 @@
+%default { "is_object":"0" }
+ /* for: move/16, move-object/16 */
+ /* op vAAAA, vBBBB */
+ movzwq 4(rPC), %rcx # ecx <- BBBB
+ movzwq 2(rPC), %rax # eax <- AAAA
+ GET_VREG %edx, %rcx
+ .if $is_object
+ SET_VREG_OBJECT %edx, %rax # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, %rax # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
diff --git a/runtime/interpreter/mterp/x86_64/op_move_exception.S b/runtime/interpreter/mterp/x86_64/op_move_exception.S
new file mode 100644
index 0000000..d0a14fd
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_exception.S
@@ -0,0 +1,5 @@
+ /* move-exception vAA */
+ movl THREAD_EXCEPTION_OFFSET(rSELF), %eax
+ SET_VREG_OBJECT %eax, rINSTq # fp[AA] <- exception object
+ movl $$0, THREAD_EXCEPTION_OFFSET(rSELF)
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_move_from16.S b/runtime/interpreter/mterp/x86_64/op_move_from16.S
new file mode 100644
index 0000000..150e9c2
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_from16.S
@@ -0,0 +1,11 @@
+%default { "is_object":"0" }
+ /* for: move/from16, move-object/from16 */
+ /* op vAA, vBBBB */
+ movzwq 2(rPC), %rax # eax <- BBBB
+ GET_VREG %edx, %rax # edx <- fp[BBBB]
+ .if $is_object
+ SET_VREG_OBJECT %edx, rINSTq # fp[A] <- fp[B]
+ .else
+ SET_VREG %edx, rINSTq # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_move_object.S b/runtime/interpreter/mterp/x86_64/op_move_object.S
new file mode 100644
index 0000000..0d86649
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_object.S
@@ -0,0 +1 @@
+%include "x86_64/op_move.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_move_object_16.S b/runtime/interpreter/mterp/x86_64/op_move_object_16.S
new file mode 100644
index 0000000..32541ff
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_object_16.S
@@ -0,0 +1 @@
+%include "x86_64/op_move_16.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_move_object_from16.S b/runtime/interpreter/mterp/x86_64/op_move_object_from16.S
new file mode 100644
index 0000000..983e4ab
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_object_from16.S
@@ -0,0 +1 @@
+%include "x86_64/op_move_from16.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_move_result.S b/runtime/interpreter/mterp/x86_64/op_move_result.S
new file mode 100644
index 0000000..8268344
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_result.S
@@ -0,0 +1,11 @@
+%default { "is_object":"0" }
+ /* for: move-result, move-result-object */
+ /* op vAA */
+ movq OFF_FP_RESULT_REGISTER(rFP), %rax # get pointer to result JType.
+ movl (%rax), %eax # r0 <- result.i.
+ .if $is_object
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- fp[B]
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- fp[B]
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_move_result_object.S b/runtime/interpreter/mterp/x86_64/op_move_result_object.S
new file mode 100644
index 0000000..c5aac17
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_result_object.S
@@ -0,0 +1 @@
+%include "x86_64/op_move_result.S" {"is_object":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_move_result_wide.S b/runtime/interpreter/mterp/x86_64/op_move_result_wide.S
new file mode 100644
index 0000000..03de783
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_result_wide.S
@@ -0,0 +1,5 @@
+ /* move-result-wide vAA */
+ movq OFF_FP_RESULT_REGISTER(rFP), %rax # get pointer to result JType.
+ movq (%rax), %rdx # Get wide
+ SET_WIDE_VREG %rdx, rINSTq # v[AA] <- rdx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_move_wide.S b/runtime/interpreter/mterp/x86_64/op_move_wide.S
new file mode 100644
index 0000000..508f8cc
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_wide.S
@@ -0,0 +1,8 @@
+ /* move-wide vA, vB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ movl rINST, %ecx # ecx <- BA
+ sarl $$4, rINST # rINST <- B
+ andb $$0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rdx, rINSTq # rdx <- v[B]
+ SET_WIDE_VREG %rdx, %rcx # v[A] <- rdx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_move_wide_16.S b/runtime/interpreter/mterp/x86_64/op_move_wide_16.S
new file mode 100644
index 0000000..ce371a9
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_wide_16.S
@@ -0,0 +1,7 @@
+ /* move-wide/16 vAAAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ movzwq 4(rPC), %rcx # ecx<- BBBB
+ movzwq 2(rPC), %rax # eax<- AAAA
+ GET_WIDE_VREG %rdx, %rcx # rdx <- v[B]
+ SET_WIDE_VREG %rdx, %rax # v[A] <- rdx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 3
diff --git a/runtime/interpreter/mterp/x86_64/op_move_wide_from16.S b/runtime/interpreter/mterp/x86_64/op_move_wide_from16.S
new file mode 100644
index 0000000..0d6971a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_move_wide_from16.S
@@ -0,0 +1,6 @@
+ /* move-wide/from16 vAA, vBBBB */
+ /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+ movzwl 2(rPC), %ecx # ecx <- BBBB
+ GET_WIDE_VREG %rdx, %rcx # rdx <- v[B]
+ SET_WIDE_VREG %rdx, rINSTq # v[A] <- rdx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_double.S b/runtime/interpreter/mterp/x86_64/op_mul_double.S
new file mode 100644
index 0000000..1f4bcb3
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_double.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop.S" {"instr":"muls","suff":"d"}
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_double_2addr.S b/runtime/interpreter/mterp/x86_64/op_mul_double_2addr.S
new file mode 100644
index 0000000..9850a28
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_double_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop2Addr.S" {"instr":"muls","suff":"d"}
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_float.S b/runtime/interpreter/mterp/x86_64/op_mul_float.S
new file mode 100644
index 0000000..85960e9
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_float.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop.S" {"instr":"muls","suff":"s"}
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_float_2addr.S b/runtime/interpreter/mterp/x86_64/op_mul_float_2addr.S
new file mode 100644
index 0000000..6d36b6a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_float_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop2Addr.S" {"instr":"muls","suff":"s"}
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_int.S b/runtime/interpreter/mterp/x86_64/op_mul_int.S
new file mode 100644
index 0000000..5f3923a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_int.S
@@ -0,0 +1 @@
+%include "x86_64/binop.S" {"instr":"imull (rFP,%rcx,4), %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_mul_int_2addr.S
new file mode 100644
index 0000000..0b5af8a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_int_2addr.S
@@ -0,0 +1,8 @@
+ /* mul vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $$4, rINST # rINST <- B
+ andb $$0xf, %cl # ecx <- A
+ GET_VREG %eax, %rcx # eax <- vA
+ imull (rFP,rINSTq,4), %eax
+ SET_VREG %eax, %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_int_lit16.S b/runtime/interpreter/mterp/x86_64/op_mul_int_lit16.S
new file mode 100644
index 0000000..a4cfdbc
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_int_lit16.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit16.S" {"instr":"imull %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_mul_int_lit8.S
new file mode 100644
index 0000000..89e9acb
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit8.S" {"instr":"imull %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_long.S b/runtime/interpreter/mterp/x86_64/op_mul_long.S
new file mode 100644
index 0000000..2b85370
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_long.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide.S" {"instr":"imulq (rFP,%rcx,4), %rax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_mul_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_mul_long_2addr.S
new file mode 100644
index 0000000..167128b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_mul_long_2addr.S
@@ -0,0 +1,8 @@
+ /* mul vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $$4, rINST # rINST <- B
+ andb $$0xf, %cl # ecx <- A
+ GET_WIDE_VREG %rax, %rcx # rax <- vA
+ imulq (rFP,rINSTq,4), %rax
+ SET_WIDE_VREG %rax, %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_neg_double.S b/runtime/interpreter/mterp/x86_64/op_neg_double.S
new file mode 100644
index 0000000..2c14b09
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_neg_double.S
@@ -0,0 +1 @@
+%include "x86_64/unop.S" {"preinstr":" movq $0x8000000000000000, %rsi", "instr":" xorq %rsi, %rax", "wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_neg_float.S b/runtime/interpreter/mterp/x86_64/op_neg_float.S
new file mode 100644
index 0000000..148b21e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_neg_float.S
@@ -0,0 +1 @@
+%include "x86_64/unop.S" {"instr":" xorl $0x80000000, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_neg_int.S b/runtime/interpreter/mterp/x86_64/op_neg_int.S
new file mode 100644
index 0000000..f90a937
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_neg_int.S
@@ -0,0 +1 @@
+%include "x86_64/unop.S" {"instr":" negl %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_neg_long.S b/runtime/interpreter/mterp/x86_64/op_neg_long.S
new file mode 100644
index 0000000..18fc3cc
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_neg_long.S
@@ -0,0 +1 @@
+%include "x86_64/unop.S" {"instr":" negq %rax", "wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_new_array.S b/runtime/interpreter/mterp/x86_64/op_new_array.S
new file mode 100644
index 0000000..9831a0b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_new_array.S
@@ -0,0 +1,18 @@
+/*
+ * Allocate an array of objects, specified with the array class
+ * and a count.
+ *
+ * The verifier guarantees that this is an array class, so we don't
+ * check for it here.
+ */
+ /* new-array vA, vB, class@CCCC */
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST ${opnum}
+ movq rINSTq, OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpNewArray)
+ testb %al, %al # 0 means an exception is thrown
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_new_instance.S b/runtime/interpreter/mterp/x86_64/op_new_instance.S
new file mode 100644
index 0000000..fc8c8cd
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_new_instance.S
@@ -0,0 +1,13 @@
+/*
+ * Create a new instance of a class.
+ */
+ /* new-instance vAA, class@BBBB */
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rSELF, OUT_ARG1
+ REFRESH_INST ${opnum}
+ movq rINSTq, OUT_ARG2
+ call SYMBOL(MterpNewInstance)
+ testb %al, %al # 0 means an exception is thrown
+ jz MterpPossibleException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_nop.S b/runtime/interpreter/mterp/x86_64/op_nop.S
new file mode 100644
index 0000000..4cb68e3
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_nop.S
@@ -0,0 +1 @@
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_not_int.S b/runtime/interpreter/mterp/x86_64/op_not_int.S
new file mode 100644
index 0000000..463d080
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_not_int.S
@@ -0,0 +1 @@
+%include "x86_64/unop.S" {"instr":" notl %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_not_long.S b/runtime/interpreter/mterp/x86_64/op_not_long.S
new file mode 100644
index 0000000..c97bb9e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_not_long.S
@@ -0,0 +1 @@
+%include "x86_64/unop.S" {"instr":" notq %rax", "wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_or_int.S b/runtime/interpreter/mterp/x86_64/op_or_int.S
new file mode 100644
index 0000000..730310f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_or_int.S
@@ -0,0 +1 @@
+%include "x86_64/binop.S" {"instr":"orl (rFP,%rcx,4), %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_or_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_or_int_2addr.S
new file mode 100644
index 0000000..f722e4d
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_or_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binop2addr.S" {"instr":"orl %eax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/op_or_int_lit16.S b/runtime/interpreter/mterp/x86_64/op_or_int_lit16.S
new file mode 100644
index 0000000..fee86c7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_or_int_lit16.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit16.S" {"instr":"orl %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_or_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_or_int_lit8.S
new file mode 100644
index 0000000..81104c7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_or_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit8.S" {"instr":"orl %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_or_long.S b/runtime/interpreter/mterp/x86_64/op_or_long.S
new file mode 100644
index 0000000..6c70a20
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_or_long.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide.S" {"instr":"orq (rFP,%rcx,4), %rax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_or_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_or_long_2addr.S
new file mode 100644
index 0000000..546da1d
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_or_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide2addr.S" {"instr":"orq %rax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/op_packed_switch.S b/runtime/interpreter/mterp/x86_64/op_packed_switch.S
new file mode 100644
index 0000000..cb0acb7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_packed_switch.S
@@ -0,0 +1,22 @@
+%default { "func":"MterpDoPackedSwitch" }
+/*
+ * Handle a packed-switch or sparse-switch instruction. In both cases
+ * we decode it and hand it off to a helper function.
+ *
+ * We don't really expect backward branches in a switch statement, but
+ * they're perfectly legal, so we check for them here.
+ *
+ * for: packed-switch, sparse-switch
+ */
+ /* op vAA, +BBBB */
+ movslq 2(rPC), OUT_ARG0 # rcx <- BBBBbbbb
+ leaq (rPC,OUT_ARG0,2), OUT_ARG0 # rcx <- PC + BBBBbbbb*2
+ GET_VREG OUT_32_ARG1, rINSTq # eax <- vAA
+ call SYMBOL($func)
+ movslq %eax, rINSTq
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue
+ GOTO_NEXT
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_double.S b/runtime/interpreter/mterp/x86_64/op_rem_double.S
new file mode 100644
index 0000000..00aed78
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_double.S
@@ -0,0 +1,14 @@
+ /* rem_double vAA, vBB, vCC */
+ movzbq 3(rPC), %rcx # ecx <- BB
+ movzbq 2(rPC), %rax # eax <- CC
+ fldl VREG_ADDRESS(%rcx) # %st1 <- fp[vBB]
+ fldl VREG_ADDRESS(%rax) # %st0 <- fp[vCC]
+1:
+ fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ fstpl VREG_ADDRESS(rINSTq) # fp[vAA] <- %st
+ CLEAR_WIDE_REF rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_double_2addr.S b/runtime/interpreter/mterp/x86_64/op_rem_double_2addr.S
new file mode 100644
index 0000000..9768266
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_double_2addr.S
@@ -0,0 +1,15 @@
+ /* rem_double/2addr vA, vB */
+ movzbq rINSTbl, %rcx # ecx <- A+
+ sarl $$4, rINST # rINST <- B
+ fldl VREG_ADDRESS(rINSTq) # vB to fp stack
+ andb $$0xf, %cl # ecx <- A
+ fldl VREG_ADDRESS(%rcx) # vA to fp stack
+1:
+ fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ fstpl VREG_ADDRESS(%rcx) # %st to vA
+ CLEAR_WIDE_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_float.S b/runtime/interpreter/mterp/x86_64/op_rem_float.S
new file mode 100644
index 0000000..5af28ac
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_float.S
@@ -0,0 +1,14 @@
+ /* rem_float vAA, vBB, vCC */
+ movzbq 3(rPC), %rcx # ecx <- BB
+ movzbq 2(rPC), %rax # eax <- CC
+ flds VREG_ADDRESS(%rcx) # vBB to fp stack
+ flds VREG_ADDRESS(%rax) # vCC to fp stack
+1:
+ fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ fstps VREG_ADDRESS(rINSTq) # %st to vAA
+ CLEAR_REF rINSTq
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_float_2addr.S b/runtime/interpreter/mterp/x86_64/op_rem_float_2addr.S
new file mode 100644
index 0000000..e9282a8
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_float_2addr.S
@@ -0,0 +1,15 @@
+ /* rem_float/2addr vA, vB */
+ movzbq rINSTbl, %rcx # ecx <- A+
+ sarl $$4, rINST # rINST <- B
+ flds VREG_ADDRESS(rINSTq) # vB to fp stack
+ andb $$0xf, %cl # ecx <- A
+ flds VREG_ADDRESS(%rcx) # vA to fp stack
+1:
+ fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ fstps VREG_ADDRESS(%rcx) # %st to vA
+ CLEAR_REF %rcx
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_int.S b/runtime/interpreter/mterp/x86_64/op_rem_int.S
new file mode 100644
index 0000000..fd77d7c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_int.S
@@ -0,0 +1 @@
+%include "x86_64/bindiv.S" {"result":"%edx","second":"%ecx","wide":"0","suffix":"l","rem":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_rem_int_2addr.S
new file mode 100644
index 0000000..25ffbf7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/bindiv2addr.S" {"result":"%edx","second":"%ecx","wide":"0","suffix":"l","rem":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_int_lit16.S b/runtime/interpreter/mterp/x86_64/op_rem_int_lit16.S
new file mode 100644
index 0000000..21cc370
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_int_lit16.S
@@ -0,0 +1 @@
+%include "x86_64/bindivLit16.S" {"result":"%edx","rem":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_rem_int_lit8.S
new file mode 100644
index 0000000..2eb0150
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/bindivLit8.S" {"result":"%edx","rem":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_long.S b/runtime/interpreter/mterp/x86_64/op_rem_long.S
new file mode 100644
index 0000000..efa7215
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_long.S
@@ -0,0 +1 @@
+%include "x86_64/bindiv.S" {"result":"%rdx","second":"%rcx","wide":"1","suffix":"q","ext":"cqo","rem":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_rem_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_rem_long_2addr.S
new file mode 100644
index 0000000..ce0dd86
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rem_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/bindiv2addr.S" {"result":"%rdx","second":"%rcx","wide":"1","suffix":"q","rem":"1","ext":"cqo"}
diff --git a/runtime/interpreter/mterp/x86_64/op_return.S b/runtime/interpreter/mterp/x86_64/op_return.S
new file mode 100644
index 0000000..14f4f8a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_return.S
@@ -0,0 +1,15 @@
+/*
+ * Return a 32-bit value.
+ *
+ * for: return, return-object
+ */
+ /* op vAA */
+ .extern MterpThreadFenceForConstructor
+ call SYMBOL(MterpThreadFenceForConstructor)
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ GET_VREG %eax, rINSTq # eax <- vAA
+ jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86_64/op_return_object.S b/runtime/interpreter/mterp/x86_64/op_return_object.S
new file mode 100644
index 0000000..1ae69a5
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_return_object.S
@@ -0,0 +1 @@
+%include "x86_64/op_return.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_return_void.S b/runtime/interpreter/mterp/x86_64/op_return_void.S
new file mode 100644
index 0000000..46a5753
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_return_void.S
@@ -0,0 +1,9 @@
+ .extern MterpThreadFenceForConstructor
+ call SYMBOL(MterpThreadFenceForConstructor)
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ xorq %rax, %rax
+ jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86_64/op_return_void_no_barrier.S b/runtime/interpreter/mterp/x86_64/op_return_void_no_barrier.S
new file mode 100644
index 0000000..92e3506
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_return_void_no_barrier.S
@@ -0,0 +1,7 @@
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ xorq %rax, %rax
+ jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86_64/op_return_wide.S b/runtime/interpreter/mterp/x86_64/op_return_wide.S
new file mode 100644
index 0000000..f2d6e04
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_return_wide.S
@@ -0,0 +1,13 @@
+/*
+ * Return a 64-bit value.
+ */
+ /* return-wide vAA */
+ .extern MterpThreadFenceForConstructor
+ call SYMBOL(MterpThreadFenceForConstructor)
+ testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(rSELF)
+ jz 1f
+ movq rSELF, OUT_ARG0
+ call SYMBOL(MterpSuspendCheck)
+1:
+ GET_WIDE_VREG %rax, rINSTq # eax <- v[AA]
+ jmp MterpReturn
diff --git a/runtime/interpreter/mterp/x86_64/op_rsub_int.S b/runtime/interpreter/mterp/x86_64/op_rsub_int.S
new file mode 100644
index 0000000..2dd2002
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rsub_int.S
@@ -0,0 +1,2 @@
+/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
+%include "x86_64/binopLit16.S" {"instr":"subl %eax, %ecx","result":"%ecx"}
diff --git a/runtime/interpreter/mterp/x86_64/op_rsub_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_rsub_int_lit8.S
new file mode 100644
index 0000000..64d0d8a
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_rsub_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit8.S" {"instr":"subl %eax, %ecx" , "result":"%ecx"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget.S b/runtime/interpreter/mterp/x86_64/op_sget.S
new file mode 100644
index 0000000..38d9a5e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sget.S
@@ -0,0 +1,25 @@
+%default { "is_object":"0", "helper":"artGet32StaticFromCode", "wide":"0" }
+/*
+ * General SGET handler wrapper.
+ *
+ * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
+ */
+ /* op vAA, field@BBBB */
+ .extern $helper
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref CCCC
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ movq rSELF, OUT_ARG2 # self
+ call SYMBOL($helper)
+ cmpl $$0, THREAD_EXCEPTION_OFFSET(rSELF)
+ jnz MterpException
+ .if $is_object
+ SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value
+ .else
+ .if $wide
+ SET_WIDE_VREG %rax, rINSTq # fp[A] <- value
+ .else
+ SET_VREG %eax, rINSTq # fp[A] <- value
+ .endif
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_boolean.S b/runtime/interpreter/mterp/x86_64/op_sget_boolean.S
new file mode 100644
index 0000000..7d358da
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sget_boolean.S
@@ -0,0 +1 @@
+%include "x86_64/op_sget.S" {"helper":"artGetBooleanStaticFromCode"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_byte.S b/runtime/interpreter/mterp/x86_64/op_sget_byte.S
new file mode 100644
index 0000000..79d9ff4
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sget_byte.S
@@ -0,0 +1 @@
+%include "x86_64/op_sget.S" {"helper":"artGetByteStaticFromCode"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_char.S b/runtime/interpreter/mterp/x86_64/op_sget_char.S
new file mode 100644
index 0000000..4488610
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sget_char.S
@@ -0,0 +1 @@
+%include "x86_64/op_sget.S" {"helper":"artGetCharStaticFromCode"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_object.S b/runtime/interpreter/mterp/x86_64/op_sget_object.S
new file mode 100644
index 0000000..09b627e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sget_object.S
@@ -0,0 +1 @@
+%include "x86_64/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_short.S b/runtime/interpreter/mterp/x86_64/op_sget_short.S
new file mode 100644
index 0000000..47ac238
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sget_short.S
@@ -0,0 +1 @@
+%include "x86_64/op_sget.S" {"helper":"artGetShortStaticFromCode"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_wide.S b/runtime/interpreter/mterp/x86_64/op_sget_wide.S
new file mode 100644
index 0000000..aa22343
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sget_wide.S
@@ -0,0 +1 @@
+%include "x86_64/op_sget.S" {"helper":"artGet64StaticFromCode", "wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shl_int.S b/runtime/interpreter/mterp/x86_64/op_shl_int.S
new file mode 100644
index 0000000..fa1edb7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shl_int.S
@@ -0,0 +1 @@
+%include "x86_64/binop1.S" {"instr":"sall %cl, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shl_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_shl_int_2addr.S
new file mode 100644
index 0000000..dd96279
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shl_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/shop2addr.S" {"instr":"sall %cl, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shl_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_shl_int_lit8.S
new file mode 100644
index 0000000..39b23ae
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shl_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit8.S" {"instr":"sall %cl, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shl_long.S b/runtime/interpreter/mterp/x86_64/op_shl_long.S
new file mode 100644
index 0000000..fdc7cb6
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shl_long.S
@@ -0,0 +1 @@
+%include "x86_64/binop1.S" {"instr":"salq %cl, %rax","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shl_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_shl_long_2addr.S
new file mode 100644
index 0000000..546633f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shl_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/shop2addr.S" {"instr":"salq %cl, %rax","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shr_int.S b/runtime/interpreter/mterp/x86_64/op_shr_int.S
new file mode 100644
index 0000000..fc289f4
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shr_int.S
@@ -0,0 +1 @@
+%include "x86_64/binop1.S" {"instr":"sarl %cl, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shr_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_shr_int_2addr.S
new file mode 100644
index 0000000..0e5bca7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shr_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/shop2addr.S" {"instr":"sarl %cl, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shr_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_shr_int_lit8.S
new file mode 100644
index 0000000..3cc9307
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shr_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit8.S" {"instr":"sarl %cl, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shr_long.S b/runtime/interpreter/mterp/x86_64/op_shr_long.S
new file mode 100644
index 0000000..25028d3
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shr_long.S
@@ -0,0 +1 @@
+%include "x86_64/binop1.S" {"instr":"sarq %cl, %rax","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_shr_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_shr_long_2addr.S
new file mode 100644
index 0000000..3738413
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_shr_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/shop2addr.S" {"instr":"sarq %cl, %rax","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sparse_switch.S b/runtime/interpreter/mterp/x86_64/op_sparse_switch.S
new file mode 100644
index 0000000..0eaa514
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sparse_switch.S
@@ -0,0 +1 @@
+%include "x86_64/op_packed_switch.S" { "func":"MterpDoSparseSwitch" }
diff --git a/runtime/interpreter/mterp/x86_64/op_sput.S b/runtime/interpreter/mterp/x86_64/op_sput.S
new file mode 100644
index 0000000..e92b032
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sput.S
@@ -0,0 +1,17 @@
+%default { "helper":"artSet32StaticFromCode"}
+/*
+ * General SPUT handler wrapper.
+ *
+ * for: sput, sput-boolean, sput-byte, sput-char, sput-short
+ */
+ /* op vAA, field@BBBB */
+ .extern $helper
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref BBBB
+ GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
+ movq rSELF, OUT_ARG3 # self
+ call SYMBOL($helper)
+ testb %al, %al
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_boolean.S b/runtime/interpreter/mterp/x86_64/op_sput_boolean.S
new file mode 100644
index 0000000..8718915
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sput_boolean.S
@@ -0,0 +1 @@
+%include "x86_64/op_sput.S" {"helper":"artSet8StaticFromCode"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_byte.S b/runtime/interpreter/mterp/x86_64/op_sput_byte.S
new file mode 100644
index 0000000..8718915
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sput_byte.S
@@ -0,0 +1 @@
+%include "x86_64/op_sput.S" {"helper":"artSet8StaticFromCode"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_char.S b/runtime/interpreter/mterp/x86_64/op_sput_char.S
new file mode 100644
index 0000000..2fe9d14
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sput_char.S
@@ -0,0 +1 @@
+%include "x86_64/op_sput.S" {"helper":"artSet16StaticFromCode"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_object.S b/runtime/interpreter/mterp/x86_64/op_sput_object.S
new file mode 100644
index 0000000..eb5a376
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sput_object.S
@@ -0,0 +1,10 @@
+ EXPORT_PC
+ leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0
+ movq rPC, OUT_ARG1
+ REFRESH_INST ${opnum}
+ movq rINSTq, OUT_ARG2
+ movq rSELF, OUT_ARG3
+ call SYMBOL(MterpSputObject)
+ testb %al, %al
+ jz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_short.S b/runtime/interpreter/mterp/x86_64/op_sput_short.S
new file mode 100644
index 0000000..2fe9d14
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sput_short.S
@@ -0,0 +1 @@
+%include "x86_64/op_sput.S" {"helper":"artSet16StaticFromCode"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_wide.S b/runtime/interpreter/mterp/x86_64/op_sput_wide.S
new file mode 100644
index 0000000..c4bc269
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sput_wide.S
@@ -0,0 +1,15 @@
+/*
+ * SPUT_WIDE handler wrapper.
+ *
+ */
+ /* sput-wide vAA, field@BBBB */
+ .extern artSet64IndirectStaticFromMterp
+ EXPORT_PC
+ movzwq 2(rPC), OUT_ARG0 # field ref BBBB
+ movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
+ leaq VREG_ADDRESS(rINSTq), OUT_ARG2 # &fp[AA]
+ movq rSELF, OUT_ARG3 # self
+ call SYMBOL(artSet64IndirectStaticFromMterp)
+ testb %al, %al
+ jnz MterpException
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/op_sub_double.S b/runtime/interpreter/mterp/x86_64/op_sub_double.S
new file mode 100644
index 0000000..952667e
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sub_double.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop.S" {"instr":"subs","suff":"d"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sub_double_2addr.S b/runtime/interpreter/mterp/x86_64/op_sub_double_2addr.S
new file mode 100644
index 0000000..0bd5dbb
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sub_double_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop2Addr.S" {"instr":"subs","suff":"d"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sub_float.S b/runtime/interpreter/mterp/x86_64/op_sub_float.S
new file mode 100644
index 0000000..ea0ae14
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sub_float.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop.S" {"instr":"subs","suff":"s"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sub_float_2addr.S b/runtime/interpreter/mterp/x86_64/op_sub_float_2addr.S
new file mode 100644
index 0000000..9dd1780
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sub_float_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/sseBinop2Addr.S" {"instr":"subs","suff":"s"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sub_int.S b/runtime/interpreter/mterp/x86_64/op_sub_int.S
new file mode 100644
index 0000000..560394f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sub_int.S
@@ -0,0 +1 @@
+%include "x86_64/binop.S" {"instr":"subl (rFP,%rcx,4), %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sub_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_sub_int_2addr.S
new file mode 100644
index 0000000..6f50f78
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sub_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binop2addr.S" {"instr":"subl %eax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sub_long.S b/runtime/interpreter/mterp/x86_64/op_sub_long.S
new file mode 100644
index 0000000..7fa54e7
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sub_long.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide.S" {"instr":"subq (rFP,%rcx,4), %rax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sub_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_sub_long_2addr.S
new file mode 100644
index 0000000..c18be10
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_sub_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide2addr.S" {"instr":"subq %rax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/op_throw.S b/runtime/interpreter/mterp/x86_64/op_throw.S
new file mode 100644
index 0000000..22ed990
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_throw.S
@@ -0,0 +1,10 @@
+/*
+ * Throw an exception object in the current thread.
+ */
+ /* throw vAA */
+ EXPORT_PC
+ GET_VREG %eax, rINSTq # eax<- vAA (exception object)
+ testb %al, %al
+ jz common_errNullObject
+ movq %rax, THREAD_EXCEPTION_OFFSET(rSELF)
+ jmp MterpException
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_3e.S b/runtime/interpreter/mterp/x86_64/op_unused_3e.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_3e.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_3f.S b/runtime/interpreter/mterp/x86_64/op_unused_3f.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_3f.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_40.S b/runtime/interpreter/mterp/x86_64/op_unused_40.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_40.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_41.S b/runtime/interpreter/mterp/x86_64/op_unused_41.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_41.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_42.S b/runtime/interpreter/mterp/x86_64/op_unused_42.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_42.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_43.S b/runtime/interpreter/mterp/x86_64/op_unused_43.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_43.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_79.S b/runtime/interpreter/mterp/x86_64/op_unused_79.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_79.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_7a.S b/runtime/interpreter/mterp/x86_64/op_unused_7a.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_7a.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_f4.S b/runtime/interpreter/mterp/x86_64/op_unused_f4.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_f4.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_fa.S b/runtime/interpreter/mterp/x86_64/op_unused_fa.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_fa.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_fb.S b/runtime/interpreter/mterp/x86_64/op_unused_fb.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_fb.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_fc.S b/runtime/interpreter/mterp/x86_64/op_unused_fc.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_fc.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_fd.S b/runtime/interpreter/mterp/x86_64/op_unused_fd.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_fd.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_fe.S b/runtime/interpreter/mterp/x86_64/op_unused_fe.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_fe.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_unused_ff.S b/runtime/interpreter/mterp/x86_64/op_unused_ff.S
new file mode 100644
index 0000000..280615f
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_unused_ff.S
@@ -0,0 +1 @@
+%include "x86_64/unused.S"
diff --git a/runtime/interpreter/mterp/x86_64/op_ushr_int.S b/runtime/interpreter/mterp/x86_64/op_ushr_int.S
new file mode 100644
index 0000000..dd91086
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_ushr_int.S
@@ -0,0 +1 @@
+%include "x86_64/binop1.S" {"instr":"shrl %cl, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_ushr_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_ushr_int_2addr.S
new file mode 100644
index 0000000..d38aedd
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_ushr_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/shop2addr.S" {"instr":"shrl %cl, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_ushr_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_ushr_int_lit8.S
new file mode 100644
index 0000000..f7ff8ab
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_ushr_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit8.S" {"instr":"shrl %cl, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_ushr_long.S b/runtime/interpreter/mterp/x86_64/op_ushr_long.S
new file mode 100644
index 0000000..7c6daca
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_ushr_long.S
@@ -0,0 +1 @@
+%include "x86_64/binop1.S" {"instr":"shrq %cl, %rax","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_ushr_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_ushr_long_2addr.S
new file mode 100644
index 0000000..cd6a22c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_ushr_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/shop2addr.S" {"instr":"shrq %cl, %rax","wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_xor_int.S b/runtime/interpreter/mterp/x86_64/op_xor_int.S
new file mode 100644
index 0000000..b295d74
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_xor_int.S
@@ -0,0 +1 @@
+%include "x86_64/binop.S" {"instr":"xorl (rFP,%rcx,4), %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_xor_int_2addr.S b/runtime/interpreter/mterp/x86_64/op_xor_int_2addr.S
new file mode 100644
index 0000000..879bfc0
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_xor_int_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binop2addr.S" {"instr":"xorl %eax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/op_xor_int_lit16.S b/runtime/interpreter/mterp/x86_64/op_xor_int_lit16.S
new file mode 100644
index 0000000..5d375a1
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_xor_int_lit16.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit16.S" {"instr":"xorl %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_xor_int_lit8.S b/runtime/interpreter/mterp/x86_64/op_xor_int_lit8.S
new file mode 100644
index 0000000..54cce9c
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_xor_int_lit8.S
@@ -0,0 +1 @@
+%include "x86_64/binopLit8.S" {"instr":"xorl %ecx, %eax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_xor_long.S b/runtime/interpreter/mterp/x86_64/op_xor_long.S
new file mode 100644
index 0000000..52b44e2
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_xor_long.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide.S" {"instr":"xorq (rFP,%rcx,4), %rax"}
diff --git a/runtime/interpreter/mterp/x86_64/op_xor_long_2addr.S b/runtime/interpreter/mterp/x86_64/op_xor_long_2addr.S
new file mode 100644
index 0000000..d75c4ba
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/op_xor_long_2addr.S
@@ -0,0 +1 @@
+%include "x86_64/binopWide2addr.S" {"instr":"xorq %rax, (rFP,%rcx,4)"}
diff --git a/runtime/interpreter/mterp/x86_64/shop2addr.S b/runtime/interpreter/mterp/x86_64/shop2addr.S
new file mode 100644
index 0000000..6b06d00
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/shop2addr.S
@@ -0,0 +1,19 @@
+%default {"wide":"0"}
+/*
+ * Generic 32-bit "shift/2addr" operation.
+ */
+ /* shift/2addr vA, vB */
+ movl rINST, %ecx # ecx <- BA
+ sarl $$4, %ecx # ecx <- B
+ GET_VREG %ecx, %rcx # ecx <- vBB
+ andb $$0xf, rINSTbl # rINST <- A
+ .if $wide
+ GET_WIDE_VREG %rax, rINSTq # rax <- vAA
+ $instr # ex: sarl %cl, %eax
+ SET_WIDE_VREG %rax, rINSTq
+ .else
+ GET_VREG %eax, rINSTq # eax <- vAA
+ $instr # ex: sarl %cl, %eax
+ SET_VREG %eax, rINSTq
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/sseBinop.S b/runtime/interpreter/mterp/x86_64/sseBinop.S
new file mode 100644
index 0000000..09d3364
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/sseBinop.S
@@ -0,0 +1,9 @@
+%default {"instr":"","suff":""}
+ movzbq 2(rPC), %rcx # ecx <- BB
+ movzbq 3(rPC), %rax # eax <- CC
+ movs${suff} VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ ${instr}${suff} VREG_ADDRESS(%rax), %xmm0
+ movs${suff} %xmm0, VREG_ADDRESS(rINSTq) # vAA <- %xmm0
+ pxor %xmm0, %xmm0
+ movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86_64/sseBinop2Addr.S b/runtime/interpreter/mterp/x86_64/sseBinop2Addr.S
new file mode 100644
index 0000000..084166b
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/sseBinop2Addr.S
@@ -0,0 +1,10 @@
+%default {"instr":"","suff":""}
+ movl rINST, %ecx # ecx <- A+
+ andl $$0xf, %ecx # ecx <- A
+ movs${suff} VREG_ADDRESS(%rcx), %xmm0 # %xmm0 <- 1st src
+ sarl $$4, rINST # rINST<- B
+ ${instr}${suff} VREG_ADDRESS(rINSTq), %xmm0
+ movs${suff} %xmm0, VREG_ADDRESS(%rcx) # vAA<- %xmm0
+ pxor %xmm0, %xmm0
+ movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/unop.S b/runtime/interpreter/mterp/x86_64/unop.S
new file mode 100644
index 0000000..1777123
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/unop.S
@@ -0,0 +1,22 @@
+%default {"preinstr":"", "instr":"", "wide":"0"}
+/*
+ * Generic 32/64-bit unary operation. Provide an "instr" line that
+ * specifies an instruction that performs "result = op eax".
+ */
+ /* unop vA, vB */
+ movl rINST, %ecx # rcx <- A+
+ sarl $$4,rINST # rINST <- B
+ .if ${wide}
+ GET_WIDE_VREG %rax, rINSTq # rax <- vB
+ .else
+ GET_VREG %eax, rINSTq # eax <- vB
+ .endif
+ andb $$0xf,%cl # ecx <- A
+$preinstr
+$instr
+ .if ${wide}
+ SET_WIDE_VREG %rax, %rcx
+ .else
+ SET_VREG %eax, %rcx
+ .endif
+ ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
diff --git a/runtime/interpreter/mterp/x86_64/unused.S b/runtime/interpreter/mterp/x86_64/unused.S
new file mode 100644
index 0000000..c95ef94
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/unused.S
@@ -0,0 +1,4 @@
+/*
+ * Bail to reference interpreter to throw.
+ */
+ jmp MterpFallback
diff --git a/runtime/interpreter/mterp/x86_64/zcmp.S b/runtime/interpreter/mterp/x86_64/zcmp.S
new file mode 100644
index 0000000..0051407
--- /dev/null
+++ b/runtime/interpreter/mterp/x86_64/zcmp.S
@@ -0,0 +1,19 @@
+/*
+ * Generic one-operand compare-and-branch operation. Provide a "revcmp"
+ * fragment that specifies the *reverse* comparison to perform, e.g.
+ * for "if-le" you would use "gt".
+ *
+ * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+ */
+ /* if-cmp vAA, +BBBB */
+ cmpl $$0, VREG_ADDRESS(rINSTq) # compare (vA, 0)
+ movl $$2, rINST # assume branch not taken
+ j${revcmp} 1f
+ movswq 2(rPC), rINSTq # fetch signed displacement
+1:
+ MTERP_PROFILE_BRANCH
+ addq rINSTq, rINSTq # rINSTq <- AA * 2
+ leaq (rPC, rINSTq), rPC
+ FETCH_INST
+ jle MterpCheckSuspendAndContinue # AA * 2 <= 0 => suspend check
+ GOTO_NEXT
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 5c44193..191c0c7 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -716,9 +716,11 @@
libraries_.get()->UnloadNativeLibraries();
}
-bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject class_loader,
- bool is_shared_namespace, jstring library_path,
- jstring permitted_path, std::string* error_msg) {
+bool JavaVMExt::LoadNativeLibrary(JNIEnv* env,
+ const std::string& path,
+ jobject class_loader,
+ jstring library_path,
+ std::string* error_msg) {
error_msg->clear();
// See if we've already loaded this library. If we have, and the class loader
@@ -777,9 +779,12 @@
Locks::mutator_lock_->AssertNotHeld(self);
const char* path_str = path.empty() ? nullptr : path.c_str();
- void* handle = android::OpenNativeLibrary(env, runtime_->GetTargetSdkVersion(), path_str,
- class_loader, is_shared_namespace, library_path,
- permitted_path);
+ void* handle = android::OpenNativeLibrary(env,
+ runtime_->GetTargetSdkVersion(),
+ path_str,
+ class_loader,
+ library_path);
+
bool needs_native_bridge = false;
if (handle == nullptr) {
if (android::NativeBridgeIsSupported(path_str)) {
diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h
index 8cae1e5..3d055cd 100644
--- a/runtime/java_vm_ext.h
+++ b/runtime/java_vm_ext.h
@@ -85,8 +85,10 @@
* Returns 'true' on success. On failure, sets 'error_msg' to a
* human-readable description of the error.
*/
- bool LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject class_loader,
- bool is_shared_namespace, jstring library_path, jstring permitted_path,
+ bool LoadNativeLibrary(JNIEnv* env,
+ const std::string& path,
+ jobject class_loader,
+ jstring library_path,
std::string* error_msg);
// Unload native libraries with cleared class loaders.
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 3e66ce2..a3b99e3 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -59,12 +59,7 @@
}
void Jit::DumpInfo(std::ostream& os) {
- os << "JIT code cache size=" << PrettySize(code_cache_->CodeCacheSize()) << "\n"
- << "JIT data cache size=" << PrettySize(code_cache_->DataCacheSize()) << "\n"
- << "JIT current capacity=" << PrettySize(code_cache_->GetCurrentCapacity()) << "\n"
- << "JIT number of compiled code=" << code_cache_->NumberOfCompiledCode() << "\n"
- << "JIT total number of compilations=" << code_cache_->NumberOfCompilations() << "\n"
- << "JIT total number of osr compilations=" << code_cache_->NumberOfOsrCompilations() << "\n";
+ code_cache_->Dump(os);
cumulative_timings_.Dump(os);
}
@@ -97,7 +92,7 @@
return nullptr;
}
jit->save_profiling_info_ = options->GetSaveProfilingInfo();
- LOG(INFO) << "JIT created with initial_capacity="
+ VLOG(jit) << "JIT created with initial_capacity="
<< PrettySize(options->GetCodeCacheInitialCapacity())
<< ", max_capacity=" << PrettySize(options->GetCodeCacheMaxCapacity())
<< ", compile_threshold=" << options->GetCompileThreshold()
@@ -174,7 +169,6 @@
// of that proxy method, as the compiler does not expect a proxy method.
ArtMethod* method_to_compile = method->GetInterfaceMethodIfProxy(sizeof(void*));
if (!code_cache_->NotifyCompilationOf(method_to_compile, self, osr)) {
- VLOG(jit) << "JIT not compiling " << PrettyMethod(method) << " due to code cache";
return false;
}
bool success = jit_compile_method_(jit_compiler_handle_, method_to_compile, self, osr);
@@ -213,6 +207,10 @@
return false;
}
+bool Jit::CanInvokeCompiledCode(ArtMethod* method) {
+ return code_cache_->ContainsPc(method->GetEntryPointFromQuickCompiledCode());
+}
+
Jit::~Jit() {
DCHECK(!save_profiling_info_ || !ProfileSaver::IsStarted());
if (dump_info_on_shutdown_) {
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 109ca3d..3f54192 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -84,8 +84,12 @@
// into the specified class linker to the jit debug interface,
void DumpTypeInfoForLoadedTypes(ClassLinker* linker);
+ // Return whether we should try to JIT compiled code as soon as an ArtMethod is invoked.
bool JitAtFirstUse();
+ // Return whether we can invoke JIT code for `method`.
+ bool CanInvokeCompiledCode(ArtMethod* method);
+
// If an OSR compiled version is available for `method`,
// and `dex_pc + dex_pc_offset` is an entry point of that compiled
// version, this method will jump to the compiled code, let it run,
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 8858b48..e5be2a4 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -24,6 +24,7 @@
#include "debugger_interface.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "gc/accounting/bitmap-inl.h"
+#include "jit/jit.h"
#include "jit/profiling_info.h"
#include "linear_alloc.h"
#include "mem_map.h"
@@ -123,13 +124,15 @@
current_capacity_(initial_code_capacity + initial_data_capacity),
code_end_(initial_code_capacity),
data_end_(initial_data_capacity),
- has_done_full_collection_(false),
+ last_collection_increased_code_cache_(false),
last_update_time_ns_(0),
garbage_collect_code_(garbage_collect_code),
used_memory_for_data_(0),
used_memory_for_code_(0),
number_of_compilations_(0),
- number_of_osr_compilations_(0) {
+ number_of_osr_compilations_(0),
+ number_of_deoptimizations_(0),
+ number_of_collections_(0) {
DCHECK_GE(max_capacity, initial_code_capacity + initial_data_capacity);
code_mspace_ = create_mspace_with_base(code_map_->Begin(), code_end_, false /*locked*/);
@@ -363,16 +366,6 @@
return reinterpret_cast<uint8_t*>(method_header);
}
-size_t JitCodeCache::NumberOfCompilations() {
- MutexLock mu(Thread::Current(), lock_);
- return number_of_compilations_;
-}
-
-size_t JitCodeCache::NumberOfOsrCompilations() {
- MutexLock mu(Thread::Current(), lock_);
- return number_of_osr_compilations_;
-}
-
size_t JitCodeCache::CodeCacheSize() {
MutexLock mu(Thread::Current(), lock_);
return CodeCacheSizeLocked();
@@ -391,11 +384,6 @@
return used_memory_for_data_;
}
-size_t JitCodeCache::NumberOfCompiledCode() {
- MutexLock mu(Thread::Current(), lock_);
- return method_code_map_.size();
-}
-
void JitCodeCache::ClearData(Thread* self, void* data) {
MutexLock mu(self, lock_);
FreeData(reinterpret_cast<uint8_t*>(data));
@@ -546,34 +534,20 @@
}
}
-void JitCodeCache::RemoveUnusedCode(Thread* self) {
- // Clear the osr map, chances are most of the code in it is now dead.
- {
- MutexLock mu(self, lock_);
- osr_code_map_.clear();
- }
-
- // Run a checkpoint on all threads to mark the JIT compiled code they are running.
- MarkCompiledCodeOnThreadStacks(self);
-
- // Iterate over all compiled code and remove entries that are not marked and not
- // the entrypoint of their corresponding ArtMethod.
- {
- MutexLock mu(self, lock_);
- ScopedCodeCacheWrite scc(code_map_.get());
- for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
- const void* code_ptr = it->first;
- ArtMethod* method = it->second;
- uintptr_t allocation = FromCodeToAllocation(code_ptr);
- const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
- if ((method->GetEntryPointFromQuickCompiledCode() != method_header->GetEntryPoint()) &&
- !GetLiveBitmap()->Test(allocation)) {
- FreeCode(code_ptr, method);
- it = method_code_map_.erase(it);
- } else {
- ++it;
- }
- }
+bool JitCodeCache::ShouldDoFullCollection() {
+ if (current_capacity_ == max_capacity_) {
+ // Always do a full collection when the code cache is full.
+ return true;
+ } else if (current_capacity_ < kReservedCapacity) {
+ // Always do partial collection when the code cache size is below the reserved
+ // capacity.
+ return false;
+ } else if (last_collection_increased_code_cache_) {
+ // This time do a full collection.
+ return true;
+ } else {
+ // This time do a partial collection.
+ return false;
}
}
@@ -591,6 +565,7 @@
if (WaitForPotentialCollectionToComplete(self)) {
return;
} else {
+ number_of_collections_++;
live_bitmap_.reset(CodeCacheBitmap::Create(
"code-cache-bitmap",
reinterpret_cast<uintptr_t>(code_map_->Begin()),
@@ -599,70 +574,122 @@
}
}
- // Check if we want to do a full collection.
- bool do_full_collection = true;
+ TimingLogger logger("JIT code cache timing logger", true, VLOG_IS_ON(jit));
{
- MutexLock mu(self, lock_);
- if (current_capacity_ == max_capacity_) {
- // Always do a full collection when the code cache is full.
- do_full_collection = true;
- } else if (current_capacity_ < kReservedCapacity) {
- // Do a partial collection until we hit the reserved capacity limit.
- do_full_collection = false;
- } else if (has_done_full_collection_) {
- // Do a partial collection if we have done a full collection in the last
- // collection round.
- do_full_collection = false;
+ TimingLogger::ScopedTiming st("Code cache collection", &logger);
+
+ bool do_full_collection = false;
+ {
+ MutexLock mu(self, lock_);
+ do_full_collection = ShouldDoFullCollection();
+ }
+
+ if (!kIsDebugBuild || VLOG_IS_ON(jit)) {
+ LOG(INFO) << "Do "
+ << (do_full_collection ? "full" : "partial")
+ << " code cache collection, code="
+ << PrettySize(CodeCacheSize())
+ << ", data=" << PrettySize(DataCacheSize());
+ }
+
+ DoCollection(self, /* collect_profiling_info */ do_full_collection);
+
+ if (!kIsDebugBuild || VLOG_IS_ON(jit)) {
+ LOG(INFO) << "After code cache collection, code="
+ << PrettySize(CodeCacheSize())
+ << ", data=" << PrettySize(DataCacheSize());
+ }
+
+ {
+ MutexLock mu(self, lock_);
+
+ // Increase the code cache only when we do partial collections.
+ // TODO: base this strategy on how full the code cache is?
+ if (do_full_collection) {
+ last_collection_increased_code_cache_ = false;
+ } else {
+ last_collection_increased_code_cache_ = true;
+ IncreaseCodeCacheCapacity();
+ }
+
+ bool next_collection_will_be_full = ShouldDoFullCollection();
+
+ // Start polling the liveness of compiled code to prepare for the next full collection.
+ // We avoid doing this if exit stubs are installed to not mess with the instrumentation.
+ // TODO(ngeoffray): Clean up instrumentation and code cache interactions.
+ if (!Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled() &&
+ next_collection_will_be_full) {
+ // Save the entry point of methods we have compiled, and update the entry
+ // point of those methods to the interpreter. If the method is invoked, the
+ // interpreter will update its entry point to the compiled code and call it.
+ for (ProfilingInfo* info : profiling_infos_) {
+ const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
+ if (ContainsPc(entry_point)) {
+ info->SetSavedEntryPoint(entry_point);
+ info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ }
+ }
+
+ DCHECK(CheckLiveCompiledCodeHasProfilingInfo());
+ }
+ live_bitmap_.reset(nullptr);
+ NotifyCollectionDone(self);
}
}
+ Runtime::Current()->GetJit()->AddTimingLogger(logger);
+}
- if (!kIsDebugBuild || VLOG_IS_ON(jit)) {
- LOG(INFO) << "Do "
- << (do_full_collection ? "full" : "partial")
- << " code cache collection, code="
- << PrettySize(CodeCacheSize())
- << ", data=" << PrettySize(DataCacheSize());
- }
-
- if (do_full_collection) {
- DoFullCollection(self);
- } else {
- RemoveUnusedCode(self);
- }
-
- {
- MutexLock mu(self, lock_);
- if (!do_full_collection) {
- has_done_full_collection_ = false;
- IncreaseCodeCacheCapacity();
+void JitCodeCache::RemoveUnmarkedCode(Thread* self) {
+ MutexLock mu(self, lock_);
+ ScopedCodeCacheWrite scc(code_map_.get());
+ // Iterate over all compiled code and remove entries that are not marked.
+ for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
+ const void* code_ptr = it->first;
+ ArtMethod* method = it->second;
+ uintptr_t allocation = FromCodeToAllocation(code_ptr);
+ if (GetLiveBitmap()->Test(allocation)) {
+ ++it;
} else {
- has_done_full_collection_ = true;
+ const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
+ if (method_header->GetEntryPoint() == GetQuickToInterpreterBridge()) {
+ method->ClearCounter();
+ }
+ FreeCode(code_ptr, method);
+ it = method_code_map_.erase(it);
}
- live_bitmap_.reset(nullptr);
- NotifyCollectionDone(self);
- }
-
- if (!kIsDebugBuild || VLOG_IS_ON(jit)) {
- LOG(INFO) << "After code cache collection, code="
- << PrettySize(CodeCacheSize())
- << ", data=" << PrettySize(DataCacheSize());
}
}
-void JitCodeCache::DoFullCollection(Thread* self) {
- instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+void JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) {
{
MutexLock mu(self, lock_);
- // Walk over all compiled methods and set the entry points of these
- // methods to interpreter.
- for (auto& it : method_code_map_) {
- instrumentation->UpdateMethodsCode(it.second, GetQuickToInterpreterBridge());
+ if (collect_profiling_info) {
+ // Clear the profiling info of methods that do not have compiled code as entrypoint.
+ // Also remove the saved entry point from the ProfilingInfo objects.
+ for (ProfilingInfo* info : profiling_infos_) {
+ const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
+ if (!ContainsPc(ptr) && !info->IsMethodBeingCompiled()) {
+ info->GetMethod()->SetProfilingInfo(nullptr);
+ }
+ info->SetSavedEntryPoint(nullptr);
+ }
+ } else if (kIsDebugBuild) {
+ // Sanity check that the profiling infos do not have a dangling entry point.
+ for (ProfilingInfo* info : profiling_infos_) {
+ DCHECK(info->GetSavedEntryPoint() == nullptr);
+ }
}
- // Clear the profiling info of methods that are not being compiled.
- for (ProfilingInfo* info : profiling_infos_) {
- if (!info->IsMethodBeingCompiled()) {
- info->GetMethod()->SetProfilingInfo(nullptr);
+ // Mark compiled code that are entrypoints of ArtMethods. Compiled code that is not
+ // an entry point is either:
+ // - an osr compiled code, that will be removed if not in a thread call stack.
+ // - discarded compiled code, that will be removed if not in a thread call stack.
+ for (const auto& it : method_code_map_) {
+ ArtMethod* method = it.second;
+ const void* code_ptr = it.first;
+ const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
+ if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) {
+ GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(code_ptr));
}
}
@@ -674,41 +701,59 @@
// Run a checkpoint on all threads to mark the JIT compiled code they are running.
MarkCompiledCodeOnThreadStacks(self);
- {
- MutexLock mu(self, lock_);
- // Free unused compiled code, and restore the entry point of used compiled code.
- {
- ScopedCodeCacheWrite scc(code_map_.get());
- for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
- const void* code_ptr = it->first;
- ArtMethod* method = it->second;
- uintptr_t allocation = FromCodeToAllocation(code_ptr);
- const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
- if (GetLiveBitmap()->Test(allocation)) {
- instrumentation->UpdateMethodsCode(method, method_header->GetEntryPoint());
- ++it;
- } else {
- method->ClearCounter();
- DCHECK_NE(method->GetEntryPointFromQuickCompiledCode(), method_header->GetEntryPoint());
- FreeCode(code_ptr, method);
- it = method_code_map_.erase(it);
- }
- }
- }
+ // At this point, mutator threads are still running, and entrypoints of methods can
+ // change. We do know they cannot change to a code cache entry that is not marked,
+ // therefore we can safely remove those entries.
+ RemoveUnmarkedCode(self);
- // Free all profiling infos of methods that were not being compiled.
+ if (collect_profiling_info) {
+ MutexLock mu(self, lock_);
+ // Free all profiling infos of methods not compiled nor being compiled.
auto profiling_kept_end = std::remove_if(profiling_infos_.begin(), profiling_infos_.end(),
[this] (ProfilingInfo* info) NO_THREAD_SAFETY_ANALYSIS {
- if (info->GetMethod()->GetProfilingInfo(sizeof(void*)) == nullptr) {
+ const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
+ // We have previously cleared the ProfilingInfo pointer in the ArtMethod in the hope
+ // that the compiled code would not get revived. As mutator threads run concurrently,
+ // they may have revived the compiled code, and now we are in the situation where
+ // a method has compiled code but no ProfilingInfo.
+ // We make sure compiled methods have a ProfilingInfo object. It is needed for
+ // code cache collection.
+ if (ContainsPc(ptr) && info->GetMethod()->GetProfilingInfo(sizeof(void*)) == nullptr) {
+ // We clear the inline caches as classes in it might be stalled.
+ info->ClearInlineCaches();
+ // Do a fence to make sure the clearing is seen before attaching to the method.
+ QuasiAtomic::ThreadFenceRelease();
+ info->GetMethod()->SetProfilingInfo(info);
+ } else if (info->GetMethod()->GetProfilingInfo(sizeof(void*)) != info) {
+ // No need for this ProfilingInfo object anymore.
FreeData(reinterpret_cast<uint8_t*>(info));
return true;
}
return false;
});
profiling_infos_.erase(profiling_kept_end, profiling_infos_.end());
+ DCHECK(CheckLiveCompiledCodeHasProfilingInfo());
}
}
+bool JitCodeCache::CheckLiveCompiledCodeHasProfilingInfo() {
+ // Check that methods we have compiled do have a ProfilingInfo object. We would
+ // have memory leaks of compiled code otherwise.
+ for (const auto& it : method_code_map_) {
+ ArtMethod* method = it.second;
+ if (method->GetProfilingInfo(sizeof(void*)) == nullptr) {
+ const void* code_ptr = it.first;
+ const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
+ if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) {
+ // If the code is not dead, then we have a problem. Note that this can even
+ // happen just after a collection, as mutator threads are running in parallel
+ // and could deoptimize an existing compiled code.
+ return false;
+ }
+ }
+ }
+ return true;
+}
OatQuickMethodHeader* JitCodeCache::LookupMethodHeader(uintptr_t pc, ArtMethod* method) {
static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA");
@@ -751,23 +796,38 @@
ProfilingInfo* JitCodeCache::AddProfilingInfo(Thread* self,
ArtMethod* method,
const std::vector<uint32_t>& entries,
- bool retry_allocation) {
- ProfilingInfo* info = AddProfilingInfoInternal(self, method, entries);
+ bool retry_allocation)
+ // No thread safety analysis as we are using TryLock/Unlock explicitly.
+ NO_THREAD_SAFETY_ANALYSIS {
+ ProfilingInfo* info = nullptr;
+ if (!retry_allocation) {
+ // If we are allocating for the interpreter, just try to lock, to avoid
+ // lock contention with the JIT.
+ if (lock_.ExclusiveTryLock(self)) {
+ info = AddProfilingInfoInternal(self, method, entries);
+ lock_.ExclusiveUnlock(self);
+ }
+ } else {
+ {
+ MutexLock mu(self, lock_);
+ info = AddProfilingInfoInternal(self, method, entries);
+ }
- if (info == nullptr && retry_allocation) {
- GarbageCollectCache(self);
- info = AddProfilingInfoInternal(self, method, entries);
+ if (info == nullptr) {
+ GarbageCollectCache(self);
+ MutexLock mu(self, lock_);
+ info = AddProfilingInfoInternal(self, method, entries);
+ }
}
return info;
}
-ProfilingInfo* JitCodeCache::AddProfilingInfoInternal(Thread* self,
+ProfilingInfo* JitCodeCache::AddProfilingInfoInternal(Thread* self ATTRIBUTE_UNUSED,
ArtMethod* method,
const std::vector<uint32_t>& entries) {
size_t profile_info_size = RoundUp(
sizeof(ProfilingInfo) + sizeof(InlineCache) * entries.size(),
sizeof(void*));
- MutexLock mu(self, lock_);
// Check whether some other thread has concurrently created it.
ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*));
@@ -821,17 +881,27 @@
bool JitCodeCache::NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr) {
if (!osr && ContainsPc(method->GetEntryPointFromQuickCompiledCode())) {
+ VLOG(jit) << PrettyMethod(method) << " is already compiled";
return false;
}
MutexLock mu(self, lock_);
if (osr && (osr_code_map_.find(method) != osr_code_map_.end())) {
+ VLOG(jit) << PrettyMethod(method) << " is already osr compiled";
return false;
}
+
ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*));
- if (info == nullptr || info->IsMethodBeingCompiled()) {
+ if (info == nullptr) {
+ VLOG(jit) << PrettyMethod(method) << " needs a ProfilingInfo to be compiled";
return false;
}
+
+ if (info->IsMethodBeingCompiled()) {
+ VLOG(jit) << PrettyMethod(method) << " is already being compiled";
+ return false;
+ }
+
info->SetIsMethodBeingCompiled(true);
return true;
}
@@ -849,6 +919,13 @@
void JitCodeCache::InvalidateCompiledCodeFor(ArtMethod* method,
const OatQuickMethodHeader* header) {
+ ProfilingInfo* profiling_info = method->GetProfilingInfo(sizeof(void*));
+ if ((profiling_info != nullptr) &&
+ (profiling_info->GetSavedEntryPoint() == header->GetEntryPoint())) {
+ // Prevent future uses of the compiled code.
+ profiling_info->SetSavedEntryPoint(nullptr);
+ }
+
if (method->GetEntryPointFromQuickCompiledCode() == header->GetEntryPoint()) {
// The entrypoint is the one to invalidate, so we just update
// it to the interpreter entry point and clear the counter to get the method
@@ -864,6 +941,8 @@
osr_code_map_.erase(it);
}
}
+ MutexLock mu(Thread::Current(), lock_);
+ number_of_deoptimizations_++;
}
uint8_t* JitCodeCache::AllocateCode(size_t code_size) {
@@ -893,5 +972,18 @@
mspace_free(data_mspace_, data);
}
+void JitCodeCache::Dump(std::ostream& os) {
+ MutexLock mu(Thread::Current(), lock_);
+ os << "Current JIT code cache size: " << PrettySize(used_memory_for_code_) << "\n"
+ << "Current JIT data cache size: " << PrettySize(used_memory_for_data_) << "\n"
+ << "Current JIT capacity: " << PrettySize(current_capacity_) << "\n"
+ << "Current number of JIT code cache entries: " << method_code_map_.size() << "\n"
+ << "Total number of JIT compilations: " << number_of_compilations_ << "\n"
+ << "Total number of JIT compilations for on stack replacement: "
+ << number_of_osr_compilations_ << "\n"
+ << "Total number of deoptimizations: " << number_of_deoptimizations_ << "\n"
+ << "Total number of JIT code cache collections: " << number_of_collections_ << std::endl;
+}
+
} // namespace jit
} // namespace art
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index 4574edf..0bd4f7d 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -67,14 +67,6 @@
// Number of bytes allocated in the data cache.
size_t DataCacheSize() REQUIRES(!lock_);
- // Number of compiled code in the code cache. Note that this is not the number
- // of methods that got JIT compiled, as we might have collected some.
- size_t NumberOfCompiledCode() REQUIRES(!lock_);
-
- // Number of compilations done throughout the lifetime of the JIT.
- size_t NumberOfCompilations() REQUIRES(!lock_);
- size_t NumberOfOsrCompilations() REQUIRES(!lock_);
-
bool NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr)
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!lock_);
@@ -124,6 +116,11 @@
return live_bitmap_.get();
}
+ // Return whether we should do a full collection given the current state of the cache.
+ bool ShouldDoFullCollection()
+ REQUIRES(lock_)
+ SHARED_REQUIRES(Locks::mutator_lock_);
+
// Perform a collection on the code cache.
void GarbageCollectCache(Thread* self)
REQUIRES(!lock_)
@@ -180,6 +177,8 @@
REQUIRES(!lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
+ void Dump(std::ostream& os) REQUIRES(!lock_);
+
private:
// Take ownership of maps.
JitCodeCache(MemMap* code_map,
@@ -208,7 +207,7 @@
ProfilingInfo* AddProfilingInfoInternal(Thread* self,
ArtMethod* method,
const std::vector<uint32_t>& entries)
- REQUIRES(!lock_)
+ REQUIRES(lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
// If a collection is in progress, wait for it to finish. Return
@@ -235,11 +234,11 @@
// Set the footprint limit of the code cache.
void SetFootprintLimit(size_t new_footprint) REQUIRES(lock_);
- void DoFullCollection(Thread* self)
+ void DoCollection(Thread* self, bool collect_profiling_info)
REQUIRES(!lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
- void RemoveUnusedCode(Thread* self)
+ void RemoveUnmarkedCode(Thread* self)
REQUIRES(!lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
@@ -247,6 +246,15 @@
REQUIRES(!lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
+ bool CheckLiveCompiledCodeHasProfilingInfo()
+ REQUIRES(lock_)
+ SHARED_REQUIRES(Locks::mutator_lock_);
+
+ void FreeCode(uint8_t* code) REQUIRES(lock_);
+ uint8_t* AllocateCode(size_t code_size) REQUIRES(lock_);
+ void FreeData(uint8_t* data) REQUIRES(lock_);
+ uint8_t* AllocateData(size_t data_size) REQUIRES(lock_);
+
// Lock for guarding allocations, collections, and the method_code_map_.
Mutex lock_;
// Condition to wait on during collection.
@@ -282,8 +290,8 @@
// The current footprint in bytes of the data portion of the code cache.
size_t data_end_ GUARDED_BY(lock_);
- // Whether a full collection has already been done on the current capacity.
- bool has_done_full_collection_ GUARDED_BY(lock_);
+ // Whether the last collection round increased the code cache.
+ bool last_collection_increased_code_cache_ GUARDED_BY(lock_);
// Last time the the code_cache was updated.
// It is atomic to avoid locking when reading it.
@@ -298,19 +306,21 @@
// The size in bytes of used memory for the code portion of the code cache.
size_t used_memory_for_code_ GUARDED_BY(lock_);
- void FreeCode(uint8_t* code) REQUIRES(lock_);
- uint8_t* AllocateCode(size_t code_size) REQUIRES(lock_);
- void FreeData(uint8_t* data) REQUIRES(lock_);
- uint8_t* AllocateData(size_t data_size) REQUIRES(lock_);
-
// Number of compilations done throughout the lifetime of the JIT.
size_t number_of_compilations_ GUARDED_BY(lock_);
+
+ // Number of compilations for on-stack-replacement done throughout the lifetime of the JIT.
size_t number_of_osr_compilations_ GUARDED_BY(lock_);
+ // Number of deoptimizations done throughout the lifetime of the JIT.
+ size_t number_of_deoptimizations_ GUARDED_BY(lock_);
+
+ // Number of code cache collections done throughout the lifetime of the JIT.
+ size_t number_of_collections_ GUARDED_BY(lock_);
+
DISALLOW_IMPLICIT_CONSTRUCTORS(JitCodeCache);
};
-
} // namespace jit
} // namespace art
diff --git a/runtime/jit/jit_instrumentation.cc b/runtime/jit/jit_instrumentation.cc
index a4e40ad..d751e5a 100644
--- a/runtime/jit/jit_instrumentation.cc
+++ b/runtime/jit/jit_instrumentation.cc
@@ -25,6 +25,9 @@
namespace art {
namespace jit {
+// At what priority to schedule jit threads. 9 is the lowest foreground priority on device.
+static constexpr int kJitPoolThreadPthreadPriority = 9;
+
class JitCompileTask FINAL : public Task {
public:
enum TaskKind {
@@ -92,6 +95,7 @@
// There is a DCHECK in the 'AddSamples' method to ensure the tread pool
// is not null when we instrument.
thread_pool_.reset(new ThreadPool("Jit thread pool", 1));
+ thread_pool_->SetPthreadPriority(kJitPoolThreadPthreadPriority);
thread_pool_->StartWorkers(Thread::Current());
{
// Add Jit interpreter instrumentation, tells the interpreter when
@@ -183,7 +187,18 @@
return;
}
- instrumentation_cache_->AddSamples(thread, method, 1);
+ ProfilingInfo* profiling_info = method->GetProfilingInfo(sizeof(void*));
+ // Update the entrypoint if the ProfilingInfo has one. The interpreter will call it
+ // instead of interpreting the method.
+ // We avoid doing this if exit stubs are installed to not mess with the instrumentation.
+ // TODO(ngeoffray): Clean up instrumentation and code cache interactions.
+ if ((profiling_info != nullptr) &&
+ (profiling_info->GetSavedEntryPoint() != nullptr) &&
+ !Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) {
+ method->SetEntryPointFromQuickCompiledCode(profiling_info->GetSavedEntryPoint());
+ } else {
+ instrumentation_cache_->AddSamples(thread, method, 1);
+ }
}
void JitInstrumentationListener::Branch(Thread* thread,
diff --git a/runtime/jit/profiling_info.h b/runtime/jit/profiling_info.h
index ab72373..a8c056c 100644
--- a/runtime/jit/profiling_info.h
+++ b/runtime/jit/profiling_info.h
@@ -126,12 +126,25 @@
is_method_being_compiled_ = value;
}
+ void SetSavedEntryPoint(const void* entry_point) {
+ saved_entry_point_ = entry_point;
+ }
+
+ const void* GetSavedEntryPoint() const {
+ return saved_entry_point_;
+ }
+
+ void ClearInlineCaches() {
+ memset(&cache_, 0, number_of_inline_caches_ * sizeof(InlineCache));
+ }
+
private:
ProfilingInfo(ArtMethod* method, const std::vector<uint32_t>& entries)
: number_of_inline_caches_(entries.size()),
method_(method),
- is_method_being_compiled_(false) {
- memset(&cache_, 0, number_of_inline_caches_ * sizeof(InlineCache));
+ is_method_being_compiled_(false),
+ saved_entry_point_(nullptr) {
+ ClearInlineCaches();
for (size_t i = 0; i < number_of_inline_caches_; ++i) {
cache_[i].dex_pc_ = entries[i];
}
@@ -148,6 +161,10 @@
// TODO: Make the JIT code cache lock global.
bool is_method_being_compiled_;
+ // Entry point of the corresponding ArtMethod, while the JIT code cache
+ // is poking for the liveness of compiled code.
+ const void* saved_entry_point_;
+
// Dynamically allocated array of size `number_of_inline_caches_`.
InlineCache cache_[0];
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 19584ed..103a8b7 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -29,6 +29,7 @@
#include "dex_cache.h"
#include "dex_file.h"
#include "gc/heap-inl.h"
+#include "jit/profiling_info.h"
#include "iftable.h"
#include "object_array-inl.h"
#include "read_barrier-inl.h"
@@ -939,6 +940,12 @@
}
for (ArtMethod& method : GetMethods(pointer_size)) {
method.VisitRoots(visitor, pointer_size);
+ if (method.GetDeclaringClassUnchecked() != nullptr && !method.IsNative()) {
+ ProfilingInfo* profiling_info = method.GetProfilingInfo(pointer_size);
+ if (profiling_info != nullptr) {
+ profiling_info->VisitRoots(visitor);
+ }
+ }
}
}
diff --git a/runtime/native/java_lang_Runtime.cc b/runtime/native/java_lang_Runtime.cc
index c177f19..df794e1 100644
--- a/runtime/native/java_lang_Runtime.cc
+++ b/runtime/native/java_lang_Runtime.cc
@@ -67,9 +67,11 @@
#endif
}
-static jstring Runtime_nativeLoad(JNIEnv* env, jclass, jstring javaFilename, jobject javaLoader,
- jboolean isSharedNamespace, jstring javaLibrarySearchPath,
- jstring javaLibraryPermittedPath) {
+static jstring Runtime_nativeLoad(JNIEnv* env,
+ jclass,
+ jstring javaFilename,
+ jobject javaLoader,
+ jstring javaLibrarySearchPath) {
ScopedUtfChars filename(env, javaFilename);
if (filename.c_str() == nullptr) {
return nullptr;
@@ -79,7 +81,9 @@
// Starting with N nativeLoad uses classloader local
// linker namespace instead of global LD_LIBRARY_PATH
- // (23 is Marshmallow)
+ // (23 is Marshmallow). This call is here to preserve
+ // backwards compatibility for the apps targeting sdk
+ // version <= 23
if (target_sdk_version == 0) {
SetLdLibraryPath(env, javaLibrarySearchPath);
}
@@ -90,9 +94,7 @@
bool success = vm->LoadNativeLibrary(env,
filename.c_str(),
javaLoader,
- isSharedNamespace == JNI_TRUE,
javaLibrarySearchPath,
- javaLibraryPermittedPath,
&error_msg);
if (success) {
return nullptr;
@@ -121,7 +123,7 @@
NATIVE_METHOD(Runtime, gc, "()V"),
NATIVE_METHOD(Runtime, maxMemory, "!()J"),
NATIVE_METHOD(Runtime, nativeExit, "(I)V"),
- NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;ZLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
+ NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(Runtime, totalMemory, "!()J"),
};
diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc
index 34d6a37..5a219ef 100644
--- a/runtime/native/java_lang_StringFactory.cc
+++ b/runtime/native/java_lang_StringFactory.cc
@@ -50,8 +50,10 @@
return soa.AddLocalReference<jstring>(result);
}
+// The char array passed as `java_data` must not be a null reference.
static jstring StringFactory_newStringFromChars(JNIEnv* env, jclass, jint offset,
jint char_count, jcharArray java_data) {
+ DCHECK(java_data != nullptr);
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray*>(java_data)));
diff --git a/runtime/openjdkjvm/OpenjdkJvm.cc b/runtime/openjdkjvm/OpenjdkJvm.cc
index 725067a..d377457 100644
--- a/runtime/openjdkjvm/OpenjdkJvm.cc
+++ b/runtime/openjdkjvm/OpenjdkJvm.cc
@@ -329,9 +329,10 @@
}
-JNIEXPORT jstring JVM_NativeLoad(JNIEnv* env, jstring javaFilename, jobject javaLoader,
- jboolean isSharedNamespace, jstring javaLibrarySearchPath,
- jstring javaLibraryPermittedPath) {
+JNIEXPORT jstring JVM_NativeLoad(JNIEnv* env,
+ jstring javaFilename,
+ jobject javaLoader,
+ jstring javaLibrarySearchPath) {
ScopedUtfChars filename(env, javaFilename);
if (filename.c_str() == NULL) {
return NULL;
@@ -354,9 +355,7 @@
bool success = vm->LoadNativeLibrary(env,
filename.c_str(),
javaLoader,
- isSharedNamespace == JNI_TRUE,
javaLibrarySearchPath,
- javaLibraryPermittedPath,
&error_msg);
if (success) {
return nullptr;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index eb5455a..8c813b4 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -316,6 +316,7 @@
linear_alloc_.reset();
low_4gb_arena_pool_.reset();
arena_pool_.reset();
+ jit_arena_pool_.reset();
MemMap::Shutdown();
ATRACE_END();
@@ -1019,10 +1020,13 @@
// Use MemMap arena pool for jit, malloc otherwise. Malloc arenas are faster to allocate but
// can't be trimmed as easily.
const bool use_malloc = IsAotCompiler();
- arena_pool_.reset(new ArenaPool(use_malloc, false));
+ arena_pool_.reset(new ArenaPool(use_malloc, /* low_4gb */ false));
+ jit_arena_pool_.reset(
+ new ArenaPool(/* use_malloc */ false, /* low_4gb */ false, "CompilerMetadata"));
+
if (IsAotCompiler() && Is64BitInstructionSet(kRuntimeISA)) {
// 4gb, no malloc. Explanation in header.
- low_4gb_arena_pool_.reset(new ArenaPool(false, true));
+ low_4gb_arena_pool_.reset(new ArenaPool(/* use_malloc */ false, /* low_4gb */ true));
}
linear_alloc_.reset(CreateLinearAlloc());
@@ -1276,9 +1280,7 @@
// libcore can't because it's the library that implements System.loadLibrary!
{
std::string error_msg;
- if (!java_vm_->LoadNativeLibrary(env, "libjavacore.so", nullptr,
- /* is_shared_namespace */ false,
- nullptr, nullptr, &error_msg)) {
+ if (!java_vm_->LoadNativeLibrary(env, "libjavacore.so", nullptr, nullptr, &error_msg)) {
LOG(FATAL) << "LoadNativeLibrary failed for \"libjavacore.so\": " << error_msg;
}
}
@@ -1287,9 +1289,7 @@
? "libopenjdkd.so"
: "libopenjdk.so";
std::string error_msg;
- if (!java_vm_->LoadNativeLibrary(env, kOpenJdkLibrary, nullptr,
- /* is_shared_namespace */ false,
- nullptr, nullptr, &error_msg)) {
+ if (!java_vm_->LoadNativeLibrary(env, kOpenJdkLibrary, nullptr, nullptr, &error_msg)) {
LOG(FATAL) << "LoadNativeLibrary failed for \"" << kOpenJdkLibrary << "\": " << error_msg;
}
}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 8aac4ce..83e77d2 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -561,6 +561,9 @@
ArenaPool* GetArenaPool() {
return arena_pool_.get();
}
+ ArenaPool* GetJitArenaPool() {
+ return jit_arena_pool_.get();
+ }
const ArenaPool* GetArenaPool() const {
return arena_pool_.get();
}
@@ -669,6 +672,7 @@
gc::Heap* heap_;
+ std::unique_ptr<ArenaPool> jit_arena_pool_;
std::unique_ptr<ArenaPool> arena_pool_;
// Special low 4gb pool for compiler linear alloc. We need ArtFields to be in low 4gb if we are
// compiling using a 32 bit image on a 64 bit compiler in case we resolve things in the image
diff --git a/runtime/stack.cc b/runtime/stack.cc
index b1f1ed6..ee5da8e 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -739,7 +739,7 @@
// Check class linker linear allocs.
mirror::Class* klass = method->GetDeclaringClass();
LinearAlloc* const class_linear_alloc = (klass != nullptr)
- ? ClassLinker::GetAllocatorForClassLoader(klass->GetClassLoader())
+ ? runtime->GetClassLinker()->GetAllocatorForClassLoader(klass->GetClassLoader())
: linear_alloc;
if (!class_linear_alloc->Contains(method)) {
// Check image space.
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index 5a4dfb8..2fba805 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -16,6 +16,11 @@
#include "thread_pool.h"
+#include <pthread.h>
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
#include "base/bit_utils.h"
#include "base/casts.h"
#include "base/logging.h"
@@ -53,6 +58,19 @@
CHECK_PTHREAD_CALL(pthread_join, (pthread_, nullptr), "thread pool worker shutdown");
}
+void ThreadPoolWorker::SetPthreadPriority(int priority) {
+ CHECK_GE(priority, PRIO_MIN);
+ CHECK_LE(priority, PRIO_MAX);
+#if defined(__ANDROID__)
+ int result = setpriority(PRIO_PROCESS, pthread_gettid_np(pthread_), priority);
+ if (result != 0) {
+ PLOG(ERROR) << "Failed to setpriority to :" << priority;
+ }
+#else
+ UNUSED(priority);
+#endif
+}
+
void ThreadPoolWorker::Run() {
Thread* self = Thread::Current();
Task* task = nullptr;
@@ -214,4 +232,10 @@
return tasks_.size();
}
+void ThreadPool::SetPthreadPriority(int priority) {
+ for (ThreadPoolWorker* worker : threads_) {
+ worker->SetPthreadPriority(priority);
+ }
+}
+
} // namespace art
diff --git a/runtime/thread_pool.h b/runtime/thread_pool.h
index 6cd4ad3..b6c6f02 100644
--- a/runtime/thread_pool.h
+++ b/runtime/thread_pool.h
@@ -59,6 +59,9 @@
virtual ~ThreadPoolWorker();
+ // Set the "nice" priorty for this worker.
+ void SetPthreadPriority(int priority);
+
protected:
ThreadPoolWorker(ThreadPool* thread_pool, const std::string& name, size_t stack_size);
static void* Callback(void* arg) REQUIRES(!Locks::mutator_lock_);
@@ -111,6 +114,9 @@
// thread count of the thread pool.
void SetMaxActiveWorkers(size_t threads) REQUIRES(!task_queue_lock_);
+ // Set the "nice" priorty for threads in the pool.
+ void SetPthreadPriority(int priority);
+
protected:
// get a task to run, blocks if there are no tasks left
virtual Task* GetTask(Thread* self) REQUIRES(!task_queue_lock_);
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 99b2296..6b82641 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -389,9 +389,10 @@
bool stop_alloc_counting = false;
Runtime* const runtime = Runtime::Current();
Trace* the_trace = nullptr;
+ Thread* const self = Thread::Current();
pthread_t sampling_pthread = 0U;
{
- MutexLock mu(Thread::Current(), *Locks::trace_lock_);
+ MutexLock mu(self, *Locks::trace_lock_);
if (the_trace_ == nullptr) {
LOG(ERROR) << "Trace stop requested, but no trace currently running";
} else {
@@ -409,6 +410,9 @@
}
{
+ gc::ScopedGCCriticalSection gcs(self,
+ gc::kGcCauseInstrumentation,
+ gc::kCollectorTypeInstrumentation);
ScopedSuspendAll ssa(__FUNCTION__);
if (the_trace != nullptr) {
stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0;
@@ -417,7 +421,7 @@
}
if (the_trace->trace_mode_ == TraceMode::kSampling) {
- MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
+ MutexLock mu(self, *Locks::thread_list_lock_);
runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
} else {
runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 0c6060e..f71ebfe 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -16,6 +16,9 @@
#include "method_verifier-inl.h"
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+#include <cutils/trace.h>
+
#include <iostream>
#include "art_field-inl.h"
@@ -283,6 +286,7 @@
// empty class, probably a marker interface
return kNoFailure;
}
+ ATRACE_BEGIN("VerifyClass");
ClassDataItemIterator it(*dex_file, class_data);
while (it.HasNextStaticField() || it.HasNextInstanceField()) {
it.Next();
@@ -317,6 +321,8 @@
data1.Merge(data2);
+ ATRACE_END();
+
if (data1.kind == kNoFailure) {
return kNoFailure;
} else {
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index cfa8329..d288943 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -385,7 +385,7 @@
ScopedLocalRef<jclass> java_lang_Runtime(env, env->FindClass("java/lang/Runtime"));
java_lang_Runtime_nativeLoad =
CacheMethod(env, java_lang_Runtime.get(), true, "nativeLoad",
- "(Ljava/lang/String;Ljava/lang/ClassLoader;ZLjava/lang/String;Ljava/lang/String;)"
+ "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)"
"Ljava/lang/String;");
}
diff --git a/test/004-ReferenceMap/build b/test/004-ReferenceMap/build
deleted file mode 100644
index 08987b5..0000000
--- a/test/004-ReferenceMap/build
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Stop if something fails.
-set -e
-
-# The test relies on DEX file produced by javac+dx so keep building with them for now
-# (see b/19467889)
-mkdir classes
-${JAVAC} -d classes `find src -name '*.java'`
-${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
- --dump-width=1000 ${DX_FLAGS} classes
-zip $TEST_NAME.jar classes.dex
diff --git a/test/004-ReferenceMap/stack_walk_refmap_jni.cc b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
index 2dbd7e8..2d26fa1 100644
--- a/test/004-ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
@@ -65,19 +65,19 @@
// We eliminate the non-live registers at a return, so only v3 is live.
// Note that it is OK for a compiler to not have a dex map at this dex PC because
// a return is not necessarily a safepoint.
- CHECK_REGS_CONTAIN_REFS(0x13U, false, 3); // v3: y
+ CHECK_REGS_CONTAIN_REFS(0x14U, false, 2); // v2: y
// Note that v0: ex can be eliminated because it's a dead merge of two different exceptions.
CHECK_REGS_CONTAIN_REFS(0x18U, true, 8, 2, 1); // v8: this, v2: y, v1: x (dead v0: ex)
if (!GetCurrentOatQuickMethodHeader()->IsOptimized()) {
- // v8: this, v5: x[1], v2: y, v1: x (dead v0: ex)
- CHECK_REGS_CONTAIN_REFS(0x1aU, true, 8, 5, 2, 1);
- // v8: this, v5: x[1], v2: y, v1: x (dead v0: ex)
- CHECK_REGS_CONTAIN_REFS(0x1dU, true, 8, 5, 2, 1);
- // v5 is removed from the root set because there is a "merge" operation.
- // See 0015: if-nez v2, 001f.
- CHECK_REGS_CONTAIN_REFS(0x1fU, true, 8, 2, 1); // v8: this, v2: y, v1: x (dead v0: ex)
+ // v8: this, v4: x[1], v2: y, v1: x (dead v0: ex)
+ CHECK_REGS_CONTAIN_REFS(0x1aU, true, 8, 4, 2, 1);
+ // v8: this, v4: x[1], v2: y, v1: x (dead v0: ex)
+ CHECK_REGS_CONTAIN_REFS(0x1eU, true, 8, 4, 2, 1);
+ // v4 is removed from the root set because there is a "merge" operation.
+ // See 0016: if-nez v2, 0020.
+ CHECK_REGS_CONTAIN_REFS(0x20U, true, 8, 2, 1); // v8: this, v2: y, v1: x (dead v0: ex)
}
- CHECK_REGS_CONTAIN_REFS(0x21U, true, 8, 2, 1); // v8: this, v2: y, v1: x (dead v0: ex)
+ CHECK_REGS_CONTAIN_REFS(0x22U, true, 8, 2, 1); // v8: this, v2: y, v1: x (dead v0: ex)
if (!GetCurrentOatQuickMethodHeader()->IsOptimized()) {
CHECK_REGS_CONTAIN_REFS(0x27U, true, 8, 4, 2, 1); // v8: this, v4: ex, v2: y, v1: x
@@ -94,124 +94,79 @@
}
};
-// Dex instructions for the function 'f' in ReferenceMap.java
-// Virtual methods -
-// #0 : (in LReferenceMap;)
-// name : 'f'
-// type : '()Ljava/lang/Object;'
-// access : 0x0000 ()
-// code -
-// registers : 9
-// ins : 1
-// outs : 2
-// insns size : 51 16-bit code units
-// |[0001e8] ReferenceMap.f:()Ljava/lang/Object;
-// |0000: const/4 v4, #int 2 // #2
-// |0001: const/4 v7, #int 0 // #0
-// |0002: const/4 v6, #int 1 // #1
+// DEX code
//
-// 0:[Unknown],1:[Unknown],2:[Unknown],3:[Unknown],4:[32-bit Constant: 2],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0003: new-array v1, v4, [Ljava/lang/Object; // type@0007
-// |0005: const/4 v2, #int 0 // #0
-
-// 0:[Unknown],1:[Reference: java.lang.Object[]],2:[Zero],3:[Unknown],4:[32-bit Constant: 2],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0006: new-instance v3, Ljava/lang/Object; // type@0003
-
-// [Unknown],1:[Reference: java.lang.Object[]],2:[Zero],3:[Uninitialized Reference: java.lang.Object],4:[32-bit Constant: 2],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0008: +invoke-object-init/range {}, Ljava/lang/Object;.<init>:()V // method@0005
-// |000b: const/4 v4, #int 2 // #2
-
-// 0:[Unknown],1:[Reference: java.lang.Object[]],2:[Zero],3:[Reference: java.lang.Object],4:[32-bit Constant: 2],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |000c: aput-object v3, v1, v4
-
-// 0:[Unknown],1:[Reference: java.lang.Object[]],2:[Zero],3:[Reference: java.lang.Object],4:[32-bit Constant: 2],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |000e: aput-object v3, v1, v6
-
-// 0:[Unknown],1:[Reference: java.lang.Object[]],2:[Zero],3:[Reference: java.lang.Object],4:[32-bit Constant: 2],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0010: +invoke-virtual-quick {v8, v7}, [000c] // vtable #000c
-
-// 0:[Conflict],1:[Conflict],2:[Conflict],3:[Reference: java.lang.Object],4:[Conflict],5:[Conflict],6:[Conflict],7:[Conflict],8:[Conflict],
-// |0013: return-object v3
-// |0014: move-exception v0
-
-// 0:[Reference: java.lang.Exception],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Conflict],4:[32-bit Constant: 2],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0015: if-nez v2, 001f // +000a
-// |0017: const/4 v4, #int 1 // #1
-
-// 0:[Reference: java.lang.Exception],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Conflict],4:[32-bit Constant: 1],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0018: new-instance v5, Ljava/lang/Object; // type@0003
-
-// 0:[Reference: java.lang.Exception],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Conflict],4:[32-bit Constant: 1],5:[Uninitialized Reference: java.lang.Object],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |001a: +invoke-object-init/range {}, Ljava/lang/Object;.<init>:()V // method@0005
-
-// 0:[Reference: java.lang.Exception],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Conflict],4:[32-bit Constant: 1],5:[Reference: java.lang.Object],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |001d: aput-object v5, v1, v4
-
-// 0:[Reference: java.lang.Exception],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Conflict],4:[32-bit Constant: 2],5:[Conflict],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |001f: aput-object v2, v1, v6
-
-// 0:[Reference: java.lang.Exception],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Conflict],4:[32-bit Constant: 2],5:[Conflict],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0021: +invoke-virtual-quick {v8, v7}, [000c] // vtable #000c
-// |0024: move-object v3, v2
-
-// 0:[Reference: java.lang.Exception],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Reference: java.lang.Object],4:[32-bit Constant: 2],5:[Conflict],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0025: goto 0013 // -0012
-// |0026: move-exception v4
-
-// 0:[Conflict],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Conflict],4:[Reference: java.lang.Throwable],5:[Conflict],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0027: aput-object v2, v1, v6
-
-// 0:[Conflict],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Conflict],4:[Reference: java.lang.Throwable],5:[Conflict],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0029: +invoke-virtual-quick {v8, v7}, [000c] // vtable #000c
-
-// 0:[Conflict],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Conflict],4:[Reference: java.lang.Throwable],5:[Conflict],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |002c: throw v4
-// |002d: move-exception v4
-// |002e: move-object v2, v3
-
-// 0:[Unknown],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Reference: java.lang.Object],4:[Reference: java.lang.Throwable],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |002f: goto 0027 // -0008
-// |0030: move-exception v0
-// |0031: move-object v2, v3
-
-// 0:[Reference: java.lang.Exception],1:[Reference: java.lang.Object[]],2:[Reference: java.lang.Object],3:[Reference: java.lang.Object],4:[32-bit Constant: 2],5:[Unknown],6:[32-bit Constant: 1],7:[Zero],8:[Reference: ReferenceMap],
-// |0032: goto 0015 // -001d
-// catches : 3
-// 0x0006 - 0x000b
-// Ljava/lang/Exception; -> 0x0014
-// <any> -> 0x0026
-// 0x000c - 0x000e
-// Ljava/lang/Exception; -> 0x0030
-// <any> -> 0x002d
-// 0x0018 - 0x001f
-// <any> -> 0x0026
-// positions :
-// 0x0003 line=8
-// 0x0005 line=9
-// 0x0006 line=11
-// 0x000b line=12
-// 0x000e line=18
-// 0x0010 line=19
-// 0x0013 line=21
-// 0x0014 line=13
-// 0x0015 line=14
-// 0x0017 line=15
-// 0x001f line=18
-// 0x0021 line=19
-// 0x0025 line=20
-// 0x0026 line=18
-// 0x0029 line=19
-// 0x002d line=18
-// 0x0030 line=13
-// locals :
-// 0x0006 - 0x000b reg=2 y Ljava/lang/Object;
-// 0x000b - 0x0013 reg=3 y Ljava/lang/Object;
-// 0x0014 - 0x0015 reg=2 y Ljava/lang/Object;
-// 0x0015 - 0x0026 reg=0 ex Ljava/lang/Exception;
-// 0x002d - 0x0032 reg=3 y Ljava/lang/Object;
-// 0x0005 - 0x0033 reg=1 x [Ljava/lang/Object;
-// 0x0032 - 0x0033 reg=2 y Ljava/lang/Object;
-// 0x0000 - 0x0033 reg=8 this LReferenceMap;
+// 0000: const/4 v4, #int 2 // #2
+// 0001: const/4 v7, #int 0 // #0
+// 0002: const/4 v6, #int 1 // #1
+// 0003: new-array v1, v4, [Ljava/lang/Object; // type@0007
+// 0005: const/4 v2, #int 0 // #0
+// 0006: new-instance v3, Ljava/lang/Object; // type@0003
+// 0008: invoke-direct {v3}, Ljava/lang/Object;.<init>:()V // method@0004
+// 000b: const/4 v4, #int 2 // #2
+// 000c: aput-object v3, v1, v4
+// 000e: aput-object v3, v1, v6
+// 0010: invoke-virtual {v8, v7}, LMain;.refmap:(I)I // method@0003
+// 0013: move-object v2, v3
+// 0014: return-object v2
+// 0015: move-exception v0
+// 0016: if-nez v2, 0020 // +000a
+// 0018: new-instance v4, Ljava/lang/Object; // type@0003
+// 001a: invoke-direct {v4}, Ljava/lang/Object;.<init>:()V // method@0004
+// 001d: const/4 v5, #int 1 // #1
+// 001e: aput-object v4, v1, v5
+// 0020: aput-object v2, v1, v6
+// 0022: invoke-virtual {v8, v7}, LMain;.refmap:(I)I // method@0003
+// 0025: goto 0014 // -0011
+// 0026: move-exception v4
+// 0027: aput-object v2, v1, v6
+// 0029: invoke-virtual {v8, v7}, LMain;.refmap:(I)I // method@0003
+// 002c: throw v4
+// 002d: move-exception v4
+// 002e: move-object v2, v3
+// 002f: goto 0027 // -0008
+// 0030: move-exception v0
+// 0031: move-object v2, v3
+// 0032: goto 0016 // -001c
+// catches : 3
+// 0x0006 - 0x000b
+// Ljava/lang/Exception; -> 0x0015
+// <any> -> 0x0026
+// 0x000c - 0x000e
+// Ljava/lang/Exception; -> 0x0030
+// <any> -> 0x002d
+// 0x0018 - 0x0020
+// <any> -> 0x0026
+// positions :
+// 0x0003 line=22
+// 0x0005 line=23
+// 0x0006 line=25
+// 0x000b line=26
+// 0x000e line=32
+// 0x0010 line=33
+// 0x0014 line=35
+// 0x0015 line=27
+// 0x0016 line=28
+// 0x0018 line=29
+// 0x0020 line=32
+// 0x0022 line=33
+// 0x0026 line=31
+// 0x0027 line=32
+// 0x0029 line=33
+// 0x002c line=31
+// 0x0030 line=27
+// locals :
+// 0x0006 - 0x000b reg=2 y Ljava/lang/Object;
+// 0x000b - 0x0014 reg=3 y Ljava/lang/Object;
+// 0x0015 - 0x0016 reg=2 y Ljava/lang/Object;
+// 0x0016 - 0x0026 reg=0 ex Ljava/lang/Exception;
+// 0x002d - 0x002f reg=3 y Ljava/lang/Object;
+// 0x002f - 0x0030 reg=2 y Ljava/lang/Object;
+// 0x0030 - 0x0032 reg=3 y Ljava/lang/Object;
+// 0x0031 - 0x0033 reg=0 ex Ljava/lang/Exception;
+// 0x0005 - 0x0033 reg=1 x [Ljava/lang/Object;
+// 0x0032 - 0x0033 reg=2 y Ljava/lang/Object;
+// 0x0000 - 0x0033 reg=8 this LMain;
extern "C" JNIEXPORT jint JNICALL Java_Main_refmap(JNIEnv*, jobject, jint count) {
// Visitor
diff --git a/test/004-StackWalk/build b/test/004-StackWalk/build
deleted file mode 100644
index 08987b5..0000000
--- a/test/004-StackWalk/build
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Stop if something fails.
-set -e
-
-# The test relies on DEX file produced by javac+dx so keep building with them for now
-# (see b/19467889)
-mkdir classes
-${JAVAC} -d classes `find src -name '*.java'`
-${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
- --dump-width=1000 ${DX_FLAGS} classes
-zip $TEST_NAME.jar classes.dex
diff --git a/test/004-StackWalk/stack_walk_jni.cc b/test/004-StackWalk/stack_walk_jni.cc
index 3a5854b..51bb68f 100644
--- a/test/004-StackWalk/stack_walk_jni.cc
+++ b/test/004-StackWalk/stack_walk_jni.cc
@@ -42,31 +42,31 @@
// Given the method name and the number of times the method has been called,
// we know the Dex registers with live reference values. Assert that what we
// find is what is expected.
- if (m_name == "f") {
+ if (m_name == "$noinline$f") {
if (gJava_StackWalk_refmap_calls == 1) {
CHECK_EQ(1U, GetDexPc());
- CHECK_REGS(4);
+ CHECK_REGS(1); // v1: this
} else {
CHECK_EQ(gJava_StackWalk_refmap_calls, 2);
CHECK_EQ(5U, GetDexPc());
- CHECK_REGS(4);
+ CHECK_REGS(1); // v1: this
}
} else if (m_name == "g") {
if (gJava_StackWalk_refmap_calls == 1) {
- CHECK_EQ(0xcU, GetDexPc());
- CHECK_REGS(0, 2); // Note that v1 is not in the minimal root set
+ CHECK_EQ(0xdU, GetDexPc());
+ CHECK_REGS(0, 2); // v2: this (Note that v1 is not in the minimal root set)
} else {
CHECK_EQ(gJava_StackWalk_refmap_calls, 2);
- CHECK_EQ(0xcU, GetDexPc());
+ CHECK_EQ(0xdU, GetDexPc());
CHECK_REGS(0, 2);
}
} else if (m_name == "shlemiel") {
if (gJava_StackWalk_refmap_calls == 1) {
- CHECK_EQ(0x380U, GetDexPc());
+ CHECK_EQ(0x393U, GetDexPc());
CHECK_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25);
} else {
CHECK_EQ(gJava_StackWalk_refmap_calls, 2);
- CHECK_EQ(0x380U, GetDexPc());
+ CHECK_EQ(0x393U, GetDexPc());
CHECK_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25);
}
}
diff --git a/test/011-array-copy/src/Main.java b/test/011-array-copy/src/Main.java
index 96e1dbf..d9b61e7 100644
--- a/test/011-array-copy/src/Main.java
+++ b/test/011-array-copy/src/Main.java
@@ -69,6 +69,11 @@
array[i] = (long) i;
}
}
+ static void initCharArray(char[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = (char) i;
+ }
+ }
/*
* Perform an array copy operation on primitive arrays with different
@@ -79,16 +84,19 @@
short[] shortArray = new short[ARRAY_SIZE];
int[] intArray = new int[ARRAY_SIZE];
long[] longArray = new long[ARRAY_SIZE];
+ char[] charArray = new char[ARRAY_SIZE];
initByteArray(byteArray);
initShortArray(shortArray);
initIntArray(intArray);
initLongArray(longArray);
+ initCharArray(charArray);
System.arraycopy(byteArray, srcPos, byteArray, dstPos, length);
System.arraycopy(shortArray, srcPos, shortArray, dstPos, length);
System.arraycopy(intArray, srcPos, intArray, dstPos, length);
System.arraycopy(longArray, srcPos, longArray, dstPos, length);
+ System.arraycopy(charArray, srcPos, charArray, dstPos, length);
for (int i = 0; i < ARRAY_SIZE; i++) {
if (intArray[i] != byteArray[i]) {
@@ -103,6 +111,10 @@
System.out.println("mismatch int vs long at " + i + " : " +
Arrays.toString(longArray));
break;
+ } else if (intArray[i] != charArray[i]) {
+ System.out.println("mismatch int vs char at " + i + " : " +
+ Arrays.toString(charArray));
+ break;
}
}
diff --git a/test/048-reflect-v8/build b/test/048-reflect-v8/build
index 4ea1838..3552b5c 100644
--- a/test/048-reflect-v8/build
+++ b/test/048-reflect-v8/build
@@ -20,9 +20,5 @@
# Hard-wired use of experimental jack.
# TODO: fix this temporary work-around for lambdas, see b/19467889
export USE_JACK=true
-export JACK_SERVER=false
-export JACK_REPOSITORY="${ANDROID_BUILD_TOP}/prebuilts/sdk/tools/jacks"
-# e.g. /foo/bar/jack-3.10.ALPHA.jar -> 3.10.ALPHA
-export JACK_VERSION="$(find "$JACK_REPOSITORY" -name '*ALPHA*' | sed 's/.*jack-//g' | sed 's/[.]jar//g')"
./default-build "$@" --experimental default-methods
diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java
index 93a9005..9aaed9d 100644
--- a/test/082-inline-execute/src/Main.java
+++ b/test/082-inline-execute/src/Main.java
@@ -40,6 +40,10 @@
test_Math_rint();
test_Math_round_D();
test_Math_round_F();
+ test_Math_isNaN_D();
+ test_Math_isNaN_F();
+ test_Math_isInfinite_D();
+ test_Math_isInfinite_F();
test_Short_reverseBytes();
test_Integer_reverseBytes();
test_Long_reverseBytes();
@@ -836,6 +840,106 @@
Assert.assertEquals(Math.round(Float.NEGATIVE_INFINITY), Integer.MIN_VALUE);
}
+ public static void test_Math_isNaN_D() {
+ // Quiet NaN.
+ Assert.assertTrue(Double.isNaN(Double.longBitsToDouble(0x7FF4000000000000l)));
+ Assert.assertTrue(Double.isNaN(Double.longBitsToDouble(0xFFF4000000000000l)));
+ // Signaling NaN.
+ Assert.assertTrue(Double.isNaN(Double.longBitsToDouble(0x7FF8000000000000l)));
+ Assert.assertTrue(Double.isNaN(Double.longBitsToDouble(0xFFF8000000000000l)));
+ // Distinct from +/- infinity.
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x7FF0000000000000l)));
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0xFFF0000000000000l)));
+ // Distinct from normal numbers.
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x7FE0000000000000l)));
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0xFFE0000000000000l)));
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x0010000000000000l)));
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x8010000000000000l)));
+ // Distinct from +/- zero.
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x0000000000000000l)));
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x8000000000000000l)));
+ // Distinct from subnormal numbers.
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x0008000000000000l)));
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x8008000000000000l)));
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x0000000000000001l)));
+ Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x8000000000000001l)));
+ }
+
+ public static void test_Math_isNaN_F() {
+ // Quiet NaN.
+ Assert.assertTrue(Float.isNaN(Float.intBitsToFloat(0x7FA00000)));
+ Assert.assertTrue(Float.isNaN(Float.intBitsToFloat(0xFFA00000)));
+ // Signaling NaN.
+ Assert.assertTrue(Float.isNaN(Float.intBitsToFloat(0x7FC00000)));
+ Assert.assertTrue(Float.isNaN(Float.intBitsToFloat(0xFFC00000)));
+ // Distinct from +/- infinity.
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x7F800000)));
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0xFF800000)));
+ // Distinct from normal numbers.
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x7F000000)));
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0xFF000000)));
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x00800000)));
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x80800000)));
+ // Distinct from +/- zero.
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x00000000)));
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x80000000)));
+ // Distinct from subnormal numbers.
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x00400000)));
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x80400000)));
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x00000001)));
+ Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x80000001)));
+ }
+
+ public static void test_Math_isInfinite_D() {
+ // Distinct from Quiet NaN.
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x7FF4000000000000l)));
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0xFFF4000000000000l)));
+ // Distinct from Signaling NaN.
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x7FF8000000000000l)));
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0xFFF8000000000000l)));
+ // +/- infinity.
+ Assert.assertTrue(Double.isInfinite(Double.longBitsToDouble(0x7FF0000000000000l)));
+ Assert.assertTrue(Double.isInfinite(Double.longBitsToDouble(0xFFF0000000000000l)));
+ // Distinct from normal numbers.
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x7FE0000000000000l)));
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0xFFE0000000000000l)));
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x0010000000000000l)));
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x8010000000000000l)));
+ // Distinct from +/- zero.
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x0000000000000000l)));
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x8000000000000000l)));
+ // Distinct from subnormal numbers.
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x0008000000000000l)));
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x8008000000000000l)));
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x0000000000000001l)));
+ Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x8000000000000001l)));
+ }
+
+ public static void test_Math_isInfinite_F() {
+ // Distinct from Quiet NaN.
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x7FA00000)));
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0xFFA00000)));
+ // Distinct from Signaling NaN.
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x7FC00000)));
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0xFFC00000)));
+ // +/- infinity.
+ Assert.assertTrue(Float.isInfinite(Float.intBitsToFloat(0x7F800000)));
+ Assert.assertTrue(Float.isInfinite(Float.intBitsToFloat(0xFF800000)));
+ // Distinct from normal numbers.
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x7F000000)));
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0xFF000000)));
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x00800000)));
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80800000)));
+ // Distinct from +/- zero.
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x00000000)));
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80000000)));
+ // Distinct from subnormal numbers.
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x00400000)));
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80400000)));
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x00000001)));
+ Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80000001)));
+ }
+
public static void test_StrictMath_abs_I() {
StrictMath.abs(-1);
Assert.assertEquals(StrictMath.abs(0), 0);
diff --git a/test/089-many-methods/build b/test/089-many-methods/build
index ff77c60..58144e1 100644
--- a/test/089-many-methods/build
+++ b/test/089-many-methods/build
@@ -43,8 +43,4 @@
printf("}\n") > fileName;
}'
-# The test relies on the error message produced by dx, not jack, so keep building with dx for now
-# (b/19467889).
-mkdir classes
-${JAVAC} -d classes `find src -name '*.java'`
-${DX} -JXmx1024m --dex --no-optimize classes
+./default-build
diff --git a/test/089-many-methods/expected.txt b/test/089-many-methods/expected.txt
index b74e0ee..bfee8b3 100644
--- a/test/089-many-methods/expected.txt
+++ b/test/089-many-methods/expected.txt
@@ -1,6 +1,2 @@
-
-trouble writing output: Too many field references: 131000; max is 65536.
-You may try using --multi-dex option.
-References by package:
-131000 default
-build exit status: 2
+ERROR: Dex writing phase: classes.dex has too many IDs. Try using multi-dex
+build exit status: 4
diff --git a/test/137-cfi/expected.txt b/test/137-cfi/expected.txt
index 6a5618e..8db7853 100644
--- a/test/137-cfi/expected.txt
+++ b/test/137-cfi/expected.txt
@@ -1 +1,2 @@
JNI_OnLoad called
+JNI_OnLoad called
diff --git a/test/137-cfi/run b/test/137-cfi/run
index 8ec98c1..ebc729b 100755
--- a/test/137-cfi/run
+++ b/test/137-cfi/run
@@ -16,9 +16,10 @@
# Test with full DWARF debugging information.
# Check full signatures of methods.
-${RUN} "$@" -Xcompiler-option --generate-debug-info --args --full-signatures
+${RUN} "$@" -Xcompiler-option --generate-debug-info \
+ --args --full-signatures --args --test-local --args --test-remote
# Test with minimal compressed debugging information.
# Check only method names (parameters are omitted to save space).
-# Temporarily disable due to bug 27172087 (leak/race in libunwind).
-# ${RUN} "$@" -Xcompiler-option --generate-mini-debug-info
+# Check only remote unwinding since decompression is disabled in local unwinds (b/27391690).
+${RUN} "$@" -Xcompiler-option --generate-mini-debug-info --args --test-remote
diff --git a/test/137-cfi/src/Main.java b/test/137-cfi/src/Main.java
index d60a4eb..5cfe33d 100644
--- a/test/137-cfi/src/Main.java
+++ b/test/137-cfi/src/Main.java
@@ -21,43 +21,48 @@
import java.util.Comparator;
public class Main implements Comparator<Main> {
- // Whether to test local unwinding. Libunwind uses linker info to find executables. As we do
- // not dlopen at the moment, this doesn't work, so keep it off for now.
- public final static boolean TEST_LOCAL_UNWINDING = true;
+ // Whether to test local unwinding.
+ private boolean testLocal;
- // Unwinding another process, modelling debuggerd. This doesn't use the linker, so should work
- // no matter whether we're using dlopen or not.
- public final static boolean TEST_REMOTE_UNWINDING = true;
+ // Unwinding another process, modelling debuggerd.
+ private boolean testRemote;
+ // We fork ourself to create the secondary process for remote unwinding.
private boolean secondary;
- private boolean full_signatures;
+ // Expect the symbols to contain full method signatures including parameters.
+ private boolean fullSignatures;
private boolean passed;
- public Main(boolean secondary, boolean full_signatures) {
- this.secondary = secondary;
- this.full_signatures = full_signatures;
+ public Main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+ for (String arg : args) {
+ if (arg.equals("--test-local")) {
+ testLocal = true;
+ }
+ if (arg.equals("--test-remote")) {
+ testRemote = true;
+ }
+ if (arg.equals("--secondary")) {
+ secondary = true;
+ }
+ if (arg.equals("--full-signatures")) {
+ fullSignatures = true;
+ }
+ }
+ if (!testLocal && !testRemote) {
+ System.out.println("No test selected.");
+ }
}
public static void main(String[] args) throws Exception {
- System.loadLibrary(args[0]);
- boolean secondary = false;
- boolean full_signatures = false;
- for (String arg : args) {
- if (arg.equals("--secondary")) {
- secondary = true;
- }
- if (arg.equals("--full-signatures")) {
- full_signatures = true;
- }
- }
- new Main(secondary, full_signatures).run();
+ new Main(args).run();
}
private void run() {
if (secondary) {
- if (!TEST_REMOTE_UNWINDING) {
+ if (!testRemote) {
throw new RuntimeException("Should not be running secondary!");
}
runSecondary();
@@ -73,11 +78,11 @@
private void runPrimary() {
// First do the in-process unwinding.
- if (TEST_LOCAL_UNWINDING && !foo()) {
+ if (testLocal && !foo()) {
System.out.println("Unwinding self failed.");
}
- if (!TEST_REMOTE_UNWINDING) {
+ if (!testRemote) {
// Skip the remote step.
return;
}
@@ -105,7 +110,7 @@
throw new RuntimeException(e);
}
- if (!unwindOtherProcess(full_signatures, pid)) {
+ if (!unwindOtherProcess(fullSignatures, pid)) {
System.out.println("Unwinding other process failed.");
}
} finally {
@@ -163,7 +168,7 @@
if (b) {
return sleep(2, b, 1.0);
} else {
- return unwindInProcess(full_signatures, 1, b);
+ return unwindInProcess(fullSignatures, 1, b);
}
}
@@ -171,6 +176,6 @@
public native boolean sleep(int i, boolean b, double dummy);
- public native boolean unwindInProcess(boolean full_signatures, int i, boolean b);
- public native boolean unwindOtherProcess(boolean full_signatures, int pid);
+ public native boolean unwindInProcess(boolean fullSignatures, int i, boolean b);
+ public native boolean unwindOtherProcess(boolean fullSignatures, int pid);
}
diff --git a/test/138-duplicate-classes-check2/build b/test/138-duplicate-classes-check2/build
index abcbbb8..d346251 100755
--- a/test/138-duplicate-classes-check2/build
+++ b/test/138-duplicate-classes-check2/build
@@ -24,9 +24,17 @@
${JAVAC} -d classes-ex `find src-ex -name '*.java'`
rm classes-ex/A.class
-if [ ${NEED_DEX} = "true" ]; then
+if [ ${USE_JACK} = "true" ]; then
+ jar cf classes.jill.jar -C classes .
+ ${JACK} --import classes.jill.jar --output-dex .
+ zip ${TEST_NAME}.jar classes.dex
+
+ jar cf classes-ex.jill.jar -C classes-ex .
+ ${JACK} --import classes-ex.jill.jar --output-dex .
+ zip ${TEST_NAME}-ex.jar classes.dex
+elif [ ${NEED_DEX} = "true" ]; then
${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
- zip $TEST_NAME.jar classes.dex
+ zip ${TEST_NAME}.jar classes.dex
${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
zip ${TEST_NAME}-ex.jar classes.dex
fi
diff --git a/test/145-alloc-tracking-stress/expected.txt b/test/145-alloc-tracking-stress/expected.txt
new file mode 100644
index 0000000..134d8d0
--- /dev/null
+++ b/test/145-alloc-tracking-stress/expected.txt
@@ -0,0 +1 @@
+Finishing
diff --git a/test/145-alloc-tracking-stress/info.txt b/test/145-alloc-tracking-stress/info.txt
new file mode 100644
index 0000000..443062d
--- /dev/null
+++ b/test/145-alloc-tracking-stress/info.txt
@@ -0,0 +1 @@
+Regression test for b/18661622
diff --git a/test/145-alloc-tracking-stress/src/Main.java b/test/145-alloc-tracking-stress/src/Main.java
new file mode 100644
index 0000000..752fdd9
--- /dev/null
+++ b/test/145-alloc-tracking-stress/src/Main.java
@@ -0,0 +1,74 @@
+/*
+
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+public class Main implements Runnable {
+ static final int numberOfThreads = 4;
+ static final int totalOperations = 1000;
+ static Method enableAllocTrackingMethod;
+ static Object holder;
+ static volatile boolean trackingThreadDone = false;
+ int threadIndex;
+
+ Main(int index) {
+ threadIndex = index;
+ }
+
+ public static void main(String[] args) throws Exception {
+ Class klass = Class.forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal");
+ if (klass == null) {
+ throw new AssertionError("Couldn't find DdmVmInternal class");
+ }
+ enableAllocTrackingMethod = klass.getDeclaredMethod("enableRecentAllocations",
+ Boolean.TYPE);
+ if (enableAllocTrackingMethod == null) {
+ throw new AssertionError("Couldn't find enableRecentAllocations method");
+ }
+
+ final Thread[] threads = new Thread[numberOfThreads];
+ for (int t = 0; t < threads.length; t++) {
+ threads[t] = new Thread(new Main(t));
+ threads[t].start();
+ }
+ for (Thread t : threads) {
+ t.join();
+ }
+ System.out.println("Finishing");
+ }
+
+ public void run() {
+ if (threadIndex == 0) {
+ for (int i = 0; i < totalOperations; ++i) {
+ try {
+ enableAllocTrackingMethod.invoke(null, true);
+ holder = new Object();
+ enableAllocTrackingMethod.invoke(null, false);
+ } catch (Exception e) {
+ System.out.println(e);
+ return;
+ }
+ }
+ trackingThreadDone = true;
+ } else {
+ while (!trackingThreadDone) {
+ holder = new Object();
+ }
+ }
+ }
+}
diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java
index 93fe397..b7712a7 100644
--- a/test/442-checker-constant-folding/src/Main.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -51,6 +51,21 @@
}
}
+ private static int $inline$int(int x) {
+ return x;
+ }
+
+ private static long $inline$long(long x) {
+ return x;
+ }
+
+ private static float $inline$float(float x) {
+ return x;
+ }
+
+ private static double $inline$double(double x) {
+ return x;
+ }
// Wrappers around methods located in file TestCmp.smali.
@@ -194,121 +209,119 @@
return y;
}
-
/**
* Exercise constant folding on addition.
*/
- /// CHECK-START: int Main.IntAddition1() constant_folding (before)
+ /// CHECK-START: int Main.IntAddition1() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: <<Add:i\d+>> Add [<<Const1>>,<<Const2>>]
/// CHECK-DAG: Return [<<Add>>]
- /// CHECK-START: int Main.IntAddition1() constant_folding (after)
+ /// CHECK-START: int Main.IntAddition1() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: Return [<<Const3>>]
- /// CHECK-START: int Main.IntAddition1() constant_folding (after)
+ /// CHECK-START: int Main.IntAddition1() constant_folding_after_inlining (after)
/// CHECK-NOT: Add
public static int IntAddition1() {
int a, b, c;
- a = 1;
- b = 2;
+ a = $inline$int(1);
+ b = $inline$int(2);
c = a + b;
return c;
}
- /// CHECK-START: int Main.IntAddition2() constant_folding (before)
+ /// CHECK-START: int Main.IntAddition2() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
/// CHECK-DAG: <<Const6:i\d+>> IntConstant 6
- /// CHECK-DAG: <<Const11:i\d+>> IntConstant 11
/// CHECK-DAG: <<Add1:i\d+>> Add [<<Const1>>,<<Const2>>]
- /// CHECK-DAG: Add [<<Const5>>,<<Const6>>]
- /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Const11>>]
+ /// CHECK-DAG: <<Add2:i\d+>> Add [<<Const5>>,<<Const6>>]
+ /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Add2>>]
/// CHECK-DAG: Return [<<Add3>>]
- /// CHECK-START: int Main.IntAddition2() constant_folding (after)
+ /// CHECK-START: int Main.IntAddition2() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const14:i\d+>> IntConstant 14
/// CHECK-DAG: Return [<<Const14>>]
- /// CHECK-START: int Main.IntAddition2() constant_folding (after)
+ /// CHECK-START: int Main.IntAddition2() constant_folding_after_inlining (after)
/// CHECK-NOT: Add
public static int IntAddition2() {
int a, b, c;
- a = 1;
- b = 2;
+ a = $inline$int(1);
+ b = $inline$int(2);
a += b;
- b = 5;
- c = 6;
+ b = $inline$int(5);
+ c = $inline$int(6);
b += c;
c = a + b;
return c;
}
- /// CHECK-START: long Main.LongAddition() constant_folding (before)
+ /// CHECK-START: long Main.LongAddition() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const1:j\d+>> LongConstant 1
/// CHECK-DAG: <<Const2:j\d+>> LongConstant 2
/// CHECK-DAG: <<Add:j\d+>> Add [<<Const1>>,<<Const2>>]
/// CHECK-DAG: Return [<<Add>>]
- /// CHECK-START: long Main.LongAddition() constant_folding (after)
+ /// CHECK-START: long Main.LongAddition() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const3:j\d+>> LongConstant 3
/// CHECK-DAG: Return [<<Const3>>]
- /// CHECK-START: long Main.LongAddition() constant_folding (after)
+ /// CHECK-START: long Main.LongAddition() constant_folding_after_inlining (after)
/// CHECK-NOT: Add
public static long LongAddition() {
long a, b, c;
- a = 1L;
- b = 2L;
+ a = $inline$long(1L);
+ b = $inline$long(2L);
c = a + b;
return c;
}
- /// CHECK-START: float Main.FloatAddition() constant_folding (before)
+ /// CHECK-START: float Main.FloatAddition() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const1:f\d+>> FloatConstant 1
/// CHECK-DAG: <<Const2:f\d+>> FloatConstant 2
/// CHECK-DAG: <<Add:f\d+>> Add [<<Const1>>,<<Const2>>]
/// CHECK-DAG: Return [<<Add>>]
- /// CHECK-START: float Main.FloatAddition() constant_folding (after)
+ /// CHECK-START: float Main.FloatAddition() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const3:f\d+>> FloatConstant 3
/// CHECK-DAG: Return [<<Const3>>]
- /// CHECK-START: float Main.FloatAddition() constant_folding (after)
+ /// CHECK-START: float Main.FloatAddition() constant_folding_after_inlining (after)
/// CHECK-NOT: Add
public static float FloatAddition() {
float a, b, c;
- a = 1F;
- b = 2F;
+ a = $inline$float(1F);
+ b = $inline$float(2F);
c = a + b;
return c;
}
- /// CHECK-START: double Main.DoubleAddition() constant_folding (before)
+ /// CHECK-START: double Main.DoubleAddition() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const1:d\d+>> DoubleConstant 1
/// CHECK-DAG: <<Const2:d\d+>> DoubleConstant 2
/// CHECK-DAG: <<Add:d\d+>> Add [<<Const1>>,<<Const2>>]
/// CHECK-DAG: Return [<<Add>>]
- /// CHECK-START: double Main.DoubleAddition() constant_folding (after)
+ /// CHECK-START: double Main.DoubleAddition() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const3:d\d+>> DoubleConstant 3
/// CHECK-DAG: Return [<<Const3>>]
- /// CHECK-START: double Main.DoubleAddition() constant_folding (after)
+ /// CHECK-START: double Main.DoubleAddition() constant_folding_after_inlining (after)
/// CHECK-NOT: Add
public static double DoubleAddition() {
double a, b, c;
- a = 1D;
- b = 2D;
+ a = $inline$double(1D);
+ b = $inline$double(2D);
c = a + b;
return c;
}
@@ -318,86 +331,86 @@
* Exercise constant folding on subtraction.
*/
- /// CHECK-START: int Main.IntSubtraction() constant_folding (before)
+ /// CHECK-START: int Main.IntSubtraction() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const6:i\d+>> IntConstant 6
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const6>>,<<Const2>>]
/// CHECK-DAG: Return [<<Sub>>]
- /// CHECK-START: int Main.IntSubtraction() constant_folding (after)
+ /// CHECK-START: int Main.IntSubtraction() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const4:i\d+>> IntConstant 4
/// CHECK-DAG: Return [<<Const4>>]
- /// CHECK-START: int Main.IntSubtraction() constant_folding (after)
+ /// CHECK-START: int Main.IntSubtraction() constant_folding_after_inlining (after)
/// CHECK-NOT: Sub
public static int IntSubtraction() {
int a, b, c;
- a = 6;
- b = 2;
+ a = $inline$int(6);
+ b = $inline$int(2);
c = a - b;
return c;
}
- /// CHECK-START: long Main.LongSubtraction() constant_folding (before)
+ /// CHECK-START: long Main.LongSubtraction() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const6:j\d+>> LongConstant 6
/// CHECK-DAG: <<Const2:j\d+>> LongConstant 2
/// CHECK-DAG: <<Sub:j\d+>> Sub [<<Const6>>,<<Const2>>]
/// CHECK-DAG: Return [<<Sub>>]
- /// CHECK-START: long Main.LongSubtraction() constant_folding (after)
+ /// CHECK-START: long Main.LongSubtraction() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const4:j\d+>> LongConstant 4
/// CHECK-DAG: Return [<<Const4>>]
- /// CHECK-START: long Main.LongSubtraction() constant_folding (after)
+ /// CHECK-START: long Main.LongSubtraction() constant_folding_after_inlining (after)
/// CHECK-NOT: Sub
public static long LongSubtraction() {
long a, b, c;
- a = 6L;
- b = 2L;
+ a = $inline$long(6L);
+ b = $inline$long(2L);
c = a - b;
return c;
}
- /// CHECK-START: float Main.FloatSubtraction() constant_folding (before)
+ /// CHECK-START: float Main.FloatSubtraction() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const6:f\d+>> FloatConstant 6
/// CHECK-DAG: <<Const2:f\d+>> FloatConstant 2
/// CHECK-DAG: <<Sub:f\d+>> Sub [<<Const6>>,<<Const2>>]
/// CHECK-DAG: Return [<<Sub>>]
- /// CHECK-START: float Main.FloatSubtraction() constant_folding (after)
+ /// CHECK-START: float Main.FloatSubtraction() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const4:f\d+>> FloatConstant 4
/// CHECK-DAG: Return [<<Const4>>]
- /// CHECK-START: float Main.FloatSubtraction() constant_folding (after)
+ /// CHECK-START: float Main.FloatSubtraction() constant_folding_after_inlining (after)
/// CHECK-NOT: Sub
public static float FloatSubtraction() {
float a, b, c;
- a = 6F;
- b = 2F;
+ a = $inline$float(6F);
+ b = $inline$float(2F);
c = a - b;
return c;
}
- /// CHECK-START: double Main.DoubleSubtraction() constant_folding (before)
+ /// CHECK-START: double Main.DoubleSubtraction() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const6:d\d+>> DoubleConstant 6
/// CHECK-DAG: <<Const2:d\d+>> DoubleConstant 2
/// CHECK-DAG: <<Sub:d\d+>> Sub [<<Const6>>,<<Const2>>]
/// CHECK-DAG: Return [<<Sub>>]
- /// CHECK-START: double Main.DoubleSubtraction() constant_folding (after)
+ /// CHECK-START: double Main.DoubleSubtraction() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const4:d\d+>> DoubleConstant 4
/// CHECK-DAG: Return [<<Const4>>]
- /// CHECK-START: double Main.DoubleSubtraction() constant_folding (after)
+ /// CHECK-START: double Main.DoubleSubtraction() constant_folding_after_inlining (after)
/// CHECK-NOT: Sub
public static double DoubleSubtraction() {
double a, b, c;
- a = 6D;
- b = 2D;
+ a = $inline$double(6D);
+ b = $inline$double(2D);
c = a - b;
return c;
}
@@ -407,86 +420,86 @@
* Exercise constant folding on multiplication.
*/
- /// CHECK-START: int Main.IntMultiplication() constant_folding (before)
+ /// CHECK-START: int Main.IntMultiplication() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const7:i\d+>> IntConstant 7
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<Mul:i\d+>> Mul [<<Const7>>,<<Const3>>]
/// CHECK-DAG: Return [<<Mul>>]
- /// CHECK-START: int Main.IntMultiplication() constant_folding (after)
+ /// CHECK-START: int Main.IntMultiplication() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const21:i\d+>> IntConstant 21
/// CHECK-DAG: Return [<<Const21>>]
- /// CHECK-START: int Main.IntMultiplication() constant_folding (after)
+ /// CHECK-START: int Main.IntMultiplication() constant_folding_after_inlining (after)
/// CHECK-NOT: Mul
public static int IntMultiplication() {
int a, b, c;
- a = 7;
- b = 3;
+ a = $inline$int(7);
+ b = $inline$int(3);
c = a * b;
return c;
}
- /// CHECK-START: long Main.LongMultiplication() constant_folding (before)
+ /// CHECK-START: long Main.LongMultiplication() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const7:j\d+>> LongConstant 7
/// CHECK-DAG: <<Const3:j\d+>> LongConstant 3
/// CHECK-DAG: <<Mul:j\d+>> Mul [<<Const7>>,<<Const3>>]
/// CHECK-DAG: Return [<<Mul>>]
- /// CHECK-START: long Main.LongMultiplication() constant_folding (after)
+ /// CHECK-START: long Main.LongMultiplication() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const21:j\d+>> LongConstant 21
/// CHECK-DAG: Return [<<Const21>>]
- /// CHECK-START: long Main.LongMultiplication() constant_folding (after)
+ /// CHECK-START: long Main.LongMultiplication() constant_folding_after_inlining (after)
/// CHECK-NOT: Mul
public static long LongMultiplication() {
long a, b, c;
- a = 7L;
- b = 3L;
+ a = $inline$long(7L);
+ b = $inline$long(3L);
c = a * b;
return c;
}
- /// CHECK-START: float Main.FloatMultiplication() constant_folding (before)
+ /// CHECK-START: float Main.FloatMultiplication() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const7:f\d+>> FloatConstant 7
/// CHECK-DAG: <<Const3:f\d+>> FloatConstant 3
/// CHECK-DAG: <<Mul:f\d+>> Mul [<<Const7>>,<<Const3>>]
/// CHECK-DAG: Return [<<Mul>>]
- /// CHECK-START: float Main.FloatMultiplication() constant_folding (after)
+ /// CHECK-START: float Main.FloatMultiplication() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const21:f\d+>> FloatConstant 21
/// CHECK-DAG: Return [<<Const21>>]
- /// CHECK-START: float Main.FloatMultiplication() constant_folding (after)
+ /// CHECK-START: float Main.FloatMultiplication() constant_folding_after_inlining (after)
/// CHECK-NOT: Mul
public static float FloatMultiplication() {
float a, b, c;
- a = 7F;
- b = 3F;
+ a = $inline$float(7F);
+ b = $inline$float(3F);
c = a * b;
return c;
}
- /// CHECK-START: double Main.DoubleMultiplication() constant_folding (before)
+ /// CHECK-START: double Main.DoubleMultiplication() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const7:d\d+>> DoubleConstant 7
/// CHECK-DAG: <<Const3:d\d+>> DoubleConstant 3
/// CHECK-DAG: <<Mul:d\d+>> Mul [<<Const7>>,<<Const3>>]
/// CHECK-DAG: Return [<<Mul>>]
- /// CHECK-START: double Main.DoubleMultiplication() constant_folding (after)
+ /// CHECK-START: double Main.DoubleMultiplication() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const21:d\d+>> DoubleConstant 21
/// CHECK-DAG: Return [<<Const21>>]
- /// CHECK-START: double Main.DoubleMultiplication() constant_folding (after)
+ /// CHECK-START: double Main.DoubleMultiplication() constant_folding_after_inlining (after)
/// CHECK-NOT: Mul
public static double DoubleMultiplication() {
double a, b, c;
- a = 7D;
- b = 3D;
+ a = $inline$double(7D);
+ b = $inline$double(3D);
c = a * b;
return c;
}
@@ -496,90 +509,90 @@
* Exercise constant folding on division.
*/
- /// CHECK-START: int Main.IntDivision() constant_folding (before)
+ /// CHECK-START: int Main.IntDivision() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const8:i\d+>> IntConstant 8
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<Div0Chk:i\d+>> DivZeroCheck [<<Const3>>]
/// CHECK-DAG: <<Div:i\d+>> Div [<<Const8>>,<<Div0Chk>>]
/// CHECK-DAG: Return [<<Div>>]
- /// CHECK-START: int Main.IntDivision() constant_folding (after)
+ /// CHECK-START: int Main.IntDivision() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: Return [<<Const2>>]
- /// CHECK-START: int Main.IntDivision() constant_folding (after)
+ /// CHECK-START: int Main.IntDivision() constant_folding_after_inlining (after)
/// CHECK-NOT: DivZeroCheck
/// CHECK-NOT: Div
public static int IntDivision() {
int a, b, c;
- a = 8;
- b = 3;
+ a = $inline$int(8);
+ b = $inline$int(3);
c = a / b;
return c;
}
- /// CHECK-START: long Main.LongDivision() constant_folding (before)
+ /// CHECK-START: long Main.LongDivision() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const8:j\d+>> LongConstant 8
/// CHECK-DAG: <<Const3:j\d+>> LongConstant 3
/// CHECK-DAG: <<Div0Chk:j\d+>> DivZeroCheck [<<Const3>>]
/// CHECK-DAG: <<Div:j\d+>> Div [<<Const8>>,<<Div0Chk>>]
/// CHECK-DAG: Return [<<Div>>]
- /// CHECK-START: long Main.LongDivision() constant_folding (after)
+ /// CHECK-START: long Main.LongDivision() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const2:j\d+>> LongConstant 2
/// CHECK-DAG: Return [<<Const2>>]
- /// CHECK-START: long Main.LongDivision() constant_folding (after)
+ /// CHECK-START: long Main.LongDivision() constant_folding_after_inlining (after)
/// CHECK-NOT: DivZeroCheck
/// CHECK-NOT: Div
public static long LongDivision() {
long a, b, c;
- a = 8L;
- b = 3L;
+ a = $inline$long(8L);
+ b = $inline$long(3L);
c = a / b;
return c;
}
- /// CHECK-START: float Main.FloatDivision() constant_folding (before)
+ /// CHECK-START: float Main.FloatDivision() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const8:f\d+>> FloatConstant 8
/// CHECK-DAG: <<Const2P5:f\d+>> FloatConstant 2.5
/// CHECK-DAG: <<Div:f\d+>> Div [<<Const8>>,<<Const2P5>>]
/// CHECK-DAG: Return [<<Div>>]
- /// CHECK-START: float Main.FloatDivision() constant_folding (after)
+ /// CHECK-START: float Main.FloatDivision() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const3P2:f\d+>> FloatConstant 3.2
/// CHECK-DAG: Return [<<Const3P2>>]
- /// CHECK-START: float Main.FloatDivision() constant_folding (after)
+ /// CHECK-START: float Main.FloatDivision() constant_folding_after_inlining (after)
/// CHECK-NOT: Div
public static float FloatDivision() {
float a, b, c;
- a = 8F;
- b = 2.5F;
+ a = $inline$float(8F);
+ b = $inline$float(2.5F);
c = a / b;
return c;
}
- /// CHECK-START: double Main.DoubleDivision() constant_folding (before)
+ /// CHECK-START: double Main.DoubleDivision() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const8:d\d+>> DoubleConstant 8
/// CHECK-DAG: <<Const2P5:d\d+>> DoubleConstant 2.5
/// CHECK-DAG: <<Div:d\d+>> Div [<<Const8>>,<<Const2P5>>]
/// CHECK-DAG: Return [<<Div>>]
- /// CHECK-START: double Main.DoubleDivision() constant_folding (after)
+ /// CHECK-START: double Main.DoubleDivision() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const3P2:d\d+>> DoubleConstant 3.2
/// CHECK-DAG: Return [<<Const3P2>>]
- /// CHECK-START: double Main.DoubleDivision() constant_folding (after)
+ /// CHECK-START: double Main.DoubleDivision() constant_folding_after_inlining (after)
/// CHECK-NOT: Div
public static double DoubleDivision() {
double a, b, c;
- a = 8D;
- b = 2.5D;
+ a = $inline$double(8D);
+ b = $inline$double(2.5D);
c = a / b;
return c;
}
@@ -589,90 +602,90 @@
* Exercise constant folding on remainder.
*/
- /// CHECK-START: int Main.IntRemainder() constant_folding (before)
+ /// CHECK-START: int Main.IntRemainder() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const8:i\d+>> IntConstant 8
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<Div0Chk:i\d+>> DivZeroCheck [<<Const3>>]
/// CHECK-DAG: <<Rem:i\d+>> Rem [<<Const8>>,<<Div0Chk>>]
/// CHECK-DAG: Return [<<Rem>>]
- /// CHECK-START: int Main.IntRemainder() constant_folding (after)
+ /// CHECK-START: int Main.IntRemainder() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: Return [<<Const2>>]
- /// CHECK-START: int Main.IntRemainder() constant_folding (after)
+ /// CHECK-START: int Main.IntRemainder() constant_folding_after_inlining (after)
/// CHECK-NOT: DivZeroCheck
/// CHECK-NOT: Rem
public static int IntRemainder() {
int a, b, c;
- a = 8;
- b = 3;
+ a = $inline$int(8);
+ b = $inline$int(3);
c = a % b;
return c;
}
- /// CHECK-START: long Main.LongRemainder() constant_folding (before)
+ /// CHECK-START: long Main.LongRemainder() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const8:j\d+>> LongConstant 8
/// CHECK-DAG: <<Const3:j\d+>> LongConstant 3
/// CHECK-DAG: <<Div0Chk:j\d+>> DivZeroCheck [<<Const3>>]
/// CHECK-DAG: <<Rem:j\d+>> Rem [<<Const8>>,<<Div0Chk>>]
/// CHECK-DAG: Return [<<Rem>>]
- /// CHECK-START: long Main.LongRemainder() constant_folding (after)
+ /// CHECK-START: long Main.LongRemainder() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const2:j\d+>> LongConstant 2
/// CHECK-DAG: Return [<<Const2>>]
- /// CHECK-START: long Main.LongRemainder() constant_folding (after)
+ /// CHECK-START: long Main.LongRemainder() constant_folding_after_inlining (after)
/// CHECK-NOT: DivZeroCheck
/// CHECK-NOT: Rem
public static long LongRemainder() {
long a, b, c;
- a = 8L;
- b = 3L;
+ a = $inline$long(8L);
+ b = $inline$long(3L);
c = a % b;
return c;
}
- /// CHECK-START: float Main.FloatRemainder() constant_folding (before)
+ /// CHECK-START: float Main.FloatRemainder() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const8:f\d+>> FloatConstant 8
/// CHECK-DAG: <<Const2P5:f\d+>> FloatConstant 2.5
/// CHECK-DAG: <<Rem:f\d+>> Rem [<<Const8>>,<<Const2P5>>]
/// CHECK-DAG: Return [<<Rem>>]
- /// CHECK-START: float Main.FloatRemainder() constant_folding (after)
+ /// CHECK-START: float Main.FloatRemainder() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const0P5:f\d+>> FloatConstant 0.5
/// CHECK-DAG: Return [<<Const0P5>>]
- /// CHECK-START: float Main.FloatRemainder() constant_folding (after)
+ /// CHECK-START: float Main.FloatRemainder() constant_folding_after_inlining (after)
/// CHECK-NOT: Rem
public static float FloatRemainder() {
float a, b, c;
- a = 8F;
- b = 2.5F;
+ a = $inline$float(8F);
+ b = $inline$float(2.5F);
c = a % b;
return c;
}
- /// CHECK-START: double Main.DoubleRemainder() constant_folding (before)
+ /// CHECK-START: double Main.DoubleRemainder() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const8:d\d+>> DoubleConstant 8
/// CHECK-DAG: <<Const2P5:d\d+>> DoubleConstant 2.5
/// CHECK-DAG: <<Rem:d\d+>> Rem [<<Const8>>,<<Const2P5>>]
/// CHECK-DAG: Return [<<Rem>>]
- /// CHECK-START: double Main.DoubleRemainder() constant_folding (after)
+ /// CHECK-START: double Main.DoubleRemainder() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const0P5:d\d+>> DoubleConstant 0.5
/// CHECK-DAG: Return [<<Const0P5>>]
- /// CHECK-START: double Main.DoubleRemainder() constant_folding (after)
+ /// CHECK-START: double Main.DoubleRemainder() constant_folding_after_inlining (after)
/// CHECK-NOT: Rem
public static double DoubleRemainder() {
double a, b, c;
- a = 8D;
- b = 2.5D;
+ a = $inline$double(8D);
+ b = $inline$double(2.5D);
c = a % b;
return c;
}
@@ -682,42 +695,42 @@
* Exercise constant folding on left shift.
*/
- /// CHECK-START: int Main.ShlIntLong() constant_folding (before)
+ /// CHECK-START: int Main.ShlIntLong() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: <<Const2L:j\d+>> LongConstant 2
/// CHECK-DAG: <<TypeConv:i\d+>> TypeConversion [<<Const2L>>]
/// CHECK-DAG: <<Shl:i\d+>> Shl [<<Const1>>,<<TypeConv>>]
/// CHECK-DAG: Return [<<Shl>>]
- /// CHECK-START: int Main.ShlIntLong() constant_folding (after)
+ /// CHECK-START: int Main.ShlIntLong() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const4:i\d+>> IntConstant 4
/// CHECK-DAG: Return [<<Const4>>]
- /// CHECK-START: int Main.ShlIntLong() constant_folding (after)
+ /// CHECK-START: int Main.ShlIntLong() constant_folding_after_inlining (after)
/// CHECK-NOT: Shl
public static int ShlIntLong() {
- int lhs = 1;
- long rhs = 2;
+ int lhs = $inline$int(1);
+ long rhs = $inline$long(2L);
return lhs << rhs;
}
- /// CHECK-START: long Main.ShlLongInt() constant_folding (before)
+ /// CHECK-START: long Main.ShlLongInt() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const3L:j\d+>> LongConstant 3
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: <<Shl:j\d+>> Shl [<<Const3L>>,<<Const2>>]
/// CHECK-DAG: Return [<<Shl>>]
- /// CHECK-START: long Main.ShlLongInt() constant_folding (after)
+ /// CHECK-START: long Main.ShlLongInt() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const12L:j\d+>> LongConstant 12
/// CHECK-DAG: Return [<<Const12L>>]
- /// CHECK-START: long Main.ShlLongInt() constant_folding (after)
+ /// CHECK-START: long Main.ShlLongInt() constant_folding_after_inlining (after)
/// CHECK-NOT: Shl
public static long ShlLongInt() {
- long lhs = 3;
- int rhs = 2;
+ long lhs = $inline$long(3L);
+ int rhs = $inline$int(2);
return lhs << rhs;
}
@@ -726,42 +739,42 @@
* Exercise constant folding on right shift.
*/
- /// CHECK-START: int Main.ShrIntLong() constant_folding (before)
+ /// CHECK-START: int Main.ShrIntLong() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const7:i\d+>> IntConstant 7
/// CHECK-DAG: <<Const2L:j\d+>> LongConstant 2
/// CHECK-DAG: <<TypeConv:i\d+>> TypeConversion [<<Const2L>>]
/// CHECK-DAG: <<Shr:i\d+>> Shr [<<Const7>>,<<TypeConv>>]
/// CHECK-DAG: Return [<<Shr>>]
- /// CHECK-START: int Main.ShrIntLong() constant_folding (after)
+ /// CHECK-START: int Main.ShrIntLong() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: Return [<<Const1>>]
- /// CHECK-START: int Main.ShrIntLong() constant_folding (after)
+ /// CHECK-START: int Main.ShrIntLong() constant_folding_after_inlining (after)
/// CHECK-NOT: Shr
public static int ShrIntLong() {
- int lhs = 7;
- long rhs = 2;
+ int lhs = $inline$int(7);
+ long rhs = $inline$long(2L);
return lhs >> rhs;
}
- /// CHECK-START: long Main.ShrLongInt() constant_folding (before)
+ /// CHECK-START: long Main.ShrLongInt() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const9L:j\d+>> LongConstant 9
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: <<Shr:j\d+>> Shr [<<Const9L>>,<<Const2>>]
/// CHECK-DAG: Return [<<Shr>>]
- /// CHECK-START: long Main.ShrLongInt() constant_folding (after)
+ /// CHECK-START: long Main.ShrLongInt() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const2L:j\d+>> LongConstant 2
/// CHECK-DAG: Return [<<Const2L>>]
- /// CHECK-START: long Main.ShrLongInt() constant_folding (after)
+ /// CHECK-START: long Main.ShrLongInt() constant_folding_after_inlining (after)
/// CHECK-NOT: Shr
public static long ShrLongInt() {
- long lhs = 9;
- int rhs = 2;
+ long lhs = $inline$long(9);
+ int rhs = $inline$int(2);
return lhs >> rhs;
}
@@ -770,42 +783,42 @@
* Exercise constant folding on unsigned right shift.
*/
- /// CHECK-START: int Main.UShrIntLong() constant_folding (before)
+ /// CHECK-START: int Main.UShrIntLong() constant_folding_after_inlining (before)
/// CHECK-DAG: <<ConstM7:i\d+>> IntConstant -7
/// CHECK-DAG: <<Const2L:j\d+>> LongConstant 2
/// CHECK-DAG: <<TypeConv:i\d+>> TypeConversion [<<Const2L>>]
/// CHECK-DAG: <<UShr:i\d+>> UShr [<<ConstM7>>,<<TypeConv>>]
/// CHECK-DAG: Return [<<UShr>>]
- /// CHECK-START: int Main.UShrIntLong() constant_folding (after)
+ /// CHECK-START: int Main.UShrIntLong() constant_folding_after_inlining (after)
/// CHECK-DAG: <<ConstRes:i\d+>> IntConstant 1073741822
/// CHECK-DAG: Return [<<ConstRes>>]
- /// CHECK-START: int Main.UShrIntLong() constant_folding (after)
+ /// CHECK-START: int Main.UShrIntLong() constant_folding_after_inlining (after)
/// CHECK-NOT: UShr
public static int UShrIntLong() {
- int lhs = -7;
- long rhs = 2;
+ int lhs = $inline$int(-7);
+ long rhs = $inline$long(2L);
return lhs >>> rhs;
}
- /// CHECK-START: long Main.UShrLongInt() constant_folding (before)
+ /// CHECK-START: long Main.UShrLongInt() constant_folding_after_inlining (before)
/// CHECK-DAG: <<ConstM9L:j\d+>> LongConstant -9
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: <<UShr:j\d+>> UShr [<<ConstM9L>>,<<Const2>>]
/// CHECK-DAG: Return [<<UShr>>]
- /// CHECK-START: long Main.UShrLongInt() constant_folding (after)
+ /// CHECK-START: long Main.UShrLongInt() constant_folding_after_inlining (after)
/// CHECK-DAG: <<ConstRes:j\d+>> LongConstant 4611686018427387901
/// CHECK-DAG: Return [<<ConstRes>>]
- /// CHECK-START: long Main.UShrLongInt() constant_folding (after)
+ /// CHECK-START: long Main.UShrLongInt() constant_folding_after_inlining (after)
/// CHECK-NOT: UShr
public static long UShrLongInt() {
- long lhs = -9;
- int rhs = 2;
+ long lhs = $inline$long(-9);
+ int rhs = $inline$int(2);
return lhs >>> rhs;
}
@@ -814,43 +827,43 @@
* Exercise constant folding on logical and.
*/
- /// CHECK-START: long Main.AndIntLong() constant_folding (before)
+ /// CHECK-START: long Main.AndIntLong() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
/// CHECK-DAG: <<Const3L:j\d+>> LongConstant 3
/// CHECK-DAG: <<TypeConv:j\d+>> TypeConversion [<<Const10>>]
/// CHECK-DAG: <<And:j\d+>> And [<<TypeConv>>,<<Const3L>>]
/// CHECK-DAG: Return [<<And>>]
- /// CHECK-START: long Main.AndIntLong() constant_folding (after)
+ /// CHECK-START: long Main.AndIntLong() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const2:j\d+>> LongConstant 2
/// CHECK-DAG: Return [<<Const2>>]
- /// CHECK-START: long Main.AndIntLong() constant_folding (after)
+ /// CHECK-START: long Main.AndIntLong() constant_folding_after_inlining (after)
/// CHECK-NOT: And
public static long AndIntLong() {
- int lhs = 10;
- long rhs = 3;
+ int lhs = $inline$int(10);
+ long rhs = $inline$long(3L);
return lhs & rhs;
}
- /// CHECK-START: long Main.AndLongInt() constant_folding (before)
+ /// CHECK-START: long Main.AndLongInt() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const10L:j\d+>> LongConstant 10
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<TypeConv:j\d+>> TypeConversion [<<Const3>>]
/// CHECK-DAG: <<And:j\d+>> And [<<TypeConv>>,<<Const10L>>]
/// CHECK-DAG: Return [<<And>>]
- /// CHECK-START: long Main.AndLongInt() constant_folding (after)
+ /// CHECK-START: long Main.AndLongInt() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const2:j\d+>> LongConstant 2
/// CHECK-DAG: Return [<<Const2>>]
- /// CHECK-START: long Main.AndLongInt() constant_folding (after)
+ /// CHECK-START: long Main.AndLongInt() constant_folding_after_inlining (after)
/// CHECK-NOT: And
public static long AndLongInt() {
- long lhs = 10;
- int rhs = 3;
+ long lhs = $inline$long(10L);
+ int rhs = $inline$int(3);
return lhs & rhs;
}
@@ -859,43 +872,43 @@
* Exercise constant folding on logical or.
*/
- /// CHECK-START: long Main.OrIntLong() constant_folding (before)
+ /// CHECK-START: long Main.OrIntLong() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
/// CHECK-DAG: <<Const3L:j\d+>> LongConstant 3
/// CHECK-DAG: <<TypeConv:j\d+>> TypeConversion [<<Const10>>]
/// CHECK-DAG: <<Or:j\d+>> Or [<<TypeConv>>,<<Const3L>>]
/// CHECK-DAG: Return [<<Or>>]
- /// CHECK-START: long Main.OrIntLong() constant_folding (after)
+ /// CHECK-START: long Main.OrIntLong() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const11:j\d+>> LongConstant 11
/// CHECK-DAG: Return [<<Const11>>]
- /// CHECK-START: long Main.OrIntLong() constant_folding (after)
+ /// CHECK-START: long Main.OrIntLong() constant_folding_after_inlining (after)
/// CHECK-NOT: Or
public static long OrIntLong() {
- int lhs = 10;
- long rhs = 3;
+ int lhs = $inline$int(10);
+ long rhs = $inline$long(3L);
return lhs | rhs;
}
- /// CHECK-START: long Main.OrLongInt() constant_folding (before)
+ /// CHECK-START: long Main.OrLongInt() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const10L:j\d+>> LongConstant 10
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<TypeConv:j\d+>> TypeConversion [<<Const3>>]
/// CHECK-DAG: <<Or:j\d+>> Or [<<TypeConv>>,<<Const10L>>]
/// CHECK-DAG: Return [<<Or>>]
- /// CHECK-START: long Main.OrLongInt() constant_folding (after)
+ /// CHECK-START: long Main.OrLongInt() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const11:j\d+>> LongConstant 11
/// CHECK-DAG: Return [<<Const11>>]
- /// CHECK-START: long Main.OrLongInt() constant_folding (after)
+ /// CHECK-START: long Main.OrLongInt() constant_folding_after_inlining (after)
/// CHECK-NOT: Or
public static long OrLongInt() {
- long lhs = 10;
- int rhs = 3;
+ long lhs = $inline$long(10L);
+ int rhs = $inline$int(3);
return lhs | rhs;
}
@@ -904,43 +917,43 @@
* Exercise constant folding on logical exclusive or.
*/
- /// CHECK-START: long Main.XorIntLong() constant_folding (before)
+ /// CHECK-START: long Main.XorIntLong() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
/// CHECK-DAG: <<Const3L:j\d+>> LongConstant 3
/// CHECK-DAG: <<TypeConv:j\d+>> TypeConversion [<<Const10>>]
/// CHECK-DAG: <<Xor:j\d+>> Xor [<<TypeConv>>,<<Const3L>>]
/// CHECK-DAG: Return [<<Xor>>]
- /// CHECK-START: long Main.XorIntLong() constant_folding (after)
+ /// CHECK-START: long Main.XorIntLong() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const9:j\d+>> LongConstant 9
/// CHECK-DAG: Return [<<Const9>>]
- /// CHECK-START: long Main.XorIntLong() constant_folding (after)
+ /// CHECK-START: long Main.XorIntLong() constant_folding_after_inlining (after)
/// CHECK-NOT: Xor
public static long XorIntLong() {
- int lhs = 10;
- long rhs = 3;
+ int lhs = $inline$int(10);
+ long rhs = $inline$long(3L);
return lhs ^ rhs;
}
- /// CHECK-START: long Main.XorLongInt() constant_folding (before)
+ /// CHECK-START: long Main.XorLongInt() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const10L:j\d+>> LongConstant 10
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<TypeConv:j\d+>> TypeConversion [<<Const3>>]
/// CHECK-DAG: <<Xor:j\d+>> Xor [<<TypeConv>>,<<Const10L>>]
/// CHECK-DAG: Return [<<Xor>>]
- /// CHECK-START: long Main.XorLongInt() constant_folding (after)
+ /// CHECK-START: long Main.XorLongInt() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const9:j\d+>> LongConstant 9
/// CHECK-DAG: Return [<<Const9>>]
- /// CHECK-START: long Main.XorLongInt() constant_folding (after)
+ /// CHECK-START: long Main.XorLongInt() constant_folding_after_inlining (after)
/// CHECK-NOT: Xor
public static long XorLongInt() {
- long lhs = 10;
- int rhs = 3;
+ long lhs = $inline$long(10L);
+ int rhs = $inline$int(3);
return lhs ^ rhs;
}
@@ -949,23 +962,23 @@
* Exercise constant folding on constant (static) condition.
*/
- /// CHECK-START: int Main.StaticCondition() constant_folding (before)
+ /// CHECK-START: int Main.StaticCondition() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const7:i\d+>> IntConstant 7
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: <<Cond:z\d+>> GreaterThanOrEqual [<<Const7>>,<<Const2>>]
- /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Cond>>]
- /// CHECK-START: int Main.StaticCondition() constant_folding (after)
+ /// CHECK-START: int Main.StaticCondition() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: If [<<Const1>>]
+ /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Const1>>]
- /// CHECK-START: int Main.StaticCondition() constant_folding (after)
+ /// CHECK-START: int Main.StaticCondition() constant_folding_after_inlining (after)
/// CHECK-NOT: GreaterThanOrEqual
public static int StaticCondition() {
int a, b, c;
- a = 7;
- b = 2;
+ a = $inline$int(7);
+ b = $inline$int(2);
if (a < b)
c = a + b;
else
@@ -1010,28 +1023,30 @@
* (forward) post-order traversal of the the dominator tree.
*/
- /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (before)
+ /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding_after_inlining (before)
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
/// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
/// CHECK-DAG: <<Add:i\d+>> Add [<<Const5>>,<<Const2>>]
/// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const5>>,<<Const2>>]
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Add>>,<<Sub>>]
+ /// CHECK-DAG: <<Phi:i\d+>> Select [<<Sub>>,<<Add>>,<<Cond>>]
/// CHECK-DAG: Return [<<Phi>>]
- /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after)
+ /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding_after_inlining (after)
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<Const7:i\d+>> IntConstant 7
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const7>>,<<Const3>>]
+ /// CHECK-DAG: <<Phi:i\d+>> Select [<<Const3>>,<<Const7>>,<<Cond>>]
/// CHECK-DAG: Return [<<Phi>>]
- /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after)
+ /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding_after_inlining (after)
/// CHECK-NOT: Add
/// CHECK-NOT: Sub
public static int JumpsAndConditionals(boolean cond) {
int a, b, c;
- a = 5;
- b = 2;
+ a = $inline$int(5);
+ b = $inline$int(2);
if (cond)
c = a + b;
else
@@ -1310,204 +1325,204 @@
* Exercise constant folding on type conversions.
*/
- /// CHECK-START: int Main.ReturnInt33() constant_folding (before)
+ /// CHECK-START: int Main.ReturnInt33() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const33:j\d+>> LongConstant 33
/// CHECK-DAG: <<Convert:i\d+>> TypeConversion [<<Const33>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: int Main.ReturnInt33() constant_folding (after)
+ /// CHECK-START: int Main.ReturnInt33() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const33:i\d+>> IntConstant 33
/// CHECK-DAG: Return [<<Const33>>]
- /// CHECK-START: int Main.ReturnInt33() constant_folding (after)
+ /// CHECK-START: int Main.ReturnInt33() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static int ReturnInt33() {
- long imm = 33L;
+ long imm = $inline$long(33L);
return (int) imm;
}
- /// CHECK-START: int Main.ReturnIntMax() constant_folding (before)
+ /// CHECK-START: int Main.ReturnIntMax() constant_folding_after_inlining (before)
/// CHECK-DAG: <<ConstMax:f\d+>> FloatConstant 1e+34
/// CHECK-DAG: <<Convert:i\d+>> TypeConversion [<<ConstMax>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: int Main.ReturnIntMax() constant_folding (after)
+ /// CHECK-START: int Main.ReturnIntMax() constant_folding_after_inlining (after)
/// CHECK-DAG: <<ConstMax:i\d+>> IntConstant 2147483647
/// CHECK-DAG: Return [<<ConstMax>>]
- /// CHECK-START: int Main.ReturnIntMax() constant_folding (after)
+ /// CHECK-START: int Main.ReturnIntMax() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static int ReturnIntMax() {
- float imm = 1.0e34f;
+ float imm = $inline$float(1.0e34f);
return (int) imm;
}
- /// CHECK-START: int Main.ReturnInt0() constant_folding (before)
+ /// CHECK-START: int Main.ReturnInt0() constant_folding_after_inlining (before)
/// CHECK-DAG: <<ConstNaN:d\d+>> DoubleConstant nan
/// CHECK-DAG: <<Convert:i\d+>> TypeConversion [<<ConstNaN>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: int Main.ReturnInt0() constant_folding (after)
+ /// CHECK-START: int Main.ReturnInt0() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
/// CHECK-DAG: Return [<<Const0>>]
- /// CHECK-START: int Main.ReturnInt0() constant_folding (after)
+ /// CHECK-START: int Main.ReturnInt0() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static int ReturnInt0() {
- double imm = Double.NaN;
+ double imm = $inline$double(Double.NaN);
return (int) imm;
}
- /// CHECK-START: long Main.ReturnLong33() constant_folding (before)
+ /// CHECK-START: long Main.ReturnLong33() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const33:i\d+>> IntConstant 33
/// CHECK-DAG: <<Convert:j\d+>> TypeConversion [<<Const33>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: long Main.ReturnLong33() constant_folding (after)
+ /// CHECK-START: long Main.ReturnLong33() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const33:j\d+>> LongConstant 33
/// CHECK-DAG: Return [<<Const33>>]
- /// CHECK-START: long Main.ReturnLong33() constant_folding (after)
+ /// CHECK-START: long Main.ReturnLong33() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static long ReturnLong33() {
- int imm = 33;
+ int imm = $inline$int(33);
return (long) imm;
}
- /// CHECK-START: long Main.ReturnLong34() constant_folding (before)
+ /// CHECK-START: long Main.ReturnLong34() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const34:f\d+>> FloatConstant 34
/// CHECK-DAG: <<Convert:j\d+>> TypeConversion [<<Const34>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: long Main.ReturnLong34() constant_folding (after)
+ /// CHECK-START: long Main.ReturnLong34() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const34:j\d+>> LongConstant 34
/// CHECK-DAG: Return [<<Const34>>]
- /// CHECK-START: long Main.ReturnLong34() constant_folding (after)
+ /// CHECK-START: long Main.ReturnLong34() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static long ReturnLong34() {
- float imm = 34.0f;
+ float imm = $inline$float(34.0f);
return (long) imm;
}
- /// CHECK-START: long Main.ReturnLong0() constant_folding (before)
+ /// CHECK-START: long Main.ReturnLong0() constant_folding_after_inlining (before)
/// CHECK-DAG: <<ConstNaN:d\d+>> DoubleConstant nan
/// CHECK-DAG: <<Convert:j\d+>> TypeConversion [<<ConstNaN>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: long Main.ReturnLong0() constant_folding (after)
+ /// CHECK-START: long Main.ReturnLong0() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const0:j\d+>> LongConstant 0
/// CHECK-DAG: Return [<<Const0>>]
- /// CHECK-START: long Main.ReturnLong0() constant_folding (after)
+ /// CHECK-START: long Main.ReturnLong0() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static long ReturnLong0() {
- double imm = -Double.NaN;
+ double imm = $inline$double(-Double.NaN);
return (long) imm;
}
- /// CHECK-START: float Main.ReturnFloat33() constant_folding (before)
+ /// CHECK-START: float Main.ReturnFloat33() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const33:i\d+>> IntConstant 33
/// CHECK-DAG: <<Convert:f\d+>> TypeConversion [<<Const33>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: float Main.ReturnFloat33() constant_folding (after)
+ /// CHECK-START: float Main.ReturnFloat33() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const33:f\d+>> FloatConstant 33
/// CHECK-DAG: Return [<<Const33>>]
- /// CHECK-START: float Main.ReturnFloat33() constant_folding (after)
+ /// CHECK-START: float Main.ReturnFloat33() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static float ReturnFloat33() {
- int imm = 33;
+ int imm = $inline$int(33);
return (float) imm;
}
- /// CHECK-START: float Main.ReturnFloat34() constant_folding (before)
+ /// CHECK-START: float Main.ReturnFloat34() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const34:j\d+>> LongConstant 34
/// CHECK-DAG: <<Convert:f\d+>> TypeConversion [<<Const34>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: float Main.ReturnFloat34() constant_folding (after)
+ /// CHECK-START: float Main.ReturnFloat34() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const34:f\d+>> FloatConstant 34
/// CHECK-DAG: Return [<<Const34>>]
- /// CHECK-START: float Main.ReturnFloat34() constant_folding (after)
+ /// CHECK-START: float Main.ReturnFloat34() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static float ReturnFloat34() {
- long imm = 34L;
+ long imm = $inline$long(34L);
return (float) imm;
}
- /// CHECK-START: float Main.ReturnFloat99P25() constant_folding (before)
+ /// CHECK-START: float Main.ReturnFloat99P25() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const:d\d+>> DoubleConstant 99.25
/// CHECK-DAG: <<Convert:f\d+>> TypeConversion [<<Const>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: float Main.ReturnFloat99P25() constant_folding (after)
+ /// CHECK-START: float Main.ReturnFloat99P25() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const:f\d+>> FloatConstant 99.25
/// CHECK-DAG: Return [<<Const>>]
- /// CHECK-START: float Main.ReturnFloat99P25() constant_folding (after)
+ /// CHECK-START: float Main.ReturnFloat99P25() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static float ReturnFloat99P25() {
- double imm = 99.25;
+ double imm = $inline$double(99.25);
return (float) imm;
}
- /// CHECK-START: double Main.ReturnDouble33() constant_folding (before)
+ /// CHECK-START: double Main.ReturnDouble33() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const33:i\d+>> IntConstant 33
/// CHECK-DAG: <<Convert:d\d+>> TypeConversion [<<Const33>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: double Main.ReturnDouble33() constant_folding (after)
+ /// CHECK-START: double Main.ReturnDouble33() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const33:d\d+>> DoubleConstant 33
/// CHECK-DAG: Return [<<Const33>>]
public static double ReturnDouble33() {
- int imm = 33;
+ int imm = $inline$int(33);
return (double) imm;
}
- /// CHECK-START: double Main.ReturnDouble34() constant_folding (before)
+ /// CHECK-START: double Main.ReturnDouble34() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const34:j\d+>> LongConstant 34
/// CHECK-DAG: <<Convert:d\d+>> TypeConversion [<<Const34>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: double Main.ReturnDouble34() constant_folding (after)
+ /// CHECK-START: double Main.ReturnDouble34() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const34:d\d+>> DoubleConstant 34
/// CHECK-DAG: Return [<<Const34>>]
- /// CHECK-START: double Main.ReturnDouble34() constant_folding (after)
+ /// CHECK-START: double Main.ReturnDouble34() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static double ReturnDouble34() {
- long imm = 34L;
+ long imm = $inline$long(34L);
return (double) imm;
}
- /// CHECK-START: double Main.ReturnDouble99P25() constant_folding (before)
+ /// CHECK-START: double Main.ReturnDouble99P25() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Const:f\d+>> FloatConstant 99.25
/// CHECK-DAG: <<Convert:d\d+>> TypeConversion [<<Const>>]
/// CHECK-DAG: Return [<<Convert>>]
- /// CHECK-START: double Main.ReturnDouble99P25() constant_folding (after)
+ /// CHECK-START: double Main.ReturnDouble99P25() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const:d\d+>> DoubleConstant 99.25
/// CHECK-DAG: Return [<<Const>>]
- /// CHECK-START: double Main.ReturnDouble99P25() constant_folding (after)
+ /// CHECK-START: double Main.ReturnDouble99P25() constant_folding_after_inlining (after)
/// CHECK-NOT: TypeConversion
public static double ReturnDouble99P25() {
- float imm = 99.25f;
+ float imm = $inline$float(99.25f);
return (double) imm;
}
diff --git a/test/450-checker-types/smali/SmaliTests.smali b/test/450-checker-types/smali/SmaliTests.smali
new file mode 100644
index 0000000..6a3122e
--- /dev/null
+++ b/test/450-checker-types/smali/SmaliTests.smali
@@ -0,0 +1,120 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LSmaliTests;
+.super Ljava/lang/Object;
+
+## CHECK-START: void SmaliTests.testInstanceOf_EQ0_NotInlined(java.lang.Object) builder (after)
+## CHECK-DAG: <<Cst0:i\d+>> IntConstant 0
+## CHECK-DAG: <<IOf:z\d+>> InstanceOf
+## CHECK-DAG: Equal [<<IOf>>,<<Cst0>>]
+
+## CHECK-START: void SmaliTests.testInstanceOf_EQ0_NotInlined(java.lang.Object) instruction_simplifier (before)
+## CHECK: CheckCast
+
+## CHECK-START: void SmaliTests.testInstanceOf_EQ0_NotInlined(java.lang.Object) instruction_simplifier (after)
+## CHECK-NOT: CheckCast
+
+.method public static testInstanceOf_EQ0_NotInlined(Ljava/lang/Object;)V
+ .registers 3
+
+ const v0, 0x0
+ instance-of v1, p0, LSubclassC;
+ if-eq v1, v0, :return
+
+ check-cast p0, LSubclassC;
+ invoke-virtual {p0}, LSubclassC;->$noinline$g()V
+
+ :return
+ return-void
+
+.end method
+
+## CHECK-START: void SmaliTests.testInstanceOf_EQ1_NotInlined(java.lang.Object) builder (after)
+## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
+## CHECK-DAG: <<IOf:z\d+>> InstanceOf
+## CHECK-DAG: Equal [<<IOf>>,<<Cst1>>]
+
+## CHECK-START: void SmaliTests.testInstanceOf_EQ1_NotInlined(java.lang.Object) instruction_simplifier (before)
+## CHECK: CheckCast
+
+## CHECK-START: void SmaliTests.testInstanceOf_EQ1_NotInlined(java.lang.Object) instruction_simplifier (after)
+## CHECK-NOT: CheckCast
+
+.method public static testInstanceOf_EQ1_NotInlined(Ljava/lang/Object;)V
+ .registers 3
+
+ const v0, 0x1
+ instance-of v1, p0, LSubclassC;
+ if-eq v1, v0, :invoke
+ return-void
+
+ :invoke
+ check-cast p0, LSubclassC;
+ invoke-virtual {p0}, LSubclassC;->$noinline$g()V
+ return-void
+
+.end method
+
+## CHECK-START: void SmaliTests.testInstanceOf_NE0_NotInlined(java.lang.Object) builder (after)
+## CHECK-DAG: <<Cst0:i\d+>> IntConstant 0
+## CHECK-DAG: <<IOf:z\d+>> InstanceOf
+## CHECK-DAG: NotEqual [<<IOf>>,<<Cst0>>]
+
+## CHECK-START: void SmaliTests.testInstanceOf_NE0_NotInlined(java.lang.Object) instruction_simplifier (before)
+## CHECK: CheckCast
+
+## CHECK-START: void SmaliTests.testInstanceOf_NE0_NotInlined(java.lang.Object) instruction_simplifier (after)
+## CHECK-NOT: CheckCast
+
+.method public static testInstanceOf_NE0_NotInlined(Ljava/lang/Object;)V
+ .registers 3
+
+ const v0, 0x0
+ instance-of v1, p0, LSubclassC;
+ if-ne v1, v0, :invoke
+ return-void
+
+ :invoke
+ check-cast p0, LSubclassC;
+ invoke-virtual {p0}, LSubclassC;->$noinline$g()V
+ return-void
+
+.end method
+
+## CHECK-START: void SmaliTests.testInstanceOf_NE1_NotInlined(java.lang.Object) builder (after)
+## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
+## CHECK-DAG: <<IOf:z\d+>> InstanceOf
+## CHECK-DAG: NotEqual [<<IOf>>,<<Cst1>>]
+
+## CHECK-START: void SmaliTests.testInstanceOf_NE1_NotInlined(java.lang.Object) instruction_simplifier (before)
+## CHECK: CheckCast
+
+## CHECK-START: void SmaliTests.testInstanceOf_NE1_NotInlined(java.lang.Object) instruction_simplifier (after)
+## CHECK-NOT: CheckCast
+
+.method public static testInstanceOf_NE1_NotInlined(Ljava/lang/Object;)V
+ .registers 3
+
+ const v0, 0x1
+ instance-of v1, p0, LSubclassC;
+ if-ne v1, v0, :return
+
+ check-cast p0, LSubclassC;
+ invoke-virtual {p0}, LSubclassC;->$noinline$g()V
+
+ :return
+ return-void
+
+.end method
diff --git a/test/450-checker-types/src/Main.java b/test/450-checker-types/src/Main.java
index 027a9d9..08b6cec 100644
--- a/test/450-checker-types/src/Main.java
+++ b/test/450-checker-types/src/Main.java
@@ -205,58 +205,6 @@
public static boolean $inline$InstanceofSubclassB(Object o) { return o instanceof SubclassB; }
public static boolean $inline$InstanceofSubclassC(Object o) { return o instanceof SubclassC; }
- /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) builder (after)
- /// CHECK-DAG: <<Cst0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<IOf1:z\d+>> InstanceOf
- /// CHECK-DAG: NotEqual [<<IOf1>>,<<Cst1>>]
- /// CHECK-DAG: <<IOf2:z\d+>> InstanceOf
- /// CHECK-DAG: Equal [<<IOf2>>,<<Cst0>>]
-
- /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (before)
- /// CHECK: CheckCast
- /// CHECK: CheckCast
- /// CHECK-NOT: CheckCast
-
- /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (after)
- /// CHECK-NOT: CheckCast
- public void testInstanceOf_NotInlined(Object o) {
- if ((o instanceof SubclassC) == true) {
- ((SubclassC)o).$noinline$g();
- }
- if ((o instanceof SubclassB) != false) {
- ((SubclassB)o).$noinline$g();
- }
- }
-
- /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) builder (after)
- /// CHECK-DAG: <<Cst0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<IOf1:z\d+>> InstanceOf
- /// CHECK-DAG: Equal [<<IOf1>>,<<Cst1>>]
- /// CHECK-DAG: <<IOf2:z\d+>> InstanceOf
- /// CHECK-DAG: NotEqual [<<IOf2>>,<<Cst0>>]
-
- /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (before)
- /// CHECK: CheckCast
- /// CHECK: CheckCast
- /// CHECK-NOT: CheckCast
-
- /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (after)
- /// CHECK-NOT: CheckCast
- public void testNotInstanceOf_NotInlined(Object o) {
- if ((o instanceof SubclassC) != true) {
- // Empty branch to flip the condition.
- } else {
- ((SubclassC)o).$noinline$g();
- }
- if ((o instanceof SubclassB) == false) {
- // Empty branch to flip the condition.
- } else {
- ((SubclassB)o).$noinline$g();
- }
- }
-
/// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) inliner (after)
/// CHECK-DAG: <<IOf:z\d+>> InstanceOf
/// CHECK-DAG: If [<<IOf>>]
diff --git a/test/454-get-vreg/build b/test/454-get-vreg/build
deleted file mode 100644
index 08987b5..0000000
--- a/test/454-get-vreg/build
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Stop if something fails.
-set -e
-
-# The test relies on DEX file produced by javac+dx so keep building with them for now
-# (see b/19467889)
-mkdir classes
-${JAVAC} -d classes `find src -name '*.java'`
-${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
- --dump-width=1000 ${DX_FLAGS} classes
-zip $TEST_NAME.jar classes.dex
diff --git a/test/458-checker-instruction-simplification/smali/SmaliTests.smali b/test/458-checker-instruction-simplification/smali/SmaliTests.smali
new file mode 100644
index 0000000..ede599b
--- /dev/null
+++ b/test/458-checker-instruction-simplification/smali/SmaliTests.smali
@@ -0,0 +1,193 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LSmaliTests;
+.super Ljava/lang/Object;
+
+## CHECK-START: int SmaliTests.EqualTrueRhs(boolean) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<Cond:z\d+>> Equal [<<Arg>>,<<Const1>>]
+## CHECK-DAG: If [<<Cond>>]
+
+## CHECK-START: int SmaliTests.EqualTrueRhs(boolean) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: If [<<Arg>>]
+
+.method public static EqualTrueRhs(Z)I
+ .registers 3
+
+ const v0, 0x1
+ const v1, 0x5
+ if-eq p0, v0, :return
+ const v1, 0x3
+ :return
+ return v1
+
+.end method
+
+## CHECK-START: int SmaliTests.EqualTrueLhs(boolean) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<Cond:z\d+>> Equal [<<Const1>>,<<Arg>>]
+## CHECK-DAG: If [<<Cond>>]
+
+## CHECK-START: int SmaliTests.EqualTrueLhs(boolean) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: If [<<Arg>>]
+
+.method public static EqualTrueLhs(Z)I
+ .registers 3
+
+ const v0, 0x1
+ const v1, 0x5
+ if-eq v0, p0, :return
+ const v1, 0x3
+ :return
+ return v1
+
+.end method
+
+## CHECK-START: int SmaliTests.EqualFalseRhs(boolean) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Cond:z\d+>> Equal [<<Arg>>,<<Const0>>]
+## CHECK-DAG: If [<<Cond>>]
+
+## CHECK-START: int SmaliTests.EqualFalseRhs(boolean) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: If [<<Arg>>]
+
+.method public static EqualFalseRhs(Z)I
+ .registers 3
+
+ const v0, 0x0
+ const v1, 0x3
+ if-eq p0, v0, :return
+ const v1, 0x5
+ :return
+ return v1
+
+.end method
+
+## CHECK-START: int SmaliTests.EqualFalseLhs(boolean) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Cond:z\d+>> Equal [<<Const0>>,<<Arg>>]
+## CHECK-DAG: If [<<Cond>>]
+
+## CHECK-START: int SmaliTests.EqualFalseLhs(boolean) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: If [<<Arg>>]
+
+.method public static EqualFalseLhs(Z)I
+ .registers 3
+
+ const v0, 0x0
+ const v1, 0x3
+ if-eq v0, p0, :return
+ const v1, 0x5
+ :return
+ return v1
+
+.end method
+
+## CHECK-START: int SmaliTests.NotEqualTrueRhs(boolean) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Arg>>,<<Const1>>]
+## CHECK-DAG: If [<<Cond>>]
+
+## CHECK-START: int SmaliTests.NotEqualTrueRhs(boolean) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: If [<<Arg>>]
+
+.method public static NotEqualTrueRhs(Z)I
+ .registers 3
+
+ const v0, 0x1
+ const v1, 0x3
+ if-ne p0, v0, :return
+ const v1, 0x5
+ :return
+ return v1
+
+.end method
+
+## CHECK-START: int SmaliTests.NotEqualTrueLhs(boolean) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Const1>>,<<Arg>>]
+## CHECK-DAG: If [<<Cond>>]
+
+## CHECK-START: int SmaliTests.NotEqualTrueLhs(boolean) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: If [<<Arg>>]
+
+.method public static NotEqualTrueLhs(Z)I
+ .registers 3
+
+ const v0, 0x1
+ const v1, 0x3
+ if-ne v0, p0, :return
+ const v1, 0x5
+ :return
+ return v1
+
+.end method
+
+## CHECK-START: int SmaliTests.NotEqualFalseRhs(boolean) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Arg>>,<<Const0>>]
+## CHECK-DAG: If [<<Cond>>]
+
+## CHECK-START: int SmaliTests.NotEqualFalseRhs(boolean) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: If [<<Arg>>]
+
+.method public static NotEqualFalseRhs(Z)I
+ .registers 3
+
+ const v0, 0x0
+ const v1, 0x5
+ if-ne p0, v0, :return
+ const v1, 0x3
+ :return
+ return v1
+
+.end method
+
+## CHECK-START: int SmaliTests.NotEqualFalseLhs(boolean) instruction_simplifier (before)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Const0>>,<<Arg>>]
+## CHECK-DAG: If [<<Cond>>]
+
+## CHECK-START: int SmaliTests.NotEqualFalseLhs(boolean) instruction_simplifier (after)
+## CHECK-DAG: <<Arg:z\d+>> ParameterValue
+## CHECK-DAG: If [<<Arg>>]
+
+.method public static NotEqualFalseLhs(Z)I
+ .registers 3
+
+ const v0, 0x0
+ const v1, 0x5
+ if-ne v0, p0, :return
+ const v1, 0x3
+ :return
+ return v1
+
+.end method
+
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index 8d6bb65..8640148 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import java.lang.reflect.Method;
+
public class Main {
public static void assertBooleanEquals(boolean expected, boolean result) {
@@ -826,17 +828,16 @@
/// CHECK-START: long Main.NotNot1(long) instruction_simplifier (before)
/// CHECK-DAG: <<Arg:j\d+>> ParameterValue
- /// CHECK-DAG: <<ConstF1:j\d+>> LongConstant -1
- /// CHECK-DAG: <<Xor1:j\d+>> Xor [<<Arg>>,<<ConstF1>>]
- /// CHECK-DAG: <<Xor2:j\d+>> Xor [<<Xor1>>,<<ConstF1>>]
- /// CHECK-DAG: Return [<<Xor2>>]
+ /// CHECK-DAG: <<Not1:j\d+>> Not [<<Arg>>]
+ /// CHECK-DAG: <<Not2:j\d+>> Not [<<Not1>>]
+ /// CHECK-DAG: Return [<<Not2>>]
/// CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
/// CHECK-DAG: <<Arg:j\d+>> ParameterValue
/// CHECK-DAG: Return [<<Arg>>]
/// CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
- /// CHECK-NOT: Xor
+ /// CHECK-NOT: Not
public static long NotNot1(long arg) {
return ~~arg;
@@ -844,10 +845,9 @@
/// CHECK-START: int Main.NotNot2(int) instruction_simplifier (before)
/// CHECK-DAG: <<Arg:i\d+>> ParameterValue
- /// CHECK-DAG: <<ConstF1:i\d+>> IntConstant -1
- /// CHECK-DAG: <<Xor1:i\d+>> Xor [<<Arg>>,<<ConstF1>>]
- /// CHECK-DAG: <<Xor2:i\d+>> Xor [<<Xor1>>,<<ConstF1>>]
- /// CHECK-DAG: <<Add:i\d+>> Add [<<Xor2>>,<<Xor1>>]
+ /// CHECK-DAG: <<Not1:i\d+>> Not [<<Arg>>]
+ /// CHECK-DAG: <<Not2:i\d+>> Not [<<Not1>>]
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Not2>>,<<Not1>>]
/// CHECK-DAG: Return [<<Add>>]
/// CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
@@ -857,7 +857,8 @@
/// CHECK-DAG: Return [<<Add>>]
/// CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
- /// CHECK-NOT: Xor
+ /// CHECK: Not
+ /// CHECK-NOT: Not
public static int NotNot2(int arg) {
int temp = ~arg;
@@ -965,174 +966,6 @@
return res;
}
- /// CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Cond:z\d+>> Equal [<<Arg>>,<<Const1>>]
- /// CHECK-DAG: If [<<Cond>>]
-
- /// CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: If [<<Arg>>]
-
- /// CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier_before_codegen (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const3>>,<<Const5>>,<<Arg>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static int EqualTrueRhs(boolean arg) {
- return (arg != true) ? 3 : 5;
- }
-
- /// CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Cond:z\d+>> Equal [<<Const1>>,<<Arg>>]
- /// CHECK-DAG: If [<<Cond>>]
-
- /// CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: If [<<Arg>>]
-
- /// CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier_before_codegen (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const3>>,<<Const5>>,<<Arg>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static int EqualTrueLhs(boolean arg) {
- return (true != arg) ? 3 : 5;
- }
-
- /// CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Cond:z\d+>> Equal [<<Arg>>,<<Const0>>]
- /// CHECK-DAG: If [<<Cond>>]
-
- /// CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: If [<<Arg>>]
-
- /// CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier_before_codegen (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const5>>,<<Const3>>,<<Arg>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static int EqualFalseRhs(boolean arg) {
- return (arg != false) ? 3 : 5;
- }
-
- /// CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Cond:z\d+>> Equal [<<Arg>>,<<Const0>>]
- /// CHECK-DAG: If [<<Cond>>]
-
- /// CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: If [<<Arg>>]
-
- /// CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier_before_codegen (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const5>>,<<Const3>>,<<Arg>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static int EqualFalseLhs(boolean arg) {
- return (false != arg) ? 3 : 5;
- }
-
- /// CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Arg>>,<<Const1>>]
- /// CHECK-DAG: If [<<Cond>>]
-
- /// CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: If [<<Arg>>]
-
- /// CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier_before_codegen (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const5>>,<<Const3>>,<<Arg>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static int NotEqualTrueRhs(boolean arg) {
- return (arg == true) ? 3 : 5;
- }
-
- /// CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Const1>>,<<Arg>>]
- /// CHECK-DAG: If [<<Cond>>]
-
- /// CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: If [<<Arg>>]
-
- /// CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier_before_codegen (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const5>>,<<Const3>>,<<Arg>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static int NotEqualTrueLhs(boolean arg) {
- return (true == arg) ? 3 : 5;
- }
-
- /// CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Arg>>,<<Const0>>]
- /// CHECK-DAG: If [<<Cond>>]
-
- /// CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: If [<<Arg>>]
-
- /// CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier_before_codegen (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const3>>,<<Const5>>,<<Arg>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static int NotEqualFalseRhs(boolean arg) {
- return (arg == false) ? 3 : 5;
- }
-
- /// CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (before)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Arg>>,<<Const0>>]
- /// CHECK-DAG: If [<<Cond>>]
-
- /// CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: If [<<Arg>>]
-
- /// CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier_before_codegen (after)
- /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
- /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Select:i\d+>> Select [<<Const3>>,<<Const5>>,<<Arg>>]
- /// CHECK-DAG: Return [<<Select>>]
-
- public static int NotEqualFalseLhs(boolean arg) {
- return (false == arg) ? 3 : 5;
- }
-
/// CHECK-START: boolean Main.EqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (before)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
@@ -1307,17 +1140,16 @@
return arg * 31;
}
- /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier (before)
+ /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier_after_bce (before)
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
/// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
/// CHECK-DAG: <<NE:z\d+>> NotEqual [<<Field>>,<<Const1>>]
- /// CHECK-DAG: If [<<NE>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const13>>,<<Const54>>,<<NE>>]
+ /// CHECK-DAG: Return [<<Select>>]
- /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier (after)
- /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
- /// CHECK-DAG: If [<<Field>>]
-
- /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier_before_codegen (after)
+ /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier_after_bce (after)
/// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
/// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
/// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
@@ -1325,20 +1157,19 @@
/// CHECK-DAG: Return [<<Select>>]
public static int booleanFieldNotEqualOne() {
- return (booleanField == true) ? 13 : 54;
+ return (booleanField == $inline$true()) ? 13 : 54;
}
- /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier (before)
+ /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier_after_bce (before)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
/// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
- /// CHECK-DAG: <<EQ:z\d+>> Equal [<<Field>>,<<Const0>>]
- /// CHECK-DAG: If [<<EQ>>]
+ /// CHECK-DAG: <<NE:z\d+>> Equal [<<Field>>,<<Const0>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const13>>,<<Const54>>,<<NE>>]
+ /// CHECK-DAG: Return [<<Select>>]
- /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier (after)
- /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
- /// CHECK-DAG: If [<<Field>>]
-
- /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier_before_codegen (after)
+ /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier_after_bce (after)
/// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
/// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
/// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
@@ -1346,7 +1177,7 @@
/// CHECK-DAG: Return [<<Select>>]
public static int booleanFieldEqualZero() {
- return (booleanField != false) ? 13 : 54;
+ return (booleanField != $inline$false()) ? 13 : 54;
}
/// CHECK-START: int Main.intConditionNotEqualOne(int) instruction_simplifier_after_bce (before)
@@ -1374,7 +1205,7 @@
// LessThanOrEqual instructions.
public static int intConditionNotEqualOne(int i) {
- return ((i > 42) == true) ? 13 : 54;
+ return ((i > 42) == $inline$true()) ? 13 : 54;
}
/// CHECK-START: int Main.intConditionEqualZero(int) instruction_simplifier_after_bce (before)
@@ -1402,7 +1233,7 @@
// LessThanOrEqual instructions.
public static int intConditionEqualZero(int i) {
- return ((i > 42) != false) ? 13 : 54;
+ return ((i > 42) != $inline$false()) ? 13 : 54;
}
// Test that conditions on float/double are not flipped.
@@ -1770,6 +1601,16 @@
return (short) (value & 0x17fff);
}
+ public static int runSmaliTest(String name, boolean input) {
+ try {
+ Class<?> c = Class.forName("SmaliTests");
+ Method m = c.getMethod(name, new Class[] { boolean.class });
+ return (Integer) m.invoke(null, input);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
public static void main(String[] args) {
int arg = 123456;
@@ -1804,14 +1645,6 @@
assertIntEquals(SubNeg1(arg, arg + 1), -(arg + arg + 1));
assertIntEquals(SubNeg2(arg, arg + 1), -(arg + arg + 1));
assertLongEquals(SubNeg3(arg, arg + 1), -(2 * arg + 1));
- assertIntEquals(EqualTrueRhs(true), 5);
- assertIntEquals(EqualTrueLhs(true), 5);
- assertIntEquals(EqualFalseRhs(true), 3);
- assertIntEquals(EqualFalseLhs(true), 3);
- assertIntEquals(NotEqualTrueRhs(true), 3);
- assertIntEquals(NotEqualTrueLhs(true), 3);
- assertIntEquals(NotEqualFalseRhs(true), 5);
- assertIntEquals(NotEqualFalseLhs(true), 5);
assertBooleanEquals(EqualBoolVsIntConst(true), true);
assertBooleanEquals(EqualBoolVsIntConst(true), true);
assertBooleanEquals(NotEqualBoolVsIntConst(false), false);
@@ -1906,7 +1739,20 @@
assertIntEquals(intAnd0x17fffToShort(0x88888888), 0x0888);
assertIntEquals(intAnd0x17fffToShort(Integer.MIN_VALUE), 0);
assertIntEquals(intAnd0x17fffToShort(Integer.MAX_VALUE), Short.MAX_VALUE);
+
+ for (String condition : new String[] { "Equal", "NotEqual" }) {
+ for (String constant : new String[] { "True", "False" }) {
+ for (String side : new String[] { "Rhs", "Lhs" }) {
+ String name = condition + constant + side;
+ assertIntEquals(runSmaliTest(name, true), 5);
+ assertIntEquals(runSmaliTest(name, false), 3);
+ }
+ }
+ }
}
+ private static boolean $inline$true() { return true; }
+ private static boolean $inline$false() { return false; }
+
public static boolean booleanField;
}
diff --git a/test/463-checker-boolean-simplifier/src/Main.java b/test/463-checker-boolean-simplifier/src/Main.java
index 682f126..f0fe1b1 100644
--- a/test/463-checker-boolean-simplifier/src/Main.java
+++ b/test/463-checker-boolean-simplifier/src/Main.java
@@ -42,7 +42,7 @@
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: If [<<Param>>]
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
+ /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const0>>,<<Const1>>]
/// CHECK-DAG: Return [<<Phi>>]
/// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (before)
@@ -185,11 +185,7 @@
/// CHECK-NOT: BooleanNot
public static int NegatedCondition(boolean x) {
- if (x != false) {
- return 42;
- } else {
- return 43;
- }
+ return (x != false) ? 42 : 43;
}
/// CHECK-START: int Main.SimpleTrueBlock(boolean, int) select_generator (after)
@@ -253,13 +249,7 @@
/// CHECK-DAG: Return [<<Select123>>]
public static int ThreeBlocks(boolean x, boolean y) {
- if (x) {
- return 1;
- } else if (y) {
- return 2;
- } else {
- return 3;
- }
+ return x ? 1 : (y ? 2 : 3);
}
/// CHECK-START: int Main.MultiplePhis() select_generator (before)
@@ -292,8 +282,10 @@
while (y++ < 10) {
if (y > 1) {
x = 13;
+ continue;
} else {
x = 42;
+ continue;
}
}
return x;
diff --git a/test/530-checker-loops/src/Main.java b/test/530-checker-loops/src/Main.java
index d5111b0..2e5fd25 100644
--- a/test/530-checker-loops/src/Main.java
+++ b/test/530-checker-loops/src/Main.java
@@ -633,6 +633,10 @@
}
}
+ //
+ // Verifier.
+ //
+
public static void main(String[] args) {
int[] empty = { };
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
diff --git a/test/537-checker-inline-and-unverified/src/Main.java b/test/537-checker-inline-and-unverified/src/Main.java
index bdc14b0..b9d5fc9 100644
--- a/test/537-checker-inline-and-unverified/src/Main.java
+++ b/test/537-checker-inline-and-unverified/src/Main.java
@@ -45,12 +45,14 @@
}
public static boolean $opt$noinline$testNoInline() {
+ boolean result = true;
try {
- return null instanceof InaccessibleClass;
+ result = (null instanceof InaccessibleClass);
+ throw new Error("Unreachable");
} catch (IllegalAccessError e) {
// expected
}
- return false;
+ return result;
}
public static boolean $opt$inline$testInline() {
diff --git a/test/555-checker-regression-x86const/build b/test/555-checker-regression-x86const/build
index 09dcc36..92ddfc9 100644
--- a/test/555-checker-regression-x86const/build
+++ b/test/555-checker-regression-x86const/build
@@ -27,14 +27,12 @@
mv classes/UnresolvedClass.class classes-ex
if [ ${USE_JACK} = "true" ]; then
- # Create .jack files from classes generated with javac.
- ${JILL} classes --output classes.jack
- ${JILL} classes-ex --output classes-ex.jack
+ jar cf classes.jill.jar -C classes .
+ jar cf classes-ex.jill.jar -C classes-ex .
- # Create DEX files from .jack files.
- ${JACK} --import classes.jack --output-dex .
+ ${JACK} --import classes.jill.jar --output-dex .
zip $TEST_NAME.jar classes.dex
- ${JACK} --import classes-ex.jack --output-dex .
+ ${JACK} --import classes-ex.jill.jar --output-dex .
zip ${TEST_NAME}-ex.jar classes.dex
else
if [ ${NEED_DEX} = "true" ]; then
diff --git a/test/563-checker-invoke-super/build b/test/563-checker-invoke-super/build
index e06193b..32f84ef 100755
--- a/test/563-checker-invoke-super/build
+++ b/test/563-checker-invoke-super/build
@@ -20,9 +20,5 @@
# Hard-wired use of experimental jack.
# TODO: fix this temporary work-around for lambdas, see b/19467889
export USE_JACK=true
-export JACK_SERVER=false
-export JACK_REPOSITORY="${ANDROID_BUILD_TOP}/prebuilts/sdk/tools/jacks"
-# e.g. /foo/bar/jack-3.10.ALPHA.jar -> 3.10.ALPHA
-export JACK_VERSION="$(find "$JACK_REPOSITORY" -name '*ALPHA*' | sed 's/.*jack-//g' | sed 's/[.]jar//g')"
./default-build "$@" --experimental default-methods
diff --git a/test/565-checker-condition-liveness/src/Main.java b/test/565-checker-condition-liveness/src/Main.java
index dc4cb76..acfcecd 100644
--- a/test/565-checker-condition-liveness/src/Main.java
+++ b/test/565-checker-condition-liveness/src/Main.java
@@ -28,10 +28,7 @@
/// CHECK-EVAL: <<UseInput>> == <<LivSel>> + 1
public static int p(float arg) {
- if (arg > 5.0f) {
- return 0;
- }
- return -1;
+ return (arg > 5.0f) ? 0 : -1;
}
/// CHECK-START: void Main.main(java.lang.String[]) liveness (after)
diff --git a/test/565-checker-doublenegbitwise/src/Main.java b/test/565-checker-doublenegbitwise/src/Main.java
index 2d70e11..e426b75 100644
--- a/test/565-checker-doublenegbitwise/src/Main.java
+++ b/test/565-checker-doublenegbitwise/src/Main.java
@@ -35,14 +35,11 @@
* Test transformation of Not/Not/And into Or/Not.
*/
- // Note: before the instruction_simplifier pass, Xor's are used instead of
- // Not's (the simplification happens during the same pass).
/// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
/// CHECK: <<P1:i\d+>> ParameterValue
/// CHECK: <<P2:i\d+>> ParameterValue
- /// CHECK: <<CstM1:i\d+>> IntConstant -1
- /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
- /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
+ /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
+ /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
/// CHECK: <<And:i\d+>> And [<<Not1>>,<<Not2>>]
/// CHECK: Return [<<And>>]
@@ -106,14 +103,11 @@
* Test transformation of Not/Not/Or into And/Not.
*/
- // See note above.
- // The second Xor has its arguments reversed for no obvious reason.
/// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
/// CHECK: <<P1:j\d+>> ParameterValue
/// CHECK: <<P2:j\d+>> ParameterValue
- /// CHECK: <<CstM1:j\d+>> LongConstant -1
- /// CHECK: <<Not1:j\d+>> Xor [<<P1>>,<<CstM1>>]
- /// CHECK: <<Not2:j\d+>> Xor [<<CstM1>>,<<P2>>]
+ /// CHECK: <<Not1:j\d+>> Not [<<P1>>]
+ /// CHECK: <<Not2:j\d+>> Not [<<P2>>]
/// CHECK: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>]
/// CHECK: Return [<<Or>>]
@@ -183,12 +177,11 @@
/// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
/// CHECK: <<P1:i\d+>> ParameterValue
/// CHECK: <<P2:i\d+>> ParameterValue
- /// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<CstM1:i\d+>> IntConstant -1
+ /// CHECK: <<Cst1:i\d+>> IntConstant 1
/// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
- /// CHECK: <<Not1:i\d+>> Xor [<<AddP1>>,<<CstM1>>]
+ /// CHECK: <<Not1:i\d+>> Not [<<AddP1>>]
/// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
- /// CHECK: <<Not2:i\d+>> Xor [<<AddP2>>,<<CstM1>>]
+ /// CHECK: <<Not2:i\d+>> Not [<<AddP2>>]
/// CHECK: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>]
/// CHECK: Return [<<Or>>]
@@ -226,9 +219,8 @@
/// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
/// CHECK: <<P1:i\d+>> ParameterValue
/// CHECK: <<P2:i\d+>> ParameterValue
- /// CHECK: <<CstM1:i\d+>> IntConstant -1
- /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
- /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
+ /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
+ /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
/// CHECK: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>]
/// CHECK: Return [<<Xor>>]
@@ -285,11 +277,10 @@
/// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
/// CHECK: <<P1:i\d+>> ParameterValue
/// CHECK: <<P2:i\d+>> ParameterValue
- /// CHECK: <<CstM1:i\d+>> IntConstant -1
/// CHECK: <<One:i\d+>> IntConstant 1
- /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
+ /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
/// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>]
- /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
+ /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
/// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
/// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
/// CHECK: Return [<<Add>>]
diff --git a/test/577-checker-fp2int/src/Main.java b/test/577-checker-fp2int/src/Main.java
index e3f1230..ace956d 100644
--- a/test/577-checker-fp2int/src/Main.java
+++ b/test/577-checker-fp2int/src/Main.java
@@ -21,7 +21,8 @@
/// CHECK-DAG: Return [<<Result>>]
//
/// CHECK-START: int Main.f2int(float) instruction_simplifier (after)
- /// CHECK-DAG: <<Raw:i\d+>> InvokeStaticOrDirect [<<Arg:f\d+>>] intrinsic:FloatFloatToRawIntBits
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: <<Raw:i\d+>> InvokeStaticOrDirect [<<Arg:f\d+>>{{(,[ij]\d+)?}}] intrinsic:FloatFloatToRawIntBits
/// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Arg>>,<<Arg>>]
/// CHECK-DAG: <<Result:i\d+>> Select [<<Raw>>,{{i\d+}},<<Cond>>]
/// CHECK-DAG: Return [<<Result>>]
@@ -34,7 +35,8 @@
/// CHECK-DAG: Return [<<Result>>]
//
/// CHECK-START: long Main.d2long(double) instruction_simplifier (after)
- /// CHECK-DAG: <<Raw:j\d+>> InvokeStaticOrDirect [<<Arg:d\d+>>] intrinsic:DoubleDoubleToRawLongBits
+ // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
+ /// CHECK-DAG: <<Raw:j\d+>> InvokeStaticOrDirect [<<Arg:d\d+>>{{(,[ij]\d+)?}}] intrinsic:DoubleDoubleToRawLongBits
/// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Arg>>,<<Arg>>]
/// CHECK-DAG: <<Result:j\d+>> Select [<<Raw>>,{{j\d+}},<<Cond>>]
/// CHECK-DAG: Return [<<Result>>]
diff --git a/test/578-bce-visit/expected.txt b/test/578-bce-visit/expected.txt
new file mode 100644
index 0000000..28fca2c
--- /dev/null
+++ b/test/578-bce-visit/expected.txt
@@ -0,0 +1,2 @@
+exception caught
+FUZZ result = 1001 16
diff --git a/test/578-bce-visit/info.txt b/test/578-bce-visit/info.txt
new file mode 100644
index 0000000..2462e1b
--- /dev/null
+++ b/test/578-bce-visit/info.txt
@@ -0,0 +1 @@
+Fuzz test that exposed bug in bounds check elimination visiting of blocks.
diff --git a/test/578-bce-visit/src/Main.java b/test/578-bce-visit/src/Main.java
new file mode 100644
index 0000000..b0e920e
--- /dev/null
+++ b/test/578-bce-visit/src/Main.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Automatically generated fuzz test that exposed bug in the way bounds
+ * check elimination visits basic blocks. If, after dynamic bce, the same
+ * block would be visited again, then static length based bce would incorrectly
+ * feed information back to itself and removed a necessary bounds check.
+ */
+public class Main {
+
+ private static int[][][] mA = new int[10][10][10];
+
+ private static int mX = 17;
+
+ private static int doit() {
+ int l0 = (((++mA[7][2][8]) <= mA[0][1][3]) ? (++mA[9][0][5]) : ((( -mA[0][7][0]) * ((mX == mX) ? 180 : mX)) + (mA[7][8][8]++)));
+ mA[1][0][4] -= mX;
+ int l1 = (((l0 >= ( ~mA[6][7][5])) && ((921 <= l0) && (mA[3][9][6] > l0))) ? mX : (l0--));
+ int l2 = ( -384);
+ for (int i0 = 7 - 1; i0 >= 1; i0--) {
+ mA[6][0][0] -= ((((l0++) == ( -mX)) ? (((mA[3][i0][1] > 503) || (mX <= i0)) ? (--l0) : (l0--)) : mX) - ( ~(mX--)));
+ int l3 = 24;
+ int l4 = ((l2--) & mX);
+ for (int i1 = i0-2 - 1; i1 >= 3; i1--) {
+ for (int i2 = 2; i2 < i0; i2++) {
+ mA[i0][4][l3] >>= 1;
+ }
+ }
+ }
+ return 1;
+ }
+
+ public static void main(String[] args) {
+ int k = 1;
+ for (int i0 = 0; i0 < 10; i0++)
+ for (int i1 = 0; i1 < 10; i1++)
+ for (int i2 = 0; i2 < 10; i2++)
+ mA[i0][i1][i2] = k++;
+ try {
+ k = doit();
+ } catch (Exception e) {
+ System.out.println("exception caught");
+ }
+ System.out.println("FUZZ result = " + k + " " + mX);
+ }
+}
diff --git a/test/578-polymorphic-inlining/expected.txt b/test/578-polymorphic-inlining/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/578-polymorphic-inlining/expected.txt
diff --git a/test/578-polymorphic-inlining/info.txt b/test/578-polymorphic-inlining/info.txt
new file mode 100644
index 0000000..77ec49b
--- /dev/null
+++ b/test/578-polymorphic-inlining/info.txt
@@ -0,0 +1,2 @@
+Regression test for polymorphic inlining that used to propagate
+wrongly the try/catch information of new blocks.
diff --git a/test/578-polymorphic-inlining/src/Main.java b/test/578-polymorphic-inlining/src/Main.java
new file mode 100644
index 0000000..22d33d0
--- /dev/null
+++ b/test/578-polymorphic-inlining/src/Main.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+ public static void main(String[] args) {
+ for (int i = 0; i < 20000; ++i) {
+ $noinline$testInTryCatch(new Main(), i);
+ $noinline$testInTryCatch(new SubMain(), i);
+ }
+ }
+
+ public static void $noinline$testInTryCatch(Main m, int i) {
+ final int value;
+ try {
+ throw new Exception();
+ } catch (Exception e) {
+ // The polymorphic inlining of 'willInlineVoid' used to generate an
+ // incorrect graph, by setting the inlined blocks as catch blocks.
+ m.willInlineVoid(i);
+ return;
+ }
+ }
+
+ public void willInlineVoid(int i) {
+ if (i == 0) {
+ $noinline$foo();
+ } else {
+ $noinline$foo();
+ $noinline$foo();
+ }
+ }
+
+ public static void $noinline$foo() {
+ if (doThrow) throw new Error("");
+ }
+
+ public static boolean doThrow;
+}
+
+class SubMain extends Main {
+ public void willInlineVoid(int i) {
+ }
+}
diff --git a/test/579-inline-infinite/expected.txt b/test/579-inline-infinite/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/579-inline-infinite/expected.txt
diff --git a/test/579-inline-infinite/info.txt b/test/579-inline-infinite/info.txt
new file mode 100644
index 0000000..6fb917c
--- /dev/null
+++ b/test/579-inline-infinite/info.txt
@@ -0,0 +1,2 @@
+Regression test for optimizing.
+Inlining of method with infinite loop cause a crash.
diff --git a/test/579-inline-infinite/src/Main.java b/test/579-inline-infinite/src/Main.java
new file mode 100644
index 0000000..f214ed4
--- /dev/null
+++ b/test/579-inline-infinite/src/Main.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class Infinite implements Runnable {
+ public int field;
+
+ private final void $noinline$infinite() {
+ while(true) {
+ field++;
+ }
+ }
+
+ public void run() {
+ $noinline$infinite();
+ }
+}
+
+public class Main {
+ public static void main(String[] args) {
+ Thread thr = new Thread(new Infinite());
+ thr.setDaemon(true);
+ thr.start();
+ // This is a compiler test, so just finish.
+ }
+}
diff --git a/test/960-default-smali/build b/test/960-default-smali/build
index b72afcd..e8f4ed0 100755
--- a/test/960-default-smali/build
+++ b/test/960-default-smali/build
@@ -17,27 +17,14 @@
# make us exit on a failure
set -e
-# Generate the smali Main.smali file or fail
-${ANDROID_BUILD_TOP}/art/test/utils/python/generate_smali_main.py ./smali
-
-# Should we compile with Java source code. By default we will use Smali.
-USES_JAVA_SOURCE="false"
-if [[ $@ == *"--jvm"* ]]; then
- USES_JAVA_SOURCE="true"
-elif [[ "$USE_JACK" == "true" ]]; then
- if $JACK -D jack.java.source.version=1.8 >& /dev/null; then
- USES_JAVA_SOURCE="true"
- else
- echo "WARNING: Cannot use jack because it does not support JLS 1.8. Falling back to smali" >&2
- fi
+if [[ $@ != *"--jvm"* ]]; then
+ # Don't do anything with jvm
+ # Hard-wired use of experimental jack.
+ # TODO: fix this temporary work-around for default-methods, see b/19467889
+ export USE_JACK=true
fi
-if [[ "$USES_JAVA_SOURCE" == "true" ]]; then
- # We are compiling java code, create it.
- mkdir -p src
- ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
- # Ignore the smali directory.
- EXTRA_ARGS="--no-smali"
-fi
+# Generate the Main.java file or fail
+${ANDROID_BUILD_TOP}/art/test/utils/python/generate_java_main.py ./src
-./default-build "$@" "$EXTRA_ARGS" --experimental default-methods
+./default-build "$@" --experimental default-methods
diff --git a/test/960-default-smali/smali/A.smali b/test/960-default-smali/smali/A.smali
deleted file mode 100644
index e755612..0000000
--- a/test/960-default-smali/smali/A.smali
+++ /dev/null
@@ -1,38 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LA;
-.super Ljava/lang/Object;
-.implements LGreeter;
-
-# class A implements Greeter {
-# public String SayHi() {
-# return "Hi ";
-# }
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public SayHi()Ljava/lang/String;
- .registers 1
-
- const-string v0, "Hi "
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/Attendant.smali b/test/960-default-smali/smali/Attendant.smali
deleted file mode 100644
index ab63aee..0000000
--- a/test/960-default-smali/smali/Attendant.smali
+++ /dev/null
@@ -1,53 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public abstract interface LAttendant;
-.super Ljava/lang/Object;
-
-# public interface Attendant {
-# public default String SayHi() {
-# return "welcome to " + GetPlace();
-# }
-# public default String SayHiTwice() {
-# return SayHi() + SayHi();
-# }
-#
-# public String GetPlace();
-# }
-
-.method public SayHi()Ljava/lang/String;
- .locals 2
- const-string v0, "welcome to "
- invoke-interface {p0}, LAttendant;->GetPlace()Ljava/lang/String;
- move-result-object v1
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
-
-.method public SayHiTwice()Ljava/lang/String;
- .locals 2
- invoke-interface {p0}, LAttendant;->SayHi()Ljava/lang/String;
- move-result-object v0
- invoke-interface {p0}, LAttendant;->SayHi()Ljava/lang/String;
- move-result-object v1
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
-
-.method public abstract GetPlace()Ljava/lang/String;
-.end method
diff --git a/test/960-default-smali/smali/B.smali b/test/960-default-smali/smali/B.smali
deleted file mode 100644
index d847dd1..0000000
--- a/test/960-default-smali/smali/B.smali
+++ /dev/null
@@ -1,38 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LB;
-.super Ljava/lang/Object;
-.implements LGreeter2;
-
-# class B implements Greeter2 {
-# public String SayHi() {
-# return "Hello ";
-# }
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public SayHi()Ljava/lang/String;
- .registers 1
-
- const-string v0, "Hello "
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/C.smali b/test/960-default-smali/smali/C.smali
deleted file mode 100644
index 08a8508..0000000
--- a/test/960-default-smali/smali/C.smali
+++ /dev/null
@@ -1,37 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LC;
-.super LA;
-
-# class C extends A {
-# public String SayHiTwice() {
-# return "You don't control me";
-# }
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, LA;-><init>()V
- return-void
-.end method
-
-.method public SayHiTwice()Ljava/lang/String;
- .registers 1
-
- const-string v0, "You don't control me"
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/D.smali b/test/960-default-smali/smali/D.smali
deleted file mode 100644
index 32f3b7e..0000000
--- a/test/960-default-smali/smali/D.smali
+++ /dev/null
@@ -1,38 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LD;
-.super Ljava/lang/Object;
-.implements LGreeter3;
-
-# class D implements Greeter3 {
-# public String GetName() {
-# return "Alex ";
-# }
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public GetName()Ljava/lang/String;
- .registers 1
-
- const-string v0, "Alex "
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/E.smali b/test/960-default-smali/smali/E.smali
deleted file mode 100644
index bae6250..0000000
--- a/test/960-default-smali/smali/E.smali
+++ /dev/null
@@ -1,38 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LE;
-.super LA;
-.implements LGreeter2;
-
-# class E extends A implements Greeter2 {
-# public String SayHi() {
-# return "Hi2 ";
-# }
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, LA;-><init>()V
- return-void
-.end method
-
-.method public SayHi()Ljava/lang/String;
- .registers 1
-
- const-string v0, "Hi2 "
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/Extension.smali b/test/960-default-smali/smali/Extension.smali
deleted file mode 100644
index 60ffa26..0000000
--- a/test/960-default-smali/smali/Extension.smali
+++ /dev/null
@@ -1,30 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public abstract interface LExtension;
-.super Ljava/lang/Object;
-
-# public interface Extension {
-# public default String SayHi() {
-# return "welcome ";
-# }
-# }
-
-.method public SayHi()Ljava/lang/String;
- .locals 1
- const-string v0, "welcome "
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/F.smali b/test/960-default-smali/smali/F.smali
deleted file mode 100644
index 3eaa089..0000000
--- a/test/960-default-smali/smali/F.smali
+++ /dev/null
@@ -1,47 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LF;
-.super LA;
-.implements LAttendant;
-
-# class F extends A implements Attendant {
-# public String GetPlace() {
-# return "android";
-# }
-# public String SayHiTwice() {
-# return "We can override both interfaces";
-# }
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public SayHiTwice()Ljava/lang/String;
- .registers 1
-
- const-string v0, "We can override both interfaces"
- return-object v0
-.end method
-
-.method public GetPlace()Ljava/lang/String;
- .registers 1
- const-string v0, "android"
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/G.smali b/test/960-default-smali/smali/G.smali
deleted file mode 100644
index 446f2a4..0000000
--- a/test/960-default-smali/smali/G.smali
+++ /dev/null
@@ -1,37 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LG;
-.super Ljava/lang/Object;
-.implements LAttendant;
-
-# class G implements Attendant {
-# public String GetPlace() {
-# return "android";
-# }
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public GetPlace()Ljava/lang/String;
- .registers 1
- const-string v0, "android"
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/Greeter.smali b/test/960-default-smali/smali/Greeter.smali
deleted file mode 100644
index 28530ff..0000000
--- a/test/960-default-smali/smali/Greeter.smali
+++ /dev/null
@@ -1,40 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public abstract interface LGreeter;
-.super Ljava/lang/Object;
-
-# public interface Greeter {
-# public String SayHi();
-#
-# public default String SayHiTwice() {
-# return SayHi() + SayHi();
-# }
-# }
-
-.method public abstract SayHi()Ljava/lang/String;
-.end method
-
-.method public SayHiTwice()Ljava/lang/String;
- .locals 2
- invoke-interface {p0}, LGreeter;->SayHi()Ljava/lang/String;
- move-result-object v0
- invoke-interface {p0}, LGreeter;->SayHi()Ljava/lang/String;
- move-result-object v1
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/Greeter2.smali b/test/960-default-smali/smali/Greeter2.smali
deleted file mode 100644
index ace1798..0000000
--- a/test/960-default-smali/smali/Greeter2.smali
+++ /dev/null
@@ -1,39 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public abstract interface LGreeter2;
-.super Ljava/lang/Object;
-.implements LGreeter;
-
-# public interface Greeter2 extends Greeter {
-# public default String SayHiTwice() {
-# return "I say " + SayHi() + SayHi();
-# }
-# }
-
-.method public SayHiTwice()Ljava/lang/String;
- .locals 3
- const-string v0, "I say "
- invoke-interface {p0}, LGreeter;->SayHi()Ljava/lang/String;
- move-result-object v1
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- invoke-interface {p0}, LGreeter;->SayHi()Ljava/lang/String;
- move-result-object v1
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/Greeter3.smali b/test/960-default-smali/smali/Greeter3.smali
deleted file mode 100644
index 31fc2e7..0000000
--- a/test/960-default-smali/smali/Greeter3.smali
+++ /dev/null
@@ -1,40 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public abstract interface LGreeter3;
-.super Ljava/lang/Object;
-.implements LGreeter;
-
-# public interface Greeter3 extends Greeter {
-# public String GetName();
-#
-# public default String SayHi() {
-# return "Hello " + GetName();
-# }
-# }
-
-.method public abstract GetName()Ljava/lang/String;
-.end method
-
-.method public SayHi()Ljava/lang/String;
- .locals 2
- const-string v0, "Hello "
- invoke-interface {p0}, LGreeter3;->GetName()Ljava/lang/String;
- move-result-object v1
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/960-default-smali/smali/H.smali b/test/960-default-smali/smali/H.smali
deleted file mode 100644
index 82065ea..0000000
--- a/test/960-default-smali/smali/H.smali
+++ /dev/null
@@ -1,28 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LH;
-.super Ljava/lang/Object;
-.implements LExtension;
-
-# class H implements Extension {
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
diff --git a/test/960-default-smali/smali/I.smali b/test/960-default-smali/smali/I.smali
deleted file mode 100644
index 72fb58a..0000000
--- a/test/960-default-smali/smali/I.smali
+++ /dev/null
@@ -1,28 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LI;
-.super LA;
-.implements LGreeter2;
-
-# class I extends A implements Greeter2 {
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
diff --git a/test/960-default-smali/smali/J.smali b/test/960-default-smali/smali/J.smali
deleted file mode 100644
index 93f3d62..0000000
--- a/test/960-default-smali/smali/J.smali
+++ /dev/null
@@ -1,29 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LJ;
-.super LA;
-
-# class J extends A {
-# }
-
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, LA;-><init>()V
- return-void
-.end method
-
diff --git a/test/960-default-smali/src/A.java b/test/960-default-smali/src/A.java
new file mode 100644
index 0000000..7664a26
--- /dev/null
+++ b/test/960-default-smali/src/A.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class A implements Greeter {
+ public String SayHi() {
+ return "Hi ";
+ }
+}
diff --git a/test/960-default-smali/src/Attendant.java b/test/960-default-smali/src/Attendant.java
new file mode 100644
index 0000000..9f9a58a
--- /dev/null
+++ b/test/960-default-smali/src/Attendant.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Attendant {
+ public default String SayHi() {
+ return "welcome to " + GetPlace();
+ }
+ public default String SayHiTwice() {
+ return SayHi() + SayHi();
+ }
+ public String GetPlace();
+}
diff --git a/test/960-default-smali/src/B.java b/test/960-default-smali/src/B.java
new file mode 100644
index 0000000..18aaade
--- /dev/null
+++ b/test/960-default-smali/src/B.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class B implements Greeter2 {
+ public String SayHi() {
+ return "Hello ";
+ }
+}
diff --git a/test/960-default-smali/src/C.java b/test/960-default-smali/src/C.java
new file mode 100644
index 0000000..f0bc185f
--- /dev/null
+++ b/test/960-default-smali/src/C.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class C extends A {
+ public String SayHiTwice() {
+ return "You don't control me";
+ }
+}
diff --git a/test/960-default-smali/src/D.java b/test/960-default-smali/src/D.java
new file mode 100644
index 0000000..b1697cd
--- /dev/null
+++ b/test/960-default-smali/src/D.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class D implements Greeter3 {
+ public String GetName() {
+ return "Alex ";
+ }
+}
diff --git a/test/960-default-smali/src/E.java b/test/960-default-smali/src/E.java
new file mode 100644
index 0000000..477cb67
--- /dev/null
+++ b/test/960-default-smali/src/E.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class E extends A implements Greeter2 {
+ public String SayHi() {
+ return "Hi2 ";
+ }
+}
diff --git a/test/960-default-smali/src/Extension.java b/test/960-default-smali/src/Extension.java
new file mode 100644
index 0000000..89617dd
--- /dev/null
+++ b/test/960-default-smali/src/Extension.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Extension {
+ public default String SayHi() {
+ return "welcome ";
+ }
+}
diff --git a/test/960-default-smali/src/F.java b/test/960-default-smali/src/F.java
new file mode 100644
index 0000000..0282de7
--- /dev/null
+++ b/test/960-default-smali/src/F.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class F extends A implements Attendant {
+ public String GetPlace() {
+ return "android";
+ }
+ public String SayHiTwice() {
+ return "We can override both interfaces";
+ }
+}
diff --git a/test/960-default-smali/src/G.java b/test/960-default-smali/src/G.java
new file mode 100644
index 0000000..86a140a
--- /dev/null
+++ b/test/960-default-smali/src/G.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class G implements Attendant {
+ public String GetPlace() {
+ return "android";
+ }
+}
diff --git a/test/960-default-smali/src/Greeter.java b/test/960-default-smali/src/Greeter.java
new file mode 100644
index 0000000..cee2283
--- /dev/null
+++ b/test/960-default-smali/src/Greeter.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Greeter {
+ public String SayHi();
+ public default String SayHiTwice() {
+ return SayHi() + SayHi();
+ }
+}
diff --git a/test/960-default-smali/src/Greeter2.java b/test/960-default-smali/src/Greeter2.java
new file mode 100644
index 0000000..07f6c53
--- /dev/null
+++ b/test/960-default-smali/src/Greeter2.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Greeter2 extends Greeter {
+ public default String SayHiTwice() {
+ return "I say " + SayHi() + SayHi();
+ }
+}
diff --git a/test/960-default-smali/src/Greeter3.java b/test/960-default-smali/src/Greeter3.java
new file mode 100644
index 0000000..bbb7171
--- /dev/null
+++ b/test/960-default-smali/src/Greeter3.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Greeter3 extends Greeter {
+ public String GetName();
+ public default String SayHi() {
+ return "Hello " + GetName();
+ }
+}
diff --git a/test/960-default-smali/src/H.java b/test/960-default-smali/src/H.java
new file mode 100644
index 0000000..d87a6db
--- /dev/null
+++ b/test/960-default-smali/src/H.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class H implements Extension { }
diff --git a/test/960-default-smali/src/I.java b/test/960-default-smali/src/I.java
new file mode 100644
index 0000000..8d6779c
--- /dev/null
+++ b/test/960-default-smali/src/I.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class I extends A implements Greeter2 { }
diff --git a/test/960-default-smali/src/J.java b/test/960-default-smali/src/J.java
new file mode 100644
index 0000000..a365e40
--- /dev/null
+++ b/test/960-default-smali/src/J.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class J extends A { }
diff --git a/test/960-default-smali/smali/classes.xml b/test/960-default-smali/src/classes.xml
similarity index 100%
rename from test/960-default-smali/smali/classes.xml
rename to test/960-default-smali/src/classes.xml
diff --git a/test/961-default-iface-resolution-generated/build b/test/961-default-iface-resolution-generated/build
index 005f76c..ccebbe4 100755
--- a/test/961-default-iface-resolution-generated/build
+++ b/test/961-default-iface-resolution-generated/build
@@ -26,32 +26,19 @@
}
trap 'restore_ulimit' ERR
-mkdir -p ./smali
+if [[ $@ != *"--jvm"* ]]; then
+ # Don't do anything with jvm
+ # Hard-wired use of experimental jack.
+ # TODO: fix this temporary work-around for default-methods, see b/19467889
+ export USE_JACK=true
+fi
+
+mkdir -p ./src
# Generate the smali files and expected.txt or fail
-./util-src/generate_smali.py ./smali ./expected.txt
+./util-src/generate_java.py ./src ./expected.txt
-# Should we compile with Java source code. By default we will use Smali.
-USES_JAVA_SOURCE="false"
-if [[ $@ == *"--jvm"* ]]; then
- USES_JAVA_SOURCE="true"
-elif [[ $USE_JACK == "true" ]]; then
- if "$JACK" -D jack.java.source.version=1.8 >& /dev/null; then
- USES_JAVA_SOURCE="true"
- else
- echo "WARNING: Cannot use jack because it does not support JLS 1.8. Falling back to smali" >&2
- fi
-fi
-
-if [[ "$USES_JAVA_SOURCE" == "true" ]]; then
- # We are compiling java code, create it.
- mkdir -p src
- ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
- # Ignore the smali directory.
- EXTRA_ARGS="--no-smali"
-fi
-
-./default-build "$@" "$EXTRA_ARGS" --experimental default-methods
+./default-build "$@" --experimental default-methods
# Reset the ulimit back to its initial value
restore_ulimit
diff --git a/test/961-default-iface-resolution-generated/util-src/generate_java.py b/test/961-default-iface-resolution-generated/util-src/generate_java.py
new file mode 100755
index 0000000..a205cd6
--- /dev/null
+++ b/test/961-default-iface-resolution-generated/util-src/generate_java.py
@@ -0,0 +1,378 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Generate Java test files for test 961.
+"""
+
+import os
+import sys
+from pathlib import Path
+
+BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+if BUILD_TOP is None:
+ print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
+ sys.exit(1)
+
+# Allow us to import utils and mixins.
+sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
+
+from testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks
+import testgen.mixins as mixins
+
+from functools import total_ordering
+import itertools
+import string
+
+# The max depth the type tree can have. Includes the class object in the tree.
+# Increasing this increases the number of generated files significantly. This
+# value was chosen as it is fairly quick to run and very comprehensive, checking
+# every possible interface tree up to 5 layers deep.
+MAX_IFACE_DEPTH = 5
+
+class MainClass(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin):
+ """
+ A Main.java file containing the Main class and the main function. It will run
+ all the test functions we have.
+ """
+
+ MAIN_CLASS_TEMPLATE = """{copyright}
+class Main {{
+{test_groups}
+{main_func}
+}}
+"""
+
+ MAIN_FUNCTION_TEMPLATE = """
+ public static void main(String[] args) {{
+ {test_group_invoke}
+ }}
+"""
+
+ TEST_GROUP_INVOKE_TEMPLATE = """
+ {test_name}();
+"""
+
+ def __init__(self):
+ """
+ Initialize this MainClass. We start out with no tests.
+ """
+ self.tests = set()
+
+ def get_expected(self):
+ """
+ Get the expected output of this test.
+ """
+ all_tests = sorted(self.tests)
+ return filter_blanks("\n".join(a.get_expected() for a in all_tests))
+
+ def add_test(self, ty):
+ """
+ Add a test for the concrete type 'ty'
+ """
+ self.tests.add(Func(ty))
+
+ def get_name(self):
+ """
+ Get the name of this class
+ """
+ return "Main"
+
+ def __str__(self):
+ """
+ Print the MainClass java code.
+ """
+ all_tests = sorted(self.tests)
+ test_invoke = ""
+ test_groups = ""
+ for t in all_tests:
+ test_groups += str(t)
+ for t in all_tests:
+ test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
+ main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)
+
+ return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright("java"),
+ test_groups = test_groups,
+ main_func = main_func)
+
+class Func(mixins.Named, mixins.NameComparableMixin):
+ """
+ A function that tests the functionality of a concrete type. Should only be
+ constructed by MainClass.add_test.
+ """
+
+ TEST_FUNCTION_TEMPLATE = """
+ public static void {fname}() {{
+ try {{
+ {farg} v = new {farg}();
+ System.out.printf("%s calls default method on %s\\n",
+ v.CalledClassName(),
+ v.CalledInterfaceName());
+ return;
+ }} catch (Error e) {{
+ e.printStackTrace(System.out);
+ return;
+ }}
+ }}
+"""
+
+ def __init__(self, farg):
+ """
+ Initialize a test function for the given argument
+ """
+ self.farg = farg
+
+ def get_expected(self):
+ """
+ Get the expected output calling this function.
+ """
+ return "{tree} calls default method on {iface_tree}".format(
+ tree = self.farg.get_tree(), iface_tree = self.farg.get_called().get_tree())
+
+ def get_name(self):
+ """
+ Get the name of this function
+ """
+ return "TEST_FUNC_{}".format(self.farg.get_name())
+
+ def __str__(self):
+ """
+ Print the java code of this function.
+ """
+ return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(), farg=self.farg.get_name())
+
+class TestClass(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.JavaFileMixin):
+ """
+ A class that will be instantiated to test default method resolution order.
+ """
+
+ TEST_CLASS_TEMPLATE = """{copyright}
+public class {class_name} implements {iface_name} {{
+ public String CalledClassName() {{
+ return "{tree}";
+ }}
+}}
+"""
+
+ def __init__(self, iface):
+ """
+ Initialize this test class which implements the given interface
+ """
+ self.iface = iface
+ self.class_name = "CLASS_"+gensym()
+
+ def get_name(self):
+ """
+ Get the name of this class
+ """
+ return self.class_name
+
+ def get_tree(self):
+ """
+ Print out a representation of the type tree of this class
+ """
+ return "[{class_name} {iface_tree}]".format(class_name = self.class_name,
+ iface_tree = self.iface.get_tree())
+
+ def __iter__(self):
+ """
+ Step through all interfaces implemented transitively by this class
+ """
+ yield self.iface
+ yield from self.iface
+
+ def get_called(self):
+ """
+ Get the interface whose default method would be called when calling the
+ CalledInterfaceName function.
+ """
+ all_ifaces = set(iface for iface in self if iface.default)
+ for i in all_ifaces:
+ if all(map(lambda j: i not in j.get_super_types(), all_ifaces)):
+ return i
+ raise Exception("UNREACHABLE! Unable to find default method!")
+
+ def __str__(self):
+ """
+ Print the java code of this class.
+ """
+ return self.TEST_CLASS_TEMPLATE.format(copyright = get_copyright('java'),
+ iface_name = self.iface.get_name(),
+ tree = self.get_tree(),
+ class_name = self.class_name)
+
+class TestInterface(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.JavaFileMixin):
+ """
+ An interface that will be used to test default method resolution order.
+ """
+
+ TEST_INTERFACE_TEMPLATE = """{copyright}
+public interface {class_name} {extends} {ifaces} {{
+ public String CalledClassName();
+
+{funcs}
+}}
+"""
+
+ DEFAULT_FUNC_TEMPLATE = """
+ public default String CalledInterfaceName() {{
+ return "{tree}";
+ }}
+"""
+
+ def __init__(self, ifaces, default):
+ """
+ Initialize interface with the given super-interfaces
+ """
+ self.ifaces = sorted(ifaces)
+ self.default = default
+ end = "_DEFAULT" if default else ""
+ self.class_name = "INTERFACE_"+gensym()+end
+
+ def get_super_types(self):
+ """
+ Returns a set of all the supertypes of this interface
+ """
+ return set(i2 for i2 in self)
+
+ def get_name(self):
+ """
+ Get the name of this class
+ """
+ return self.class_name
+
+ def get_tree(self):
+ """
+ Print out a representation of the type tree of this class
+ """
+ return "[{class_name} {iftree}]".format(class_name = self.get_name(),
+ iftree = print_tree(self.ifaces))
+
+ def __iter__(self):
+ """
+ Performs depth-first traversal of the interface tree this interface is the
+ root of. Does not filter out repeats.
+ """
+ for i in self.ifaces:
+ yield i
+ yield from i
+
+ def __str__(self):
+ """
+ Print the java code of this interface.
+ """
+ j_ifaces = " "
+ for i in self.ifaces:
+ j_ifaces += " {},".format(i.get_name())
+ j_ifaces = j_ifaces[0:-1]
+ if self.default:
+ funcs = self.DEFAULT_FUNC_TEMPLATE.format(ifaces = j_ifaces,
+ tree = self.get_tree(),
+ class_name = self.class_name)
+ else:
+ funcs = ""
+ return self.TEST_INTERFACE_TEMPLATE.format(copyright = get_copyright('java'),
+ extends = "extends" if len(self.ifaces) else "",
+ ifaces = j_ifaces,
+ funcs = funcs,
+ tree = self.get_tree(),
+ class_name = self.class_name)
+
+def print_tree(ifaces):
+ """
+ Prints a list of iface trees
+ """
+ return " ".join(i.get_tree() for i in ifaces)
+
+# The deduplicated output of subtree_sizes for each size up to
+# MAX_LEAF_IFACE_PER_OBJECT.
+SUBTREES = [set(tuple(sorted(l)) for l in subtree_sizes(i))
+ for i in range(MAX_IFACE_DEPTH + 1)]
+
+def create_interface_trees():
+ """
+ Return all legal interface trees
+ """
+ def dump_supers(s):
+ """
+ Does depth first traversal of all the interfaces in the list.
+ """
+ for i in s:
+ yield i
+ yield from i
+
+ def create_interface_trees_inner(num, allow_default):
+ for split in SUBTREES[num]:
+ ifaces = []
+ for sub in split:
+ if sub == 1:
+ ifaces.append([TestInterface([], allow_default)])
+ if allow_default:
+ ifaces[-1].append(TestInterface([], False))
+ else:
+ ifaces.append(list(create_interface_trees_inner(sub, allow_default)))
+ for supers in itertools.product(*ifaces):
+ all_supers = sorted(set(dump_supers(supers)) - set(supers))
+ for i in range(len(all_supers) + 1):
+ for combo in itertools.combinations(all_supers, i):
+ yield TestInterface(list(combo) + list(supers), allow_default)
+ if allow_default:
+ for i in range(len(split)):
+ ifaces = []
+ for sub, cs in zip(split, itertools.count()):
+ if sub == 1:
+ ifaces.append([TestInterface([], i == cs)])
+ else:
+ ifaces.append(list(create_interface_trees_inner(sub, i == cs)))
+ for supers in itertools.product(*ifaces):
+ all_supers = sorted(set(dump_supers(supers)) - set(supers))
+ for i in range(len(all_supers) + 1):
+ for combo in itertools.combinations(all_supers, i):
+ yield TestInterface(list(combo) + list(supers), False)
+
+ for num in range(1, MAX_IFACE_DEPTH):
+ yield from create_interface_trees_inner(num, True)
+
+def create_all_test_files():
+ """
+ Creates all the objects representing the files in this test. They just need to
+ be dumped.
+ """
+ mc = MainClass()
+ classes = {mc}
+ for tree in create_interface_trees():
+ classes.add(tree)
+ for i in tree:
+ classes.add(i)
+ test_class = TestClass(tree)
+ mc.add_test(test_class)
+ classes.add(test_class)
+ return mc, classes
+
+def main(argv):
+ java_dir = Path(argv[1])
+ if not java_dir.exists() or not java_dir.is_dir():
+ print("{} is not a valid java dir".format(java_dir), file=sys.stderr)
+ sys.exit(1)
+ expected_txt = Path(argv[2])
+ mainclass, all_files = create_all_test_files()
+ with expected_txt.open('w') as out:
+ print(mainclass.get_expected(), file=out)
+ for f in all_files:
+ f.dump(java_dir)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/test/961-default-iface-resolution-generated/util-src/generate_smali.py b/test/961-default-iface-resolution-generated/util-src/generate_smali.py
deleted file mode 100755
index 921a096..0000000
--- a/test/961-default-iface-resolution-generated/util-src/generate_smali.py
+++ /dev/null
@@ -1,466 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Generate Smali test files for test 961.
-"""
-
-import os
-import sys
-from pathlib import Path
-
-BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
-if BUILD_TOP is None:
- print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
- sys.exit(1)
-
-# Allow us to import utils and mixins.
-sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
-
-from testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks
-import testgen.mixins as mixins
-
-from functools import total_ordering
-import itertools
-import string
-
-# The max depth the type tree can have. Includes the class object in the tree.
-# Increasing this increases the number of generated files significantly. This
-# value was chosen as it is fairly quick to run and very comprehensive, checking
-# every possible interface tree up to 5 layers deep.
-MAX_IFACE_DEPTH = 5
-
-class MainClass(mixins.DumpMixin, mixins.Named, mixins.SmaliFileMixin):
- """
- A Main.smali file containing the Main class and the main function. It will run
- all the test functions we have.
- """
-
- MAIN_CLASS_TEMPLATE = """{copyright}
-
-.class public LMain;
-.super Ljava/lang/Object;
-
-# class Main {{
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-{test_groups}
-
-{main_func}
-
-# }}
-"""
-
- MAIN_FUNCTION_TEMPLATE = """
-# public static void main(String[] args) {{
-.method public static main([Ljava/lang/String;)V
- .locals 2
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
-
- {test_group_invoke}
-
- return-void
-.end method
-# }}
-"""
-
- TEST_GROUP_INVOKE_TEMPLATE = """
-# {test_name}();
- invoke-static {{}}, {test_name}()V
-"""
-
- def __init__(self):
- """
- Initialize this MainClass. We start out with no tests.
- """
- self.tests = set()
-
- def get_expected(self):
- """
- Get the expected output of this test.
- """
- all_tests = sorted(self.tests)
- return filter_blanks("\n".join(a.get_expected() for a in all_tests))
-
- def add_test(self, ty):
- """
- Add a test for the concrete type 'ty'
- """
- self.tests.add(Func(ty))
-
- def get_name(self):
- """
- Get the name of this class
- """
- return "Main"
-
- def __str__(self):
- """
- Print the MainClass smali code.
- """
- all_tests = sorted(self.tests)
- test_invoke = ""
- test_groups = ""
- for t in all_tests:
- test_groups += str(t)
- for t in all_tests:
- test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
- main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)
-
- return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright("smali"),
- test_groups = test_groups,
- main_func = main_func)
-
-class Func(mixins.Named, mixins.NameComparableMixin):
- """
- A function that tests the functionality of a concrete type. Should only be
- constructed by MainClass.add_test.
- """
-
- TEST_FUNCTION_TEMPLATE = """
-# public static void {fname}() {{
-# try {{
-# {farg} v = new {farg}();
-# System.out.printf("%s calls default method on %s\\n",
-# v.CalledClassName(),
-# v.CalledInterfaceName());
-# return;
-# }} catch (Error e) {{
-# e.printStackTrace(System.out);
-# return;
-# }}
-# }}
-.method public static {fname}()V
- .locals 7
- :call_{fname}_try_start
- new-instance v6, L{farg};
- invoke-direct {{v6}}, L{farg};-><init>()V
-
- const/4 v0, 2
- new-array v1,v0, [Ljava/lang/Object;
- const/4 v0, 0
- invoke-virtual {{v6}}, L{farg};->CalledClassName()Ljava/lang/String;
- move-result-object v4
- aput-object v4,v1,v0
-
- sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v3, "%s calls default method on %s\\n"
-
- invoke-virtual {{v6}}, L{farg};->CalledInterfaceName()Ljava/lang/String;
- move-result-object v4
- const/4 v0, 1
- aput-object v4, v1, v0
-
- invoke-virtual {{v2,v3,v1}}, Ljava/io/PrintStream;->printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
- return-void
- :call_{fname}_try_end
- .catch Ljava/lang/Error; {{:call_{fname}_try_start .. :call_{fname}_try_end}} :error_{fname}_start
- :error_{fname}_start
- move-exception v3
- sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
- invoke-virtual {{v3,v2}}, Ljava/lang/Error;->printStackTrace(Ljava/io/PrintStream;)V
- return-void
-.end method
-"""
-
- def __init__(self, farg):
- """
- Initialize a test function for the given argument
- """
- self.farg = farg
-
- def get_expected(self):
- """
- Get the expected output calling this function.
- """
- return "{tree} calls default method on {iface_tree}".format(
- tree = self.farg.get_tree(), iface_tree = self.farg.get_called().get_tree())
-
- def get_name(self):
- """
- Get the name of this function
- """
- return "TEST_FUNC_{}".format(self.farg.get_name())
-
- def __str__(self):
- """
- Print the smali code of this function.
- """
- return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(), farg=self.farg.get_name())
-
-class TestClass(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin):
- """
- A class that will be instantiated to test default method resolution order.
- """
-
- TEST_CLASS_TEMPLATE = """{copyright}
-
-.class public L{class_name};
-.super Ljava/lang/Object;
-.implements L{iface_name};
-
-# public class {class_name} implements {iface_name} {{
-# public String CalledClassName() {{
-# return "{tree}";
-# }}
-# }}
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public CalledClassName()Ljava/lang/String;
- .locals 1
- const-string v0, "{tree}"
- return-object v0
-.end method
-"""
-
- def __init__(self, iface):
- """
- Initialize this test class which implements the given interface
- """
- self.iface = iface
- self.class_name = "CLASS_"+gensym()
-
- def get_name(self):
- """
- Get the name of this class
- """
- return self.class_name
-
- def get_tree(self):
- """
- Print out a representation of the type tree of this class
- """
- return "[{class_name} {iface_tree}]".format(class_name = self.class_name,
- iface_tree = self.iface.get_tree())
-
- def __iter__(self):
- """
- Step through all interfaces implemented transitively by this class
- """
- yield self.iface
- yield from self.iface
-
- def get_called(self):
- """
- Get the interface whose default method would be called when calling the
- CalledInterfaceName function.
- """
- all_ifaces = set(iface for iface in self if iface.default)
- for i in all_ifaces:
- if all(map(lambda j: i not in j.get_super_types(), all_ifaces)):
- return i
- raise Exception("UNREACHABLE! Unable to find default method!")
-
- def __str__(self):
- """
- Print the smali code of this class.
- """
- return self.TEST_CLASS_TEMPLATE.format(copyright = get_copyright('smali'),
- iface_name = self.iface.get_name(),
- tree = self.get_tree(),
- class_name = self.class_name)
-
-class TestInterface(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin):
- """
- An interface that will be used to test default method resolution order.
- """
-
- TEST_INTERFACE_TEMPLATE = """{copyright}
-.class public abstract interface L{class_name};
-.super Ljava/lang/Object;
-{implements_spec}
-
-# public interface {class_name} {extends} {ifaces} {{
-# public String CalledClassName();
-.method public abstract CalledClassName()Ljava/lang/String;
-.end method
-
-{funcs}
-
-# }}
-"""
-
- DEFAULT_FUNC_TEMPLATE = """
-# public default String CalledInterfaceName() {{
-# return "{tree}";
-# }}
-.method public CalledInterfaceName()Ljava/lang/String;
- .locals 1
- const-string v0, "{tree}"
- return-object v0
-.end method
-"""
-
- IMPLEMENTS_TEMPLATE = """
-.implements L{iface_name};
-"""
-
- def __init__(self, ifaces, default):
- """
- Initialize interface with the given super-interfaces
- """
- self.ifaces = sorted(ifaces)
- self.default = default
- end = "_DEFAULT" if default else ""
- self.class_name = "INTERFACE_"+gensym()+end
-
- def get_super_types(self):
- """
- Returns a set of all the supertypes of this interface
- """
- return set(i2 for i2 in self)
-
- def get_name(self):
- """
- Get the name of this class
- """
- return self.class_name
-
- def get_tree(self):
- """
- Print out a representation of the type tree of this class
- """
- return "[{class_name} {iftree}]".format(class_name = self.get_name(),
- iftree = print_tree(self.ifaces))
-
- def __iter__(self):
- """
- Performs depth-first traversal of the interface tree this interface is the
- root of. Does not filter out repeats.
- """
- for i in self.ifaces:
- yield i
- yield from i
-
- def __str__(self):
- """
- Print the smali code of this interface.
- """
- s_ifaces = " "
- j_ifaces = " "
- for i in self.ifaces:
- s_ifaces += self.IMPLEMENTS_TEMPLATE.format(iface_name = i.get_name())
- j_ifaces += " {},".format(i.get_name())
- j_ifaces = j_ifaces[0:-1]
- if self.default:
- funcs = self.DEFAULT_FUNC_TEMPLATE.format(ifaces = j_ifaces,
- tree = self.get_tree(),
- class_name = self.class_name)
- else:
- funcs = ""
- return self.TEST_INTERFACE_TEMPLATE.format(copyright = get_copyright('smali'),
- implements_spec = s_ifaces,
- extends = "extends" if len(self.ifaces) else "",
- ifaces = j_ifaces,
- funcs = funcs,
- tree = self.get_tree(),
- class_name = self.class_name)
-
-def print_tree(ifaces):
- """
- Prints a list of iface trees
- """
- return " ".join(i.get_tree() for i in ifaces)
-
-# The deduplicated output of subtree_sizes for each size up to
-# MAX_LEAF_IFACE_PER_OBJECT.
-SUBTREES = [set(tuple(sorted(l)) for l in subtree_sizes(i))
- for i in range(MAX_IFACE_DEPTH + 1)]
-
-def create_interface_trees():
- """
- Return all legal interface trees
- """
- def dump_supers(s):
- """
- Does depth first traversal of all the interfaces in the list.
- """
- for i in s:
- yield i
- yield from i
-
- def create_interface_trees_inner(num, allow_default):
- for split in SUBTREES[num]:
- ifaces = []
- for sub in split:
- if sub == 1:
- ifaces.append([TestInterface([], allow_default)])
- if allow_default:
- ifaces[-1].append(TestInterface([], False))
- else:
- ifaces.append(list(create_interface_trees_inner(sub, allow_default)))
- for supers in itertools.product(*ifaces):
- all_supers = sorted(set(dump_supers(supers)) - set(supers))
- for i in range(len(all_supers) + 1):
- for combo in itertools.combinations(all_supers, i):
- yield TestInterface(list(combo) + list(supers), allow_default)
- if allow_default:
- for i in range(len(split)):
- ifaces = []
- for sub, cs in zip(split, itertools.count()):
- if sub == 1:
- ifaces.append([TestInterface([], i == cs)])
- else:
- ifaces.append(list(create_interface_trees_inner(sub, i == cs)))
- for supers in itertools.product(*ifaces):
- all_supers = sorted(set(dump_supers(supers)) - set(supers))
- for i in range(len(all_supers) + 1):
- for combo in itertools.combinations(all_supers, i):
- yield TestInterface(list(combo) + list(supers), False)
-
- for num in range(1, MAX_IFACE_DEPTH):
- yield from create_interface_trees_inner(num, True)
-
-def create_all_test_files():
- """
- Creates all the objects representing the files in this test. They just need to
- be dumped.
- """
- mc = MainClass()
- classes = {mc}
- for tree in create_interface_trees():
- classes.add(tree)
- for i in tree:
- classes.add(i)
- test_class = TestClass(tree)
- mc.add_test(test_class)
- classes.add(test_class)
- return mc, classes
-
-def main(argv):
- smali_dir = Path(argv[1])
- if not smali_dir.exists() or not smali_dir.is_dir():
- print("{} is not a valid smali dir".format(smali_dir), file=sys.stderr)
- sys.exit(1)
- expected_txt = Path(argv[2])
- mainclass, all_files = create_all_test_files()
- with expected_txt.open('w') as out:
- print(mainclass.get_expected(), file=out)
- for f in all_files:
- f.dump(smali_dir)
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/test/962-iface-static/build b/test/962-iface-static/build
index e17272f..0dd8573 100755
--- a/test/962-iface-static/build
+++ b/test/962-iface-static/build
@@ -17,24 +17,11 @@
# make us exit on a failure
set -e
-# Should we compile with Java source code. By default we will use Smali.
-USES_JAVA_SOURCE="false"
-if [[ $@ == *"--jvm"* ]]; then
- USES_JAVA_SOURCE="true"
-elif [[ "$USE_JACK" == "true" ]]; then
- if $JACK -D jack.java.source.version=1.8 2>/dev/null; then
- USES_JAVA_SOURCE="true"
- else
- echo "WARNING: Cannot use jack because it does not support JLS 1.8. Falling back to smali" >&2
- fi
+if [[ $@ != *"--jvm"* ]]; then
+ # Don't do anything with jvm
+ # Hard-wired use of experimental jack.
+ # TODO: fix this temporary work-around for default-methods, see b/19467889
+ export USE_JACK=true
fi
-if [[ "$USES_JAVA_SOURCE" == "true" ]]; then
- # We are compiling java code, create it.
- mkdir -p src
- ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
- # Ignore the smali directory.
- EXTRA_ARGS="--no-smali"
-fi
-
-./default-build "$@" "$EXTRA_ARGS" --experimental default-methods
+./default-build "$@" --experimental default-methods
diff --git a/test/962-iface-static/smali/Displayer.smali b/test/962-iface-static/smali/Displayer.smali
deleted file mode 100644
index ed4c013..0000000
--- a/test/962-iface-static/smali/Displayer.smali
+++ /dev/null
@@ -1,45 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public class Displayer {
-# static {
-# System.out.println("init");
-# }
-#
-# public Displayer() {
-# System.out.println("constructor");
-# }
-# }
-
-.class public LDisplayer;
-.super Ljava/lang/Object;
-
-.method static constructor <clinit>()V
- .locals 3
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "init"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- return-void
-.end method
-
-.method public constructor <init>()V
- .locals 2
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "constructor"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- return-void
-.end method
diff --git a/test/962-iface-static/smali/Main.smali b/test/962-iface-static/smali/Main.smali
deleted file mode 100644
index 72fa5e0..0000000
--- a/test/962-iface-static/smali/Main.smali
+++ /dev/null
@@ -1,40 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# class Main {
-# public static void main(String[] args) {
-# System.out.println(iface.SayHi());
-# }
-# }
-.class public LMain;
-.super Ljava/lang/Object;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public static main([Ljava/lang/String;)V
- .locals 2
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
-
- invoke-static {}, Liface;->SayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- return-void
-.end method
diff --git a/test/962-iface-static/smali/iface.smali b/test/962-iface-static/smali/iface.smali
deleted file mode 100644
index 5b9c03e..0000000
--- a/test/962-iface-static/smali/iface.smali
+++ /dev/null
@@ -1,43 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface iface {
-# public static final Displayer f = new Displayer();
-#
-# public static String SayHi() {
-# return "Hello";
-# }
-# }
-
-.class public abstract interface Liface;
-.super Ljava/lang/Object;
-
-.field public final static f:LDisplayer;
-
-.method static constructor <clinit>()V
- .locals 3
- new-instance v1, LDisplayer;
- invoke-direct {v1}, LDisplayer;-><init>()V
- sput-object v1, Liface;->f:LDisplayer;
- return-void
-.end method
-
-.method public static SayHi()Ljava/lang/String;
- .locals 1
- const-string v0, "Hello"
- return-object v0
-.end method
-
diff --git a/test/962-iface-static/src/Displayer.java b/test/962-iface-static/src/Displayer.java
new file mode 100644
index 0000000..5b28b3f
--- /dev/null
+++ b/test/962-iface-static/src/Displayer.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class Displayer {
+ static {
+ System.out.println("init");
+ }
+ public Displayer() {
+ System.out.println("constructor");
+ }
+}
diff --git a/test/962-iface-static/src/Iface.java b/test/962-iface-static/src/Iface.java
new file mode 100644
index 0000000..82c7808
--- /dev/null
+++ b/test/962-iface-static/src/Iface.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface {
+ public static final Displayer f = new Displayer();
+ public static String SayHi() {
+ return "Hello";
+ }
+}
diff --git a/test/962-iface-static/src/Main.java b/test/962-iface-static/src/Main.java
new file mode 100644
index 0000000..7cb8eb7
--- /dev/null
+++ b/test/962-iface-static/src/Main.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class Main {
+ public static void main(String[] args) {
+ System.out.println(Iface.SayHi());
+ }
+}
diff --git a/test/963-default-range-smali/build b/test/963-default-range-smali/build
index e17272f..0dd8573 100755
--- a/test/963-default-range-smali/build
+++ b/test/963-default-range-smali/build
@@ -17,24 +17,11 @@
# make us exit on a failure
set -e
-# Should we compile with Java source code. By default we will use Smali.
-USES_JAVA_SOURCE="false"
-if [[ $@ == *"--jvm"* ]]; then
- USES_JAVA_SOURCE="true"
-elif [[ "$USE_JACK" == "true" ]]; then
- if $JACK -D jack.java.source.version=1.8 2>/dev/null; then
- USES_JAVA_SOURCE="true"
- else
- echo "WARNING: Cannot use jack because it does not support JLS 1.8. Falling back to smali" >&2
- fi
+if [[ $@ != *"--jvm"* ]]; then
+ # Don't do anything with jvm
+ # Hard-wired use of experimental jack.
+ # TODO: fix this temporary work-around for default-methods, see b/19467889
+ export USE_JACK=true
fi
-if [[ "$USES_JAVA_SOURCE" == "true" ]]; then
- # We are compiling java code, create it.
- mkdir -p src
- ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
- # Ignore the smali directory.
- EXTRA_ARGS="--no-smali"
-fi
-
-./default-build "$@" "$EXTRA_ARGS" --experimental default-methods
+./default-build "$@" --experimental default-methods
diff --git a/test/963-default-range-smali/smali/A.smali b/test/963-default-range-smali/smali/A.smali
deleted file mode 100644
index b3d91dd..0000000
--- a/test/963-default-range-smali/smali/A.smali
+++ /dev/null
@@ -1,29 +0,0 @@
-# /*
-# * Copyright 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-
-.class public LA;
-.super Ljava/lang/Object;
-.implements Liface;
-
-# class A implements iface {
-# }
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
diff --git a/test/963-default-range-smali/smali/Main.smali b/test/963-default-range-smali/smali/Main.smali
deleted file mode 100644
index 400fba7..0000000
--- a/test/963-default-range-smali/smali/Main.smali
+++ /dev/null
@@ -1,77 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# class Main {
-# public static void main(String[] args) {
-# A a = new A();
-# System.out.println(a.SayHi("a string 0",
-# "a string 1",
-# "a string 2",
-# "a string 3",
-# "a string 4",
-# "a string 5",
-# "a string 6",
-# "a string 7",
-# "a string 8",
-# "a string 9"));
-# iface b = (iface)a;
-# System.out.println(b.SayHi("a string 0",
-# "a string 1",
-# "a string 2",
-# "a string 3",
-# "a string 4",
-# "a string 5",
-# "a string 6",
-# "a string 7",
-# "a string 8",
-# "a string 9"));
-# }
-# }
-.class public LMain;
-.super Ljava/lang/Object;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public static main([Ljava/lang/String;)V
- .locals 15
- sget-object v12, Ljava/lang/System;->out:Ljava/io/PrintStream;
-
- new-instance v1, LA;
- invoke-direct {v1}, LA;-><init>()V
- const-string v2, "a string 0"
- const-string v3, "a string 1"
- const-string v4, "a string 2"
- const-string v5, "a string 3"
- const-string v6, "a string 4"
- const-string v7, "a string 5"
- const-string v8, "a string 6"
- const-string v9, "a string 7"
- const-string v10, "a string 8"
- const-string v11, "a string 9"
- invoke-virtual/range {v1 .. v11}, LA;->SayHi(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v12,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-interface/range {v1 .. v11}, Liface;->SayHi(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v12,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- return-void
-.end method
diff --git a/test/963-default-range-smali/smali/iface.smali b/test/963-default-range-smali/smali/iface.smali
deleted file mode 100644
index c2c3ce6..0000000
--- a/test/963-default-range-smali/smali/iface.smali
+++ /dev/null
@@ -1,40 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface iface {
-# public default String SayHi(String n1,
-# String n2,
-# String n3,
-# String n4,
-# String n5,
-# String n6,
-# String n7,
-# String n8,
-# String n9,
-# String n0) {
-# return "Hello";
-# }
-# }
-
-.class public abstract interface Liface;
-.super Ljava/lang/Object;
-
-.method public SayHi(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
- .locals 1
- const-string v0, "Hello"
- return-object v0
-.end method
-
diff --git a/test/963-default-range-smali/src/A.java b/test/963-default-range-smali/src/A.java
new file mode 100644
index 0000000..617eccb
--- /dev/null
+++ b/test/963-default-range-smali/src/A.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class A implements Iface { }
diff --git a/test/963-default-range-smali/src/Iface.java b/test/963-default-range-smali/src/Iface.java
new file mode 100644
index 0000000..7556209
--- /dev/null
+++ b/test/963-default-range-smali/src/Iface.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface {
+ public default String SayHi(String n1,
+ String n2,
+ String n3,
+ String n4,
+ String n5,
+ String n6,
+ String n7,
+ String n8,
+ String n9,
+ String n0) {
+ return "Hello";
+ }
+}
diff --git a/test/963-default-range-smali/src/Main.java b/test/963-default-range-smali/src/Main.java
new file mode 100644
index 0000000..841842d
--- /dev/null
+++ b/test/963-default-range-smali/src/Main.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class Main {
+ public static void main(String[] args) {
+ A a = new A();
+ System.out.println(a.SayHi("a string 0",
+ "a string 1",
+ "a string 2",
+ "a string 3",
+ "a string 4",
+ "a string 5",
+ "a string 6",
+ "a string 7",
+ "a string 8",
+ "a string 9"));
+ Iface b = a;
+ System.out.println(b.SayHi("a string 0",
+ "a string 1",
+ "a string 2",
+ "a string 3",
+ "a string 4",
+ "a string 5",
+ "a string 6",
+ "a string 7",
+ "a string 8",
+ "a string 9"));
+ }
+}
diff --git a/test/964-default-iface-init-generated/build b/test/964-default-iface-init-generated/build
index 0780da1..ccebbe4 100755
--- a/test/964-default-iface-init-generated/build
+++ b/test/964-default-iface-init-generated/build
@@ -26,30 +26,19 @@
}
trap 'restore_ulimit' ERR
+if [[ $@ != *"--jvm"* ]]; then
+ # Don't do anything with jvm
+ # Hard-wired use of experimental jack.
+ # TODO: fix this temporary work-around for default-methods, see b/19467889
+ export USE_JACK=true
+fi
+
+mkdir -p ./src
+
# Generate the smali files and expected.txt or fail
-./util-src/generate_smali.py ./smali ./expected.txt
+./util-src/generate_java.py ./src ./expected.txt
-# Should we compile with Java source code. By default we will use Smali.
-USES_JAVA_SOURCE="false"
-if [[ $@ == *"--jvm"* ]]; then
- USES_JAVA_SOURCE="true"
-elif [[ "$USE_JACK" == "true" ]]; then
- if $JACK -D jack.java.source.version=1.8 2>/dev/null; then
- USES_JAVA_SOURCE="true"
- else
- echo "WARNING: Cannot use jack because it does not support JLS 1.8. Falling back to smali" >&2
- fi
-fi
-
-if [[ "$USES_JAVA_SOURCE" == "true" ]]; then
- # We are compiling java code, create it.
- mkdir -p src
- ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
- # Ignore the smali directory.
- EXTRA_ARGS="--no-smali"
-fi
-
-./default-build "$@" "$EXTRA_ARGS" --experimental default-methods
+./default-build "$@" --experimental default-methods
# Reset the ulimit back to its initial value
restore_ulimit
diff --git a/test/964-default-iface-init-generated/smali/Displayer.smali b/test/964-default-iface-init-generated/smali/Displayer.smali
deleted file mode 100644
index 91280a8..0000000
--- a/test/964-default-iface-init-generated/smali/Displayer.smali
+++ /dev/null
@@ -1,45 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# // This class is b/c java does not allow static {} blocks in interfaces.
-# public class Displayer {
-# public Displayer(String type) {
-# System.out.println("initialization of " + type);
-# }
-# public void touch() {
-# return;
-# }
-# }
-
-.class public LDisplayer;
-.super Ljava/lang/Object;
-
-.method public constructor <init>(Ljava/lang/String;)V
- .locals 2
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- const-string v0, "initialization of "
- invoke-virtual {v0, p1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- return-void
-.end method
-
-.method public touch()V
- .locals 0
- return-void
-.end method
-
diff --git a/test/964-default-iface-init-generated/src/Displayer.java b/test/964-default-iface-init-generated/src/Displayer.java
new file mode 100644
index 0000000..4be0ab2
--- /dev/null
+++ b/test/964-default-iface-init-generated/src/Displayer.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// This class is b/c java does not allow static {} blocks in interfaces.
+public class Displayer {
+ public Displayer(String type) {
+ System.out.println("initialization of " + type);
+ }
+ public void touch() {
+ return;
+ }
+}
diff --git a/test/964-default-iface-init-generated/util-src/generate_java.py b/test/964-default-iface-init-generated/util-src/generate_java.py
new file mode 100755
index 0000000..b2df49f
--- /dev/null
+++ b/test/964-default-iface-init-generated/util-src/generate_java.py
@@ -0,0 +1,419 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Generate java test files for test 964.
+"""
+
+import os
+import sys
+from pathlib import Path
+
+BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+if BUILD_TOP is None:
+ print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
+ sys.exit(1)
+
+# Allow us to import utils and mixins.
+sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
+
+from testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks
+import testgen.mixins as mixins
+
+from functools import total_ordering
+import itertools
+import string
+
+# The max depth the tree can have.
+MAX_IFACE_DEPTH = 3
+
+class MainClass(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin):
+ """
+ A Main.java file containing the Main class and the main function. It will run
+ all the test functions we have.
+ """
+
+ MAIN_CLASS_TEMPLATE = """{copyright}
+class Main {{
+{test_groups}
+{main_func}
+}}
+"""
+
+ MAIN_FUNCTION_TEMPLATE = """
+ public static void main(String[] args) {{
+ {test_group_invoke}
+ }}
+"""
+
+ TEST_GROUP_INVOKE_TEMPLATE = """
+ {test_name}();
+"""
+
+ def __init__(self):
+ """
+ Initialize this MainClass. We start out with no tests.
+ """
+ self.tests = set()
+
+ def add_test(self, ty):
+ """
+ Add a test for the concrete type 'ty'
+ """
+ self.tests.add(Func(ty))
+
+ def get_expected(self):
+ """
+ Get the expected output of this test.
+ """
+ all_tests = sorted(self.tests)
+ return filter_blanks("\n".join(a.get_expected() for a in all_tests))
+
+ def get_name(self):
+ """
+ Gets the name of this class
+ """
+ return "Main"
+
+ def __str__(self):
+ """
+ Print the java code for this test.
+ """
+ all_tests = sorted(self.tests)
+ test_invoke = ""
+ test_groups = ""
+ for t in all_tests:
+ test_groups += str(t)
+ for t in all_tests:
+ test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
+ main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)
+
+ return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright('java'),
+ test_groups = test_groups,
+ main_func = main_func)
+
+class Func(mixins.Named, mixins.NameComparableMixin):
+ """
+ A function that tests the functionality of a concrete type. Should only be
+ constructed by MainClass.add_test.
+ """
+
+ TEST_FUNCTION_TEMPLATE = """
+ public static void {fname}() {{
+ try {{
+ System.out.println("About to initialize {tree}");
+ {farg} v = new {farg}();
+ System.out.println("Initialized {tree}");
+ v.touchAll();
+ System.out.println("All of {tree} hierarchy initialized");
+ return;
+ }} catch (Error e) {{
+ e.printStackTrace(System.out);
+ return;
+ }}
+ }}
+"""
+
+ OUTPUT_FORMAT = """
+About to initialize {tree}
+{initialize_output}
+Initialized {tree}
+{touch_output}
+All of {tree} hierarchy initialized
+""".strip()
+
+ def __init__(self, farg):
+ """
+ Initialize a test function for the given argument
+ """
+ self.farg = farg
+
+ def __str__(self):
+ """
+ Print the java code for this test function.
+ """
+ return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(),
+ farg=self.farg.get_name(),
+ tree = self.farg.get_tree())
+
+ def get_name(self):
+ """
+ Gets the name of this test function
+ """
+ return "TEST_FUNC_{}".format(self.farg.get_name())
+
+ def get_expected(self):
+ """
+ Get the expected output of this function.
+ """
+ return self.OUTPUT_FORMAT.format(
+ tree = self.farg.get_tree(),
+ initialize_output = self.farg.get_initialize_output().strip(),
+ touch_output = self.farg.get_touch_output().strip())
+
+class TestClass(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.JavaFileMixin):
+ """
+ A class that will be instantiated to test interface initialization order.
+ """
+
+ TEST_CLASS_TEMPLATE = """{copyright}
+public class {class_name} implements {ifaces} {{
+ public void marker() {{
+ return;
+ }}
+
+ public void touchAll() {{
+{touch_calls}
+ }}
+}}
+"""
+
+ TOUCH_CALL_TEMPLATE = """
+ System.out.println("{class_name} touching {iface_name}");
+ {iface_name}.field.touch();
+"""
+
+ TOUCH_OUTPUT_TEMPLATE = """
+{class_name} touching {iface_name}
+{touch_output}
+""".strip()
+
+ def __init__(self, ifaces):
+ """
+ Initialize this test class which implements the given interfaces
+ """
+ self.ifaces = ifaces
+ self.class_name = "CLASS_"+gensym()
+
+ def get_name(self):
+ """
+ Gets the name of this interface
+ """
+ return self.class_name
+
+ def get_tree(self):
+ """
+ Print out a representation of the type tree of this class
+ """
+ return "[{fname} {iftree}]".format(fname = self.get_name(), iftree = print_tree(self.ifaces))
+
+ def get_initialize_output(self):
+ return "\n".join(map(lambda i: i.get_initialize_output().strip(), dump_tree(self.ifaces)))
+
+ def get_touch_output(self):
+ return "\n".join(map(lambda a: self.TOUCH_OUTPUT_TEMPLATE.format(
+ class_name = self.class_name,
+ iface_name = a.get_name(),
+ touch_output = a.get_touch_output()).strip(),
+ self.get_all_interfaces()))
+
+ def get_all_interfaces(self):
+ """
+ Returns a set of all interfaces this class transitively implements
+ """
+ return sorted(set(dump_tree(self.ifaces)))
+
+ def __str__(self):
+ """
+ Print the java code for this class.
+ """
+ j_ifaces = ', '.join(map(lambda a: a.get_name(), self.ifaces))
+ touches = '\n'.join(map(lambda a: self.TOUCH_CALL_TEMPLATE.format(class_name = self.class_name,
+ iface_name = a.get_name()),
+ self.get_all_interfaces()))
+ return self.TEST_CLASS_TEMPLATE.format(copyright = get_copyright('java'),
+ ifaces = j_ifaces,
+ class_name = self.class_name,
+ touch_calls = touches)
+
+class TestInterface(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.JavaFileMixin):
+ """
+ An interface that will be used to test default method resolution order.
+ """
+
+ TEST_INTERFACE_TEMPLATE = """{copyright}
+public interface {class_name} {extends} {ifaces} {{
+ public static final Displayer field = new Displayer("{tree}");
+ public void marker();
+{funcs}
+}}
+"""
+
+ DEFAULT_FUNC_TEMPLATE = """
+ public default void {class_name}_DEFAULT_FUNC() {{ return; }}
+"""
+
+ OUTPUT_TEMPLATE = "initialization of {tree}"
+
+ def __init__(self, ifaces, default):
+ """
+ Initialize interface with the given super-interfaces
+ """
+ self.ifaces = ifaces
+ self.default = default
+ end = "_DEFAULT" if default else ""
+ self.class_name = "INTERFACE_"+gensym()+end
+ self.cloned = False
+ self.initialized = False
+
+ def clone(self):
+ """
+ Clones this interface, returning a new one with the same structure but
+ different name.
+ """
+ return TestInterface(tuple(map(lambda a: a.clone(), self.ifaces)), self.default)
+
+ def get_name(self):
+ """
+ Gets the name of this interface
+ """
+ return self.class_name
+
+ def __iter__(self):
+ """
+ Performs depth-first traversal of the interface tree this interface is the
+ root of. Does not filter out repeats.
+ """
+ for i in self.ifaces:
+ yield i
+ yield from i
+
+ def get_tree(self):
+ """
+ Print out a representation of the type tree of this class
+ """
+ return "[{class_name} {iftree}]".format(class_name = self.get_name(),
+ iftree = print_tree(self.ifaces))
+
+ def get_initialize_output(self):
+ """
+ Returns the expected output upon the class that implements this interface being initialized.
+ """
+ if self.default and not self.initialized:
+ self.initialized = True
+ return self.OUTPUT_TEMPLATE.format(tree = self.get_tree())
+ else:
+ return ""
+
+ def get_touch_output(self):
+ """
+ Returns the expected output upon this interface being touched.
+ """
+ if not self.default and not self.initialized:
+ self.initialized = True
+ return self.OUTPUT_TEMPLATE.format(tree = self.get_tree())
+ else:
+ return ""
+
+ def __str__(self):
+ """
+ Print the java code for this interface.
+ """
+ j_ifaces = ', '.join(map(lambda a: a.get_name(), self.ifaces))
+ if self.default:
+ funcs = self.DEFAULT_FUNC_TEMPLATE.format(class_name = self.class_name)
+ else:
+ funcs = ""
+ return self.TEST_INTERFACE_TEMPLATE.format(copyright = get_copyright('java'),
+ extends = "extends" if len(self.ifaces) else "",
+ ifaces = j_ifaces,
+ funcs = funcs,
+ tree = self.get_tree(),
+ class_name = self.class_name)
+
+def dump_tree(ifaces):
+ """
+ Yields all the interfaces transitively implemented by the set in
+ reverse-depth-first order
+ """
+ for i in ifaces:
+ yield from dump_tree(i.ifaces)
+ yield i
+
+def print_tree(ifaces):
+ """
+ Prints the tree for the given ifaces.
+ """
+ return " ".join(i.get_tree() for i in ifaces)
+
+def clone_all(l):
+ return tuple(a.clone() for a in l)
+
+# Cached output of subtree_sizes for speed of access.
+SUBTREES = [set(tuple(l) for l in subtree_sizes(i))
+ for i in range(MAX_IFACE_DEPTH + 1)]
+
+def create_test_classes():
+ """
+ Yield all the test classes with the different interface trees
+ """
+ for num in range(1, MAX_IFACE_DEPTH + 1):
+ for split in SUBTREES[num]:
+ ifaces = []
+ for sub in split:
+ ifaces.append(list(create_interface_trees(sub)))
+ for supers in itertools.product(*ifaces):
+ yield TestClass(clone_all(supers))
+ for i in range(len(set(dump_tree(supers)) - set(supers))):
+ ns = clone_all(supers)
+ selected = sorted(set(dump_tree(ns)) - set(ns))[i]
+ yield TestClass(tuple([selected] + list(ns)))
+
+def create_interface_trees(num):
+ """
+ Yield all the interface trees up to 'num' depth.
+ """
+ if num == 0:
+ yield TestInterface(tuple(), False)
+ yield TestInterface(tuple(), True)
+ return
+ for split in SUBTREES[num]:
+ ifaces = []
+ for sub in split:
+ ifaces.append(list(create_interface_trees(sub)))
+ for supers in itertools.product(*ifaces):
+ yield TestInterface(clone_all(supers), False)
+ yield TestInterface(clone_all(supers), True)
+ # TODO Should add on some from higher up the tree.
+
+def create_all_test_files():
+ """
+ Creates all the objects representing the files in this test. They just need to
+ be dumped.
+ """
+ mc = MainClass()
+ classes = {mc}
+ for clazz in create_test_classes():
+ classes.add(clazz)
+ for i in dump_tree(clazz.ifaces):
+ classes.add(i)
+ mc.add_test(clazz)
+ return mc, classes
+
+def main(argv):
+ java_dir = Path(argv[1])
+ if not java_dir.exists() or not java_dir.is_dir():
+ print("{} is not a valid java dir".format(java_dir), file=sys.stderr)
+ sys.exit(1)
+ expected_txt = Path(argv[2])
+ mainclass, all_files = create_all_test_files()
+ with expected_txt.open('w') as out:
+ print(mainclass.get_expected(), file=out)
+ for f in all_files:
+ f.dump(java_dir)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/test/964-default-iface-init-generated/util-src/generate_smali.py b/test/964-default-iface-init-generated/util-src/generate_smali.py
deleted file mode 100755
index c0ba157..0000000
--- a/test/964-default-iface-init-generated/util-src/generate_smali.py
+++ /dev/null
@@ -1,531 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Generate Smali test files for test 964.
-"""
-
-import os
-import sys
-from pathlib import Path
-
-BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
-if BUILD_TOP is None:
- print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
- sys.exit(1)
-
-# Allow us to import utils and mixins.
-sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
-
-from testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks
-import testgen.mixins as mixins
-
-from functools import total_ordering
-import itertools
-import string
-
-# The max depth the tree can have.
-MAX_IFACE_DEPTH = 3
-
-class MainClass(mixins.DumpMixin, mixins.Named, mixins.SmaliFileMixin):
- """
- A Main.smali file containing the Main class and the main function. It will run
- all the test functions we have.
- """
-
- MAIN_CLASS_TEMPLATE = """{copyright}
-
-.class public LMain;
-.super Ljava/lang/Object;
-
-# class Main {{
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-{test_groups}
-
-{main_func}
-
-# }}
-"""
-
- MAIN_FUNCTION_TEMPLATE = """
-# public static void main(String[] args) {{
-.method public static main([Ljava/lang/String;)V
- .locals 2
-
- {test_group_invoke}
-
- return-void
-.end method
-# }}
-"""
-
- TEST_GROUP_INVOKE_TEMPLATE = """
-# {test_name}();
- invoke-static {{}}, {test_name}()V
-"""
-
- def __init__(self):
- """
- Initialize this MainClass. We start out with no tests.
- """
- self.tests = set()
-
- def add_test(self, ty):
- """
- Add a test for the concrete type 'ty'
- """
- self.tests.add(Func(ty))
-
- def get_expected(self):
- """
- Get the expected output of this test.
- """
- all_tests = sorted(self.tests)
- return filter_blanks("\n".join(a.get_expected() for a in all_tests))
-
- def get_name(self):
- """
- Gets the name of this class
- """
- return "Main"
-
- def __str__(self):
- """
- Print the smali code for this test.
- """
- all_tests = sorted(self.tests)
- test_invoke = ""
- test_groups = ""
- for t in all_tests:
- test_groups += str(t)
- for t in all_tests:
- test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
- main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)
-
- return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright('smali'),
- test_groups = test_groups,
- main_func = main_func)
-
-class Func(mixins.Named, mixins.NameComparableMixin):
- """
- A function that tests the functionality of a concrete type. Should only be
- constructed by MainClass.add_test.
- """
-
- TEST_FUNCTION_TEMPLATE = """
-# public static void {fname}() {{
-# try {{
-# System.out.println("About to initialize {tree}");
-# {farg} v = new {farg}();
-# System.out.println("Initialized {tree}");
-# v.touchAll();
-# System.out.println("All of {tree} hierarchy initialized");
-# return;
-# }} catch (Error e) {{
-# e.printStackTrace(System.out);
-# return;
-# }}
-# }}
-.method public static {fname}()V
- .locals 7
- :call_{fname}_try_start
- sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v3, "About to initialize {tree}"
- invoke-virtual {{v2, v3}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- new-instance v6, L{farg};
- invoke-direct {{v6}}, L{farg};-><init>()V
-
- const-string v3, "Initialized {tree}"
- invoke-virtual {{v2, v3}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-virtual {{v6}}, L{farg};->touchAll()V
-
- const-string v3, "All of {tree} hierarchy initialized"
- invoke-virtual {{v2, v3}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- return-void
- :call_{fname}_try_end
- .catch Ljava/lang/Error; {{:call_{fname}_try_start .. :call_{fname}_try_end}} :error_{fname}_start
- :error_{fname}_start
- move-exception v3
- sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
- invoke-virtual {{v3,v2}}, Ljava/lang/Error;->printStackTrace(Ljava/io/PrintStream;)V
- return-void
-.end method
-"""
-
- OUTPUT_FORMAT = """
-About to initialize {tree}
-{initialize_output}
-Initialized {tree}
-{touch_output}
-All of {tree} hierarchy initialized
-""".strip()
-
- def __init__(self, farg):
- """
- Initialize a test function for the given argument
- """
- self.farg = farg
-
- def __str__(self):
- """
- Print the smali code for this test function.
- """
- return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(),
- farg=self.farg.get_name(),
- tree = self.farg.get_tree())
-
- def get_name(self):
- """
- Gets the name of this test function
- """
- return "TEST_FUNC_{}".format(self.farg.get_name())
-
- def get_expected(self):
- """
- Get the expected output of this function.
- """
- return self.OUTPUT_FORMAT.format(
- tree = self.farg.get_tree(),
- initialize_output = self.farg.get_initialize_output().strip(),
- touch_output = self.farg.get_touch_output().strip())
-
-class TestClass(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin):
- """
- A class that will be instantiated to test interface initialization order.
- """
-
- TEST_CLASS_TEMPLATE = """{copyright}
-
-.class public L{class_name};
-.super Ljava/lang/Object;
-{implements_spec}
-
-# public class {class_name} implements {ifaces} {{
-#
-# public {class_name}() {{
-# }}
-.method public constructor <init>()V
- .locals 2
- invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-# public void marker() {{
-# return;
-# }}
-.method public marker()V
- .locals 0
- return-void
-.end method
-
-# public void touchAll() {{
-.method public touchAll()V
- .locals 2
- sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
- {touch_calls}
- return-void
-.end method
-# }}
-# }}
-"""
-
- IMPLEMENTS_TEMPLATE = """
-.implements L{iface_name};
-"""
-
- TOUCH_CALL_TEMPLATE = """
-# System.out.println("{class_name} touching {iface_name}");
-# {iface_name}.field.touch();
- const-string v1, "{class_name} touching {iface_name}"
- invoke-virtual {{v0, v1}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- sget-object v1, L{iface_name};->field:LDisplayer;
- invoke-virtual {{v1}}, LDisplayer;->touch()V
-"""
-
- TOUCH_OUTPUT_TEMPLATE = """
-{class_name} touching {iface_name}
-{touch_output}
-""".strip()
-
- def __init__(self, ifaces):
- """
- Initialize this test class which implements the given interfaces
- """
- self.ifaces = ifaces
- self.class_name = "CLASS_"+gensym()
-
- def get_name(self):
- """
- Gets the name of this interface
- """
- return self.class_name
-
- def get_tree(self):
- """
- Print out a representation of the type tree of this class
- """
- return "[{fname} {iftree}]".format(fname = self.get_name(), iftree = print_tree(self.ifaces))
-
- def get_initialize_output(self):
- return "\n".join(map(lambda i: i.get_initialize_output().strip(), dump_tree(self.ifaces)))
-
- def get_touch_output(self):
- return "\n".join(map(lambda a: self.TOUCH_OUTPUT_TEMPLATE.format(
- class_name = self.class_name,
- iface_name = a.get_name(),
- touch_output = a.get_touch_output()).strip(),
- self.get_all_interfaces()))
-
- def get_all_interfaces(self):
- """
- Returns a set of all interfaces this class transitively implements
- """
- return sorted(set(dump_tree(self.ifaces)))
-
- def __str__(self):
- """
- Print the smali code for this class.
- """
- s_ifaces = '\n'.join(map(lambda a: self.IMPLEMENTS_TEMPLATE.format(iface_name = a.get_name()),
- self.ifaces))
- j_ifaces = ', '.join(map(lambda a: a.get_name(), self.ifaces))
- touches = '\n'.join(map(lambda a: self.TOUCH_CALL_TEMPLATE.format(class_name = self.class_name,
- iface_name = a.get_name()),
- self.get_all_interfaces()))
- return self.TEST_CLASS_TEMPLATE.format(copyright = get_copyright('smali'),
- implements_spec = s_ifaces,
- ifaces = j_ifaces,
- class_name = self.class_name,
- touch_calls = touches)
-
-class TestInterface(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin):
- """
- An interface that will be used to test default method resolution order.
- """
-
- TEST_INTERFACE_TEMPLATE = """{copyright}
-.class public abstract interface L{class_name};
-.super Ljava/lang/Object;
-{implements_spec}
-
-# public interface {class_name} {extends} {ifaces} {{
-# public static final Displayer field = new Displayer("{tree}");
-.field public final static field:LDisplayer;
-
-.method static constructor <clinit>()V
- .locals 3
- const-string v2, "{tree}"
- new-instance v1, LDisplayer;
- invoke-direct {{v1, v2}}, LDisplayer;-><init>(Ljava/lang/String;)V
- sput-object v1, L{class_name};->field:LDisplayer;
- return-void
-.end method
-
-# public void marker();
-.method public abstract marker()V
-.end method
-
-{funcs}
-
-# }}
-"""
-
- DEFAULT_FUNC_TEMPLATE = """
-# public default void {class_name}_DEFAULT_FUNC() {{
-# return;
-# }}
-.method public {class_name}_DEFAULT_FUNC()V
- .locals 0
- return-void
-.end method
-"""
- IMPLEMENTS_TEMPLATE = """
-.implements L{iface_name};
-"""
-
- OUTPUT_TEMPLATE = "initialization of {tree}"
-
- def __init__(self, ifaces, default):
- """
- Initialize interface with the given super-interfaces
- """
- self.ifaces = ifaces
- self.default = default
- end = "_DEFAULT" if default else ""
- self.class_name = "INTERFACE_"+gensym()+end
- self.cloned = False
- self.initialized = False
-
- def clone(self):
- """
- Clones this interface, returning a new one with the same structure but
- different name.
- """
- return TestInterface(tuple(map(lambda a: a.clone(), self.ifaces)), self.default)
-
- def get_name(self):
- """
- Gets the name of this interface
- """
- return self.class_name
-
- def __iter__(self):
- """
- Performs depth-first traversal of the interface tree this interface is the
- root of. Does not filter out repeats.
- """
- for i in self.ifaces:
- yield i
- yield from i
-
- def get_tree(self):
- """
- Print out a representation of the type tree of this class
- """
- return "[{class_name} {iftree}]".format(class_name = self.get_name(),
- iftree = print_tree(self.ifaces))
-
- def get_initialize_output(self):
- """
- Returns the expected output upon the class that implements this interface being initialized.
- """
- if self.default and not self.initialized:
- self.initialized = True
- return self.OUTPUT_TEMPLATE.format(tree = self.get_tree())
- else:
- return ""
-
- def get_touch_output(self):
- """
- Returns the expected output upon this interface being touched.
- """
- if not self.default and not self.initialized:
- self.initialized = True
- return self.OUTPUT_TEMPLATE.format(tree = self.get_tree())
- else:
- return ""
-
- def __str__(self):
- """
- Print the smali code for this interface.
- """
- s_ifaces = '\n'.join(map(lambda a: self.IMPLEMENTS_TEMPLATE.format(iface_name = a.get_name()),
- self.ifaces))
- j_ifaces = ', '.join(map(lambda a: a.get_name(), self.ifaces))
- if self.default:
- funcs = self.DEFAULT_FUNC_TEMPLATE.format(class_name = self.class_name)
- else:
- funcs = ""
- return self.TEST_INTERFACE_TEMPLATE.format(copyright = get_copyright('smali'),
- implements_spec = s_ifaces,
- extends = "extends" if len(self.ifaces) else "",
- ifaces = j_ifaces,
- funcs = funcs,
- tree = self.get_tree(),
- class_name = self.class_name)
-
-def dump_tree(ifaces):
- """
- Yields all the interfaces transitively implemented by the set in
- reverse-depth-first order
- """
- for i in ifaces:
- yield from dump_tree(i.ifaces)
- yield i
-
-def print_tree(ifaces):
- """
- Prints the tree for the given ifaces.
- """
- return " ".join(i.get_tree() for i in ifaces)
-
-def clone_all(l):
- return tuple(a.clone() for a in l)
-
-# Cached output of subtree_sizes for speed of access.
-SUBTREES = [set(tuple(l) for l in subtree_sizes(i))
- for i in range(MAX_IFACE_DEPTH + 1)]
-
-def create_test_classes():
- """
- Yield all the test classes with the different interface trees
- """
- for num in range(1, MAX_IFACE_DEPTH + 1):
- for split in SUBTREES[num]:
- ifaces = []
- for sub in split:
- ifaces.append(list(create_interface_trees(sub)))
- for supers in itertools.product(*ifaces):
- yield TestClass(clone_all(supers))
- for i in range(len(set(dump_tree(supers)) - set(supers))):
- ns = clone_all(supers)
- selected = sorted(set(dump_tree(ns)) - set(ns))[i]
- yield TestClass(tuple([selected] + list(ns)))
-
-def create_interface_trees(num):
- """
- Yield all the interface trees up to 'num' depth.
- """
- if num == 0:
- yield TestInterface(tuple(), False)
- yield TestInterface(tuple(), True)
- return
- for split in SUBTREES[num]:
- ifaces = []
- for sub in split:
- ifaces.append(list(create_interface_trees(sub)))
- for supers in itertools.product(*ifaces):
- yield TestInterface(clone_all(supers), False)
- yield TestInterface(clone_all(supers), True)
- # TODO Should add on some from higher up the tree.
-
-def create_all_test_files():
- """
- Creates all the objects representing the files in this test. They just need to
- be dumped.
- """
- mc = MainClass()
- classes = {mc}
- for clazz in create_test_classes():
- classes.add(clazz)
- for i in dump_tree(clazz.ifaces):
- classes.add(i)
- mc.add_test(clazz)
- return mc, classes
-
-def main(argv):
- smali_dir = Path(argv[1])
- if not smali_dir.exists() or not smali_dir.is_dir():
- print("{} is not a valid smali dir".format(smali_dir), file=sys.stderr)
- sys.exit(1)
- expected_txt = Path(argv[2])
- mainclass, all_files = create_all_test_files()
- with expected_txt.open('w') as out:
- print(mainclass.get_expected(), file=out)
- for f in all_files:
- f.dump(smali_dir)
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/test/965-default-verify/build b/test/965-default-verify/build
index 5ba5438..0dd8573 100755
--- a/test/965-default-verify/build
+++ b/test/965-default-verify/build
@@ -17,32 +17,11 @@
# make us exit on a failure
set -e
-# Should we compile with Java source code. By default we will use Smali.
-USES_JAVA_SOURCE="false"
-if [[ $@ == *"--jvm"* ]]; then
- USES_JAVA_SOURCE="true"
-elif [[ "$USE_JACK" == "true" ]]; then
- if $JACK -D jack.java.source.version=1.8 2>/dev/null; then
- USES_JAVA_SOURCE="true"
- else
- echo "WARNING: Cannot use jack because it does not support JLS 1.8. Falling back to smali" >&2
- fi
+if [[ $@ != *"--jvm"* ]]; then
+ # Don't do anything with jvm
+ # Hard-wired use of experimental jack.
+ # TODO: fix this temporary work-around for default-methods, see b/19467889
+ export USE_JACK=true
fi
-if [[ "$USES_JAVA_SOURCE" == "true" ]]; then
- # We are compiling Java code, create it.
- mkdir -p src
- mkdir -p src2
- ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
- # Move build-src to src and the src copies to src2. This is needed because of
- # how our default build script works and we wanted the java and smali code
- # to be the same in the smali files.
- for f in `find ./build-src -type f -name "*.java" | xargs -i basename \{\}`; do
- mv ./src/$f ./src2/$f
- mv ./build-src/$f ./src/$f
- done
- # Ignore the smali directory.
- EXTRA_ARGS="--no-smali"
-fi
-
-./default-build "$@" "$EXTRA_ARGS" --experimental default-methods
+./default-build "$@" --experimental default-methods
diff --git a/test/965-default-verify/build-src/Statics.java b/test/965-default-verify/build-src/Statics.java
deleted file mode 100644
index 300aeec..0000000
--- a/test/965-default-verify/build-src/Statics.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-class Statics {
- public static void nonexistantFunction() {
- System.out.println("I don't exist");
- }
-}
-
diff --git a/test/965-default-verify/smali/Iface.smali b/test/965-default-verify/smali/Iface.smali
deleted file mode 100644
index 74799a6..0000000
--- a/test/965-default-verify/smali/Iface.smali
+++ /dev/null
@@ -1,40 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface Iface {
-# public default String sayHi() {
-# return "Hello";
-# }
-#
-# public default void verificationSoftFail() {
-# Statics.nonexistantFunction();
-# }
-# }
-
-.class public abstract interface LIface;
-.super Ljava/lang/Object;
-
-.method public sayHi()Ljava/lang/String;
- .locals 1
- const-string v0, "Hello"
- return-object v0
-.end method
-
-.method public verificationSoftFail()V
- .locals 1
- invoke-static {}, LStatics;->nonexistantFunction()V
- return-void
-.end method
diff --git a/test/965-default-verify/smali/Main.smali b/test/965-default-verify/smali/Main.smali
deleted file mode 100644
index 8e90706..0000000
--- a/test/965-default-verify/smali/Main.smali
+++ /dev/null
@@ -1,179 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# class Main implements Iface {
-# public static void main(String[] args) {
-# System.out.println("Create Main instance");
-# Main m = new Main();
-# System.out.println("Calling functions on concrete Main");
-# callMain(m);
-# System.out.println("Calling functions on interface Iface");
-# callIface(m);
-# }
-#
-# public static void callMain(Main m) {
-# System.out.println("Calling verifiable function on Main");
-# System.out.println(m.sayHi());
-# System.out.println("Calling unverifiable function on Main");
-# try {
-# m.verificationSoftFail();
-# System.out.println("Unexpected no error Thrown on Main");
-# } catch (NoSuchMethodError e) {
-# System.out.println("Expected NSME Thrown on Main");
-# } catch (Throwable e) {
-# System.out.println("Unexpected Error Thrown on Main");
-# e.printStackTrace(System.out);
-# }
-# System.out.println("Calling verifiable function on Main");
-# System.out.println(m.sayHi());
-# return;
-# }
-#
-# public static void callIface(Iface m) {
-# System.out.println("Calling verifiable function on Iface");
-# System.out.println(m.sayHi());
-# System.out.println("Calling unverifiable function on Iface");
-# try {
-# m.verificationSoftFail();
-# System.out.println("Unexpected no error Thrown on Iface");
-# } catch (NoSuchMethodError e) {
-# System.out.println("Expected NSME Thrown on Iface");
-# } catch (Throwable e) {
-# System.out.println("Unexpected Error Thrown on Iface");
-# e.printStackTrace(System.out);
-# }
-# System.out.println("Calling verifiable function on Iface");
-# System.out.println(m.sayHi());
-# return;
-# }
-# }
-
-.class public LMain;
-.super Ljava/lang/Object;
-.implements LIface;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public static main([Ljava/lang/String;)V
- .locals 3
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
-
- const-string v0, "Create Main instance"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- new-instance v2, LMain;
- invoke-direct {v2}, LMain;-><init>()V
-
- const-string v0, "Calling functions on concrete Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-static {v2}, LMain;->callMain(LMain;)V
-
- const-string v0, "Calling functions on interface Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-static {v2}, LMain;->callIface(LIface;)V
-
- return-void
-.end method
-
-.method public static callIface(LIface;)V
- .locals 3
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "Calling verifiable function on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-interface {p0}, LIface;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Calling unverifiable function on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- :try_start
- invoke-interface {p0}, LIface;->verificationSoftFail()V
-
- const-string v0, "Unexpected no error Thrown on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- goto :error_end
- :try_end
- .catch Ljava/lang/NoSuchMethodError; {:try_start .. :try_end} :NSME_error_start
- .catch Ljava/lang/Throwable; {:try_start .. :try_end} :other_error_start
- :NSME_error_start
- const-string v0, "Expected NSME Thrown on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :other_error_start
- move-exception v2
- const-string v0, "Unexpected Error Thrown on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-virtual {v2,v1}, Ljava/lang/Throwable;->printStackTrace(Ljava/io/PrintStream;)V
- goto :error_end
- :error_end
- const-string v0, "Calling verifiable function on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-interface {p0}, LIface;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- return-void
-.end method
-
-.method public static callMain(LMain;)V
- .locals 3
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "Calling verifiable function on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-virtual {p0}, LMain;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Calling unverifiable function on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- :try_start
- invoke-virtual {p0}, LMain;->verificationSoftFail()V
-
- const-string v0, "Unexpected no error Thrown on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- goto :error_end
- :try_end
- .catch Ljava/lang/NoSuchMethodError; {:try_start .. :try_end} :NSME_error_start
- .catch Ljava/lang/Throwable; {:try_start .. :try_end} :other_error_start
- :NSME_error_start
- const-string v0, "Expected NSME Thrown on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :other_error_start
- move-exception v2
- const-string v0, "Unexpected Error Thrown on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-virtual {v2,v1}, Ljava/lang/Throwable;->printStackTrace(Ljava/io/PrintStream;)V
- goto :error_end
- :error_end
- const-string v0, "Calling verifiable function on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-virtual {p0}, LMain;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- return-void
-.end method
diff --git a/test/965-default-verify/smali/Statics.smali b/test/965-default-verify/smali/Statics.smali
deleted file mode 100644
index 1e8cac0..0000000
--- a/test/965-default-verify/smali/Statics.smali
+++ /dev/null
@@ -1,30 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# class Statics {
-# // public static void nonexistantFunction() {
-# // System.out.println("I don't exist");
-# // }
-# }
-#
-.class public LStatics;
-.super Ljava/lang/Object;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
diff --git a/test/965-default-verify/src/Iface.java b/test/965-default-verify/src/Iface.java
new file mode 100644
index 0000000..180fba2
--- /dev/null
+++ b/test/965-default-verify/src/Iface.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface {
+ public default String sayHi() {
+ return "Hello";
+ }
+ public default void verificationSoftFail() {
+ Statics.nonexistantFunction();
+ }
+}
diff --git a/test/965-default-verify/src/Main.java b/test/965-default-verify/src/Main.java
new file mode 100644
index 0000000..6374cb5
--- /dev/null
+++ b/test/965-default-verify/src/Main.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class Main implements Iface {
+ public static void main(String[] args) {
+ System.out.println("Create Main instance");
+ Main m = new Main();
+ System.out.println("Calling functions on concrete Main");
+ callMain(m);
+ System.out.println("Calling functions on interface Iface");
+ callIface(m);
+ }
+
+ public static void callMain(Main m) {
+ System.out.println("Calling verifiable function on Main");
+ System.out.println(m.sayHi());
+ System.out.println("Calling unverifiable function on Main");
+ try {
+ m.verificationSoftFail();
+ System.out.println("Unexpected no error Thrown on Main");
+ } catch (NoSuchMethodError e) {
+ System.out.println("Expected NSME Thrown on Main");
+ } catch (Throwable e) {
+ System.out.println("Unexpected Error Thrown on Main");
+ e.printStackTrace(System.out);
+ }
+ System.out.println("Calling verifiable function on Main");
+ System.out.println(m.sayHi());
+ return;
+ }
+
+ public static void callIface(Iface m) {
+ System.out.println("Calling verifiable function on Iface");
+ System.out.println(m.sayHi());
+ System.out.println("Calling unverifiable function on Iface");
+ try {
+ m.verificationSoftFail();
+ System.out.println("Unexpected no error Thrown on Iface");
+ } catch (NoSuchMethodError e) {
+ System.out.println("Expected NSME Thrown on Iface");
+ } catch (Throwable e) {
+ System.out.println("Unexpected Error Thrown on Iface");
+ e.printStackTrace(System.out);
+ }
+ System.out.println("Calling verifiable function on Iface");
+ System.out.println(m.sayHi());
+ return;
+ }
+}
diff --git a/test/965-default-verify/src/Statics.java b/test/965-default-verify/src/Statics.java
new file mode 100644
index 0000000..2e17ba4
--- /dev/null
+++ b/test/965-default-verify/src/Statics.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class Statics {
+ public static void nonexistantFunction() {
+ System.out.println("I don't exist");
+ }
+}
+
diff --git a/test/965-default-verify/src2/Statics.java b/test/965-default-verify/src2/Statics.java
new file mode 100644
index 0000000..7899ca9
--- /dev/null
+++ b/test/965-default-verify/src2/Statics.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class Statics {
+ // public static void nonexistantFunction() {
+ // System.out.println("I don't exist");
+ // }
+}
diff --git a/test/966-default-conflict/build b/test/966-default-conflict/build
index e66e840..0dd8573 100755
--- a/test/966-default-conflict/build
+++ b/test/966-default-conflict/build
@@ -17,18 +17,11 @@
# make us exit on a failure
set -e
-# TODO: Support running with jack.
-
-if [[ $@ == *"--jvm"* ]]; then
- # Build the Java files if we are running a --jvm test
- mkdir -p src
- mkdir -p classes
- ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
- # Build with the non-conflicting version
- ${JAVAC} -implicit:none -d classes src/Iface.java build-src/Iface2.java src/Main.java
- rm classes/Iface2.class
- # Build with the conflicting version
- ${JAVAC} -implicit:none -cp classes -d classes src/Iface2.java
-else
- ./default-build "$@" --experimental default-methods
+if [[ $@ != *"--jvm"* ]]; then
+ # Don't do anything with jvm
+ # Hard-wired use of experimental jack.
+ # TODO: fix this temporary work-around for default-methods, see b/19467889
+ export USE_JACK=true
fi
+
+./default-build "$@" --experimental default-methods
diff --git a/test/966-default-conflict/smali/Iface.smali b/test/966-default-conflict/smali/Iface.smali
deleted file mode 100644
index e996b3a..0000000
--- a/test/966-default-conflict/smali/Iface.smali
+++ /dev/null
@@ -1,39 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface Iface {
-# public default String sayHi() {
-# return "Hi";
-# }
-# public default String charge() {
-# return "CHARGE";
-# }
-# }
-
-.class public abstract interface LIface;
-.super Ljava/lang/Object;
-
-.method public sayHi()Ljava/lang/String;
- .locals 1
- const-string v0, "Hi"
- return-object v0
-.end method
-
-.method public charge()Ljava/lang/String;
- .locals 1
- const-string v0, "CHARGE"
- return-object v0
-.end method
diff --git a/test/966-default-conflict/smali/Iface2.smali b/test/966-default-conflict/smali/Iface2.smali
deleted file mode 100644
index 82fa547..0000000
--- a/test/966-default-conflict/smali/Iface2.smali
+++ /dev/null
@@ -1,31 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface Iface2 {
-# public default String sayHi() {
-# return "hello";
-# }
-# }
-
-.class public abstract interface LIface2;
-.super Ljava/lang/Object;
-
-.method public sayHi()Ljava/lang/String;
- .locals 1
- const-string v0, "hello"
- return-object v0
-.end method
-
diff --git a/test/966-default-conflict/smali/Main.smali b/test/966-default-conflict/smali/Main.smali
deleted file mode 100644
index ce974d8..0000000
--- a/test/966-default-conflict/smali/Main.smali
+++ /dev/null
@@ -1,227 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# class Main implements Iface, Iface2 {
-# public static void main(String[] args) {
-# System.out.println("Create Main instance");
-# Main m = new Main();
-# System.out.println("Calling functions on concrete Main");
-# callMain(m);
-# System.out.println("Calling functions on interface Iface");
-# callIface(m);
-# System.out.println("Calling functions on interface Iface2");
-# callIface2(m);
-# }
-#
-# public static void callMain(Main m) {
-# System.out.println("Calling non-conflicting function on Main");
-# System.out.println(m.charge());
-# System.out.println("Calling conflicting function on Main");
-# try {
-# System.out.println(m.sayHi());
-# System.out.println("Unexpected no error Thrown on Main");
-# } catch (AbstractMethodError e) {
-# System.out.println("Unexpected AME Thrown on Main");
-# } catch (IncompatibleClassChangeError e) {
-# System.out.println("Expected ICCE Thrown on Main");
-# }
-# System.out.println("Calling non-conflicting function on Main");
-# System.out.println(m.charge());
-# return;
-# }
-#
-# public static void callIface(Iface m) {
-# System.out.println("Calling non-conflicting function on Iface");
-# System.out.println(m.charge());
-# System.out.println("Calling conflicting function on Iface");
-# try {
-# System.out.println(m.sayHi());
-# System.out.println("Unexpected no error Thrown on Iface");
-# } catch (AbstractMethodError e) {
-# System.out.println("Unexpected AME Thrown on Iface");
-# } catch (IncompatibleClassChangeError e) {
-# System.out.println("Expected ICCE Thrown on Iface");
-# }
-# System.out.println("Calling non-conflicting function on Iface");
-# System.out.println(m.charge());
-# return;
-# }
-#
-# public static void callIface2(Iface2 m) {
-# System.out.println("Calling conflicting function on Iface2");
-# try {
-# System.out.println(m.sayHi());
-# System.out.println("Unexpected no error Thrown on Iface2");
-# } catch (AbstractMethodError e) {
-# System.out.println("Unexpected AME Thrown on Iface2");
-# } catch (IncompatibleClassChangeError e) {
-# System.out.println("Expected ICCE Thrown on Iface2");
-# }
-# return;
-# }
-# }
-
-.class public LMain;
-.super Ljava/lang/Object;
-.implements LIface;
-.implements LIface2;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public static main([Ljava/lang/String;)V
- .locals 3
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
-
- const-string v0, "Create Main instance"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- new-instance v2, LMain;
- invoke-direct {v2}, LMain;-><init>()V
-
- const-string v0, "Calling functions on concrete Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-static {v2}, LMain;->callMain(LMain;)V
-
- const-string v0, "Calling functions on interface Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-static {v2}, LMain;->callIface(LIface;)V
-
- const-string v0, "Calling functions on interface Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-static {v2}, LMain;->callIface2(LIface2;)V
-
- return-void
-.end method
-
-.method public static callIface(LIface;)V
- .locals 2
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "Calling non-conflicting function on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-interface {p0}, LIface;->charge()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Calling conflicting function on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- :try_start
- invoke-interface {p0}, LIface;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Unexpected no error Thrown on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- goto :error_end
- :try_end
- .catch Ljava/lang/AbstractMethodError; {:try_start .. :try_end} :AME_error_start
- .catch Ljava/lang/IncompatibleClassChangeError; {:try_start .. :try_end} :ICCE_error_start
- :AME_error_start
- const-string v0, "Unexpected AME Thrown on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :ICCE_error_start
- const-string v0, "Expected ICCE Thrown on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :error_end
- const-string v0, "Calling non-conflicting function on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-interface {p0}, LIface;->charge()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- return-void
-.end method
-
-.method public static callIface2(LIface2;)V
- .locals 2
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "Calling conflicting function on Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- :try_start
- invoke-interface {p0}, LIface2;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Unexpected no error Thrown on Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- goto :error_end
- :try_end
- .catch Ljava/lang/AbstractMethodError; {:try_start .. :try_end} :AME_error_start
- .catch Ljava/lang/IncompatibleClassChangeError; {:try_start .. :try_end} :ICCE_error_start
- :AME_error_start
- const-string v0, "Unexpected AME Thrown on Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :ICCE_error_start
- const-string v0, "Expected ICCE Thrown on Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :error_end
-
- return-void
-.end method
-
-.method public static callMain(LMain;)V
- .locals 2
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "Calling non-conflicting function on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-virtual {p0}, LMain;->charge()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Calling conflicting function on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- :try_start
- invoke-virtual {p0}, LMain;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Unexpected no error Thrown on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- goto :error_end
- :try_end
- .catch Ljava/lang/AbstractMethodError; {:try_start .. :try_end} :AME_error_start
- .catch Ljava/lang/IncompatibleClassChangeError; {:try_start .. :try_end} :ICCE_error_start
- :AME_error_start
- const-string v0, "Unexpected AME Thrown on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :ICCE_error_start
- const-string v0, "Expected ICCE Thrown on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :error_end
- const-string v0, "Calling non-conflicting function on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-virtual {p0}, LMain;->charge()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- return-void
-.end method
diff --git a/test/966-default-conflict/src/Iface.java b/test/966-default-conflict/src/Iface.java
new file mode 100644
index 0000000..2131ed8
--- /dev/null
+++ b/test/966-default-conflict/src/Iface.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface {
+ public default String sayHi() {
+ return "Hi";
+ }
+ public default String charge() {
+ return "CHARGE";
+ }
+}
diff --git a/test/966-default-conflict/build-src/Iface2.java b/test/966-default-conflict/src/Iface2.java
similarity index 100%
rename from test/966-default-conflict/build-src/Iface2.java
rename to test/966-default-conflict/src/Iface2.java
diff --git a/test/966-default-conflict/src/Main.java b/test/966-default-conflict/src/Main.java
new file mode 100644
index 0000000..ce8cb47
--- /dev/null
+++ b/test/966-default-conflict/src/Main.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class Main implements Iface, Iface2 {
+ public static void main(String[] args) {
+ System.out.println("Create Main instance");
+ Main m = new Main();
+ System.out.println("Calling functions on concrete Main");
+ callMain(m);
+ System.out.println("Calling functions on interface Iface");
+ callIface(m);
+ System.out.println("Calling functions on interface Iface2");
+ callIface2(m);
+ }
+ public static void callMain(Main m) {
+ System.out.println("Calling non-conflicting function on Main");
+ System.out.println(m.charge());
+ System.out.println("Calling conflicting function on Main");
+ try {
+ System.out.println(m.sayHi());
+ System.out.println("Unexpected no error Thrown on Main");
+ } catch (AbstractMethodError e) {
+ System.out.println("Unexpected AME Thrown on Main");
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("Expected ICCE Thrown on Main");
+ }
+ System.out.println("Calling non-conflicting function on Main");
+ System.out.println(m.charge());
+ return;
+ }
+ public static void callIface(Iface m) {
+ System.out.println("Calling non-conflicting function on Iface");
+ System.out.println(m.charge());
+ System.out.println("Calling conflicting function on Iface");
+ try {
+ System.out.println(m.sayHi());
+ System.out.println("Unexpected no error Thrown on Iface");
+ } catch (AbstractMethodError e) {
+ System.out.println("Unexpected AME Thrown on Iface");
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("Expected ICCE Thrown on Iface");
+ }
+ System.out.println("Calling non-conflicting function on Iface");
+ System.out.println(m.charge());
+ return;
+ }
+ public static void callIface2(Iface2 m) {
+ System.out.println("Calling conflicting function on Iface2");
+ try {
+ System.out.println(m.sayHi());
+ System.out.println("Unexpected no error Thrown on Iface2");
+ } catch (AbstractMethodError e) {
+ System.out.println("Unexpected AME Thrown on Iface2");
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("Expected ICCE Thrown on Iface2");
+ }
+ return;
+ }
+}
diff --git a/test/966-default-conflict/src2/Iface2.java b/test/966-default-conflict/src2/Iface2.java
new file mode 100644
index 0000000..d29033c
--- /dev/null
+++ b/test/966-default-conflict/src2/Iface2.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface2 {
+ public default String sayHi() {
+ return "hello";
+ }
+}
diff --git a/test/967-default-ame/build b/test/967-default-ame/build
index 53001a9..0dd8573 100755
--- a/test/967-default-ame/build
+++ b/test/967-default-ame/build
@@ -17,19 +17,11 @@
# make us exit on a failure
set -e
-# TODO: Support running with jack.
-
-if [[ $@ == *"--jvm"* ]]; then
- # Build the Java files if we are running a --jvm test
- mkdir -p src
- mkdir -p classes
- ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
- # Build with the non-conflicting version
- ${JAVAC} -implicit:none -d classes src/Iface.java build-src/Iface2.java build-src/Iface3.java src/Main.java
- rm classes/Iface2.class
- rm classes/Iface3.class
- # Build with the conflicting version
- ${JAVAC} -implicit:none -cp classes -d classes src/Iface2.java src/Iface3.java
-else
- ./default-build "$@" --experimental default-methods
+if [[ $@ != *"--jvm"* ]]; then
+ # Don't do anything with jvm
+ # Hard-wired use of experimental jack.
+ # TODO: fix this temporary work-around for default-methods, see b/19467889
+ export USE_JACK=true
fi
+
+./default-build "$@" --experimental default-methods
diff --git a/test/967-default-ame/smali/Iface.smali b/test/967-default-ame/smali/Iface.smali
deleted file mode 100644
index e996b3a..0000000
--- a/test/967-default-ame/smali/Iface.smali
+++ /dev/null
@@ -1,39 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface Iface {
-# public default String sayHi() {
-# return "Hi";
-# }
-# public default String charge() {
-# return "CHARGE";
-# }
-# }
-
-.class public abstract interface LIface;
-.super Ljava/lang/Object;
-
-.method public sayHi()Ljava/lang/String;
- .locals 1
- const-string v0, "Hi"
- return-object v0
-.end method
-
-.method public charge()Ljava/lang/String;
- .locals 1
- const-string v0, "CHARGE"
- return-object v0
-.end method
diff --git a/test/967-default-ame/smali/Iface2.smali b/test/967-default-ame/smali/Iface2.smali
deleted file mode 100644
index a21a8dd..0000000
--- a/test/967-default-ame/smali/Iface2.smali
+++ /dev/null
@@ -1,27 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface Iface2 extends Iface {
-# public String sayHi();
-# }
-
-.class public abstract interface LIface2;
-.super Ljava/lang/Object;
-.implements LIface;
-
-.method public abstract sayHi()Ljava/lang/String;
-.end method
-
diff --git a/test/967-default-ame/smali/Iface3.smali b/test/967-default-ame/smali/Iface3.smali
deleted file mode 100644
index 874e96d..0000000
--- a/test/967-default-ame/smali/Iface3.smali
+++ /dev/null
@@ -1,26 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface Iface3 {
-# public String charge();
-# }
-
-.class public abstract interface LIface3;
-.super Ljava/lang/Object;
-
-.method public abstract charge()Ljava/lang/String;
-.end method
-
diff --git a/test/967-default-ame/smali/Main.smali b/test/967-default-ame/smali/Main.smali
deleted file mode 100644
index e4d63cf..0000000
--- a/test/967-default-ame/smali/Main.smali
+++ /dev/null
@@ -1,228 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# class Main implements Iface, Iface2, Iface3 {
-# public static void main(String[] args) {
-# System.out.println("Create Main instance");
-# Main m = new Main();
-# System.out.println("Calling functions on concrete Main");
-# callMain(m);
-# System.out.println("Calling functions on interface Iface");
-# callIface(m);
-# System.out.println("Calling functions on interface Iface2");
-# callIface2(m);
-# }
-#
-# public static void callMain(Main m) {
-# System.out.println("Calling non-abstract function on Main");
-# System.out.println(m.charge());
-# System.out.println("Calling abstract function on Main");
-# try {
-# System.out.println(m.sayHi());
-# System.out.println("Unexpected no error Thrown on Main");
-# } catch (AbstractMethodError e) {
-# System.out.println("Expected AME Thrown on Main");
-# } catch (IncompatibleClassChangeError e) {
-# System.out.println("Unexpected ICCE Thrown on Main");
-# }
-# System.out.println("Calling non-abstract function on Main");
-# System.out.println(m.charge());
-# return;
-# }
-#
-# public static void callIface(Iface m) {
-# System.out.println("Calling non-abstract function on Iface");
-# System.out.println(m.charge());
-# System.out.println("Calling abstract function on Iface");
-# try {
-# System.out.println(m.sayHi());
-# System.out.println("Unexpected no error Thrown on Iface");
-# } catch (AbstractMethodError e) {
-# System.out.println("Expected AME Thrown on Iface");
-# } catch (IncompatibleClassChangeError e) {
-# System.out.println("Unexpected ICCE Thrown on Iface");
-# }
-# System.out.println("Calling non-abstract function on Iface");
-# System.out.println(m.charge());
-# return;
-# }
-#
-# public static void callIface2(Iface2 m) {
-# System.out.println("Calling abstract function on Iface2");
-# try {
-# System.out.println(m.sayHi());
-# System.out.println("Unexpected no error Thrown on Iface2");
-# } catch (AbstractMethodError e) {
-# System.out.println("Expected AME Thrown on Iface2");
-# } catch (IncompatibleClassChangeError e) {
-# System.out.println("Unexpected ICCE Thrown on Iface2");
-# }
-# return;
-# }
-# }
-
-.class public LMain;
-.super Ljava/lang/Object;
-.implements LIface;
-.implements LIface2;
-.implements LIface3;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public static main([Ljava/lang/String;)V
- .locals 3
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
-
- const-string v0, "Create Main instance"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- new-instance v2, LMain;
- invoke-direct {v2}, LMain;-><init>()V
-
- const-string v0, "Calling functions on concrete Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-static {v2}, LMain;->callMain(LMain;)V
-
- const-string v0, "Calling functions on interface Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-static {v2}, LMain;->callIface(LIface;)V
-
- const-string v0, "Calling functions on interface Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- invoke-static {v2}, LMain;->callIface2(LIface2;)V
-
- return-void
-.end method
-
-.method public static callIface(LIface;)V
- .locals 2
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "Calling non-abstract function on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-interface {p0}, LIface;->charge()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Calling abstract function on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- :try_start
- invoke-interface {p0}, LIface;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Unexpected no error Thrown on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- goto :error_end
- :try_end
- .catch Ljava/lang/AbstractMethodError; {:try_start .. :try_end} :AME_error_start
- .catch Ljava/lang/IncompatibleClassChangeError; {:try_start .. :try_end} :ICCE_error_start
- :AME_error_start
- const-string v0, "Expected AME Thrown on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :ICCE_error_start
- const-string v0, "Unexpected ICCE Thrown on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :error_end
- const-string v0, "Calling non-abstract function on Iface"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-interface {p0}, LIface;->charge()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- return-void
-.end method
-
-.method public static callIface2(LIface2;)V
- .locals 2
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "Calling abstract function on Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- :try_start
- invoke-interface {p0}, LIface2;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Unexpected no error Thrown on Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- goto :error_end
- :try_end
- .catch Ljava/lang/AbstractMethodError; {:try_start .. :try_end} :AME_error_start
- .catch Ljava/lang/IncompatibleClassChangeError; {:try_start .. :try_end} :ICCE_error_start
- :AME_error_start
- const-string v0, "Expected AME Thrown on Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :ICCE_error_start
- const-string v0, "Unexpected ICCE Thrown on Iface2"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :error_end
-
- return-void
-.end method
-
-.method public static callMain(LMain;)V
- .locals 2
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "Calling non-abstract function on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-virtual {p0}, LMain;->charge()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Calling abstract function on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- :try_start
- invoke-virtual {p0}, LMain;->sayHi()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "Unexpected no error Thrown on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- goto :error_end
- :try_end
- .catch Ljava/lang/AbstractMethodError; {:try_start .. :try_end} :AME_error_start
- .catch Ljava/lang/IncompatibleClassChangeError; {:try_start .. :try_end} :ICCE_error_start
- :AME_error_start
- const-string v0, "Expected AME Thrown on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :ICCE_error_start
- const-string v0, "Unexpected ICCE Thrown on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- goto :error_end
- :error_end
- const-string v0, "Calling non-abstract function on Main"
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- invoke-virtual {p0}, LMain;->charge()Ljava/lang/String;
- move-result-object v0
- invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- return-void
-.end method
diff --git a/test/967-default-ame/src/Iface.java b/test/967-default-ame/src/Iface.java
new file mode 100644
index 0000000..2131ed8
--- /dev/null
+++ b/test/967-default-ame/src/Iface.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface {
+ public default String sayHi() {
+ return "Hi";
+ }
+ public default String charge() {
+ return "CHARGE";
+ }
+}
diff --git a/test/967-default-ame/build-src/Iface2.java b/test/967-default-ame/src/Iface2.java
similarity index 100%
rename from test/967-default-ame/build-src/Iface2.java
rename to test/967-default-ame/src/Iface2.java
diff --git a/test/967-default-ame/build-src/Iface3.java b/test/967-default-ame/src/Iface3.java
similarity index 100%
rename from test/967-default-ame/build-src/Iface3.java
rename to test/967-default-ame/src/Iface3.java
diff --git a/test/967-default-ame/src/Main.java b/test/967-default-ame/src/Main.java
new file mode 100644
index 0000000..3e48062
--- /dev/null
+++ b/test/967-default-ame/src/Main.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+class Main implements Iface, Iface2, Iface3 {
+ public static void main(String[] args) {
+ System.out.println("Create Main instance");
+ Main m = new Main();
+ System.out.println("Calling functions on concrete Main");
+ callMain(m);
+ System.out.println("Calling functions on interface Iface");
+ callIface(m);
+ System.out.println("Calling functions on interface Iface2");
+ callIface2(m);
+ }
+ public static void callMain(Main m) {
+ System.out.println("Calling non-abstract function on Main");
+ System.out.println(m.charge());
+ System.out.println("Calling abstract function on Main");
+ try {
+ System.out.println(m.sayHi());
+ System.out.println("Unexpected no error Thrown on Main");
+ } catch (AbstractMethodError e) {
+ System.out.println("Expected AME Thrown on Main");
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("Unexpected ICCE Thrown on Main");
+ }
+ System.out.println("Calling non-abstract function on Main");
+ System.out.println(m.charge());
+ return;
+ }
+ public static void callIface(Iface m) {
+ System.out.println("Calling non-abstract function on Iface");
+ System.out.println(m.charge());
+ System.out.println("Calling abstract function on Iface");
+ try {
+ System.out.println(m.sayHi());
+ System.out.println("Unexpected no error Thrown on Iface");
+ } catch (AbstractMethodError e) {
+ System.out.println("Expected AME Thrown on Iface");
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("Unexpected ICCE Thrown on Iface");
+ }
+ System.out.println("Calling non-abstract function on Iface");
+ System.out.println(m.charge());
+ return;
+ }
+ public static void callIface2(Iface2 m) {
+ System.out.println("Calling abstract function on Iface2");
+ try {
+ System.out.println(m.sayHi());
+ System.out.println("Unexpected no error Thrown on Iface2");
+ } catch (AbstractMethodError e) {
+ System.out.println("Expected AME Thrown on Iface2");
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("Unexpected ICCE Thrown on Iface2");
+ }
+ return;
+ }
+}
diff --git a/test/967-default-ame/src2/Iface.java b/test/967-default-ame/src2/Iface.java
new file mode 100644
index 0000000..2131ed8
--- /dev/null
+++ b/test/967-default-ame/src2/Iface.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface {
+ public default String sayHi() {
+ return "Hi";
+ }
+ public default String charge() {
+ return "CHARGE";
+ }
+}
diff --git a/test/967-default-ame/src2/Iface2.java b/test/967-default-ame/src2/Iface2.java
new file mode 100644
index 0000000..0e4fb5f
--- /dev/null
+++ b/test/967-default-ame/src2/Iface2.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface2 extends Iface {
+ public String sayHi();
+}
diff --git a/test/967-default-ame/src2/Iface3.java b/test/967-default-ame/src2/Iface3.java
new file mode 100644
index 0000000..70fc33b
--- /dev/null
+++ b/test/967-default-ame/src2/Iface3.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface3 {
+ public String charge();
+}
diff --git a/test/969-iface-super/build b/test/969-iface-super/build
index b1ef320..e8f4ed0 100755
--- a/test/969-iface-super/build
+++ b/test/969-iface-super/build
@@ -17,27 +17,14 @@
# make us exit on a failure
set -e
-# Should we compile with Java source code. By default we will use Smali.
-USES_JAVA_SOURCE="false"
-if [[ $@ == *"--jvm"* ]]; then
- USES_JAVA_SOURCE="true"
-elif [[ "$USE_JACK" == "true" ]]; then
- if $JACK -D jack.java.source.version=1.8 2>/dev/null; then
- USES_JAVA_SOURCE="true"
- else
- echo "WARNING: Cannot use jack because it does not support JLS 1.8. Falling back to smali" >&2
- fi
+if [[ $@ != *"--jvm"* ]]; then
+ # Don't do anything with jvm
+ # Hard-wired use of experimental jack.
+ # TODO: fix this temporary work-around for default-methods, see b/19467889
+ export USE_JACK=true
fi
-# Generate the smali Main.smali file or fail
-${ANDROID_BUILD_TOP}/art/test/utils/python/generate_smali_main.py ./smali
+# Generate the Main.java file or fail
+${ANDROID_BUILD_TOP}/art/test/utils/python/generate_java_main.py ./src
-if [[ "$USES_JAVA_SOURCE" == "true" ]]; then
- # We are compiling java code, create it.
- mkdir -p src
- ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
- # Ignore the smali directory.
- EXTRA_ARGS="--no-smali"
-fi
-
-./default-build "$@" "$EXTRA_ARGS" --experimental default-methods
+./default-build "$@" --experimental default-methods
diff --git a/test/969-iface-super/expected.txt b/test/969-iface-super/expected.txt
index f310d10..f7a63d6 100644
--- a/test/969-iface-super/expected.txt
+++ b/test/969-iface-super/expected.txt
@@ -1,39 +1,39 @@
Testing for type A
A-virtual A.SayHi()='Hello '
-A-interface iface.SayHi()='Hello '
+A-interface Iface.SayHi()='Hello '
End testing for type A
Testing for type B
B-virtual B.SayHi()='Hello Hello '
-B-interface iface.SayHi()='Hello Hello '
-B-interface iface2.SayHi()='Hello Hello '
+B-interface Iface.SayHi()='Hello Hello '
+B-interface Iface2.SayHi()='Hello Hello '
End testing for type B
Testing for type C
C-virtual C.SayHi()='Hello and welcome '
-C-interface iface.SayHi()='Hello and welcome '
+C-interface Iface.SayHi()='Hello and welcome '
End testing for type C
Testing for type D
D-virtual D.SayHi()='Hello Hello and welcome '
-D-interface iface.SayHi()='Hello Hello and welcome '
-D-interface iface2.SayHi()='Hello Hello and welcome '
+D-interface Iface.SayHi()='Hello Hello and welcome '
+D-interface Iface2.SayHi()='Hello Hello and welcome '
End testing for type D
Testing for type E
E-virtual E.SayHi()='Hello there!'
-E-interface iface.SayHi()='Hello there!'
-E-interface iface3.SayHi()='Hello there!'
+E-interface Iface.SayHi()='Hello there!'
+E-interface Iface3.SayHi()='Hello there!'
End testing for type E
Testing for type F
F-virtual E.SayHi()='Hello there!'
F-virtual F.SayHi()='Hello there!'
-F-interface iface.SayHi()='Hello there!'
-F-interface iface3.SayHi()='Hello there!'
+F-interface Iface.SayHi()='Hello there!'
+F-interface Iface3.SayHi()='Hello there!'
F-virtual F.SaySurprisedHi()='Hello there!!'
End testing for type F
Testing for type G
G-virtual E.SayHi()='Hello there!?'
G-virtual F.SayHi()='Hello there!?'
G-virtual G.SayHi()='Hello there!?'
-G-interface iface.SayHi()='Hello there!?'
-G-interface iface3.SayHi()='Hello there!?'
+G-interface Iface.SayHi()='Hello there!?'
+G-interface Iface3.SayHi()='Hello there!?'
G-virtual F.SaySurprisedHi()='Hello there!!'
G-virtual G.SaySurprisedHi()='Hello there!!'
G-virtual G.SayVerySurprisedHi()='Hello there!!!'
@@ -42,6 +42,6 @@
H-virtual H.SayConfusedHi()='Hello ?!'
H-virtual A.SayHi()='Hello ?'
H-virtual H.SayHi()='Hello ?'
-H-interface iface.SayHi()='Hello ?'
+H-interface Iface.SayHi()='Hello ?'
H-virtual H.SaySurprisedHi()='Hello !'
End testing for type H
diff --git a/test/969-iface-super/smali/A.smali b/test/969-iface-super/smali/A.smali
deleted file mode 100644
index e7760a1..0000000
--- a/test/969-iface-super/smali/A.smali
+++ /dev/null
@@ -1,28 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public class A implements iface {
-# }
-
-.class public LA;
-.super Ljava/lang/Object;
-.implements Liface;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
diff --git a/test/969-iface-super/smali/B.smali b/test/969-iface-super/smali/B.smali
deleted file mode 100644
index e529d05..0000000
--- a/test/969-iface-super/smali/B.smali
+++ /dev/null
@@ -1,28 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public class B implements iface2 {
-# }
-
-.class public LB;
-.super Ljava/lang/Object;
-.implements Liface2;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
diff --git a/test/969-iface-super/smali/C.smali b/test/969-iface-super/smali/C.smali
deleted file mode 100644
index 6fbb0c4..0000000
--- a/test/969-iface-super/smali/C.smali
+++ /dev/null
@@ -1,41 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public class C implements iface {
-# public String SayHi() {
-# return iface.super.SayHi() + " and welcome ";
-# }
-# }
-
-.class public LC;
-.super Ljava/lang/Object;
-.implements Liface;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public SayHi()Ljava/lang/String;
- .locals 2
- invoke-super {p0}, Liface;->SayHi()Ljava/lang/String;
- move-result-object v0
- const-string v1, " and welcome "
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/969-iface-super/smali/D.smali b/test/969-iface-super/smali/D.smali
deleted file mode 100644
index ecd4629..0000000
--- a/test/969-iface-super/smali/D.smali
+++ /dev/null
@@ -1,41 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public class D implements iface2 {
-# public String SayHi() {
-# return iface2.super.SayHi() + " and welcome ";
-# }
-# }
-
-.class public LD;
-.super Ljava/lang/Object;
-.implements Liface2;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public SayHi()Ljava/lang/String;
- .locals 2
- invoke-super {p0}, Liface2;->SayHi()Ljava/lang/String;
- move-result-object v0
- const-string v1, " and welcome "
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/969-iface-super/smali/E.smali b/test/969-iface-super/smali/E.smali
deleted file mode 100644
index 558aaea..0000000
--- a/test/969-iface-super/smali/E.smali
+++ /dev/null
@@ -1,41 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public class E implements iface3 {
-# public String SayHi() {
-# return iface3.super.SayHi() + " there!";
-# }
-# }
-
-.class public LE;
-.super Ljava/lang/Object;
-.implements Liface3;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-.method public SayHi()Ljava/lang/String;
- .locals 2
- invoke-super {p0}, Liface3;->SayHi()Ljava/lang/String;
- move-result-object v0
- const-string v1, " there!"
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/969-iface-super/smali/F.smali b/test/969-iface-super/smali/F.smali
deleted file mode 100644
index c402d5c..0000000
--- a/test/969-iface-super/smali/F.smali
+++ /dev/null
@@ -1,40 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public class F extends E {
-# public String SaySurprisedHi() {
-# return super.SayHi() + "!";
-# }
-# }
-
-.class public LF;
-.super LE;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, LE;-><init>()V
- return-void
-.end method
-
-.method public SaySurprisedHi()Ljava/lang/String;
- .registers 2
- invoke-super {p0}, LE;->SayHi()Ljava/lang/String;
- move-result-object v0
- const-string v1, "!"
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/969-iface-super/smali/G.smali b/test/969-iface-super/smali/G.smali
deleted file mode 100644
index 45705e6..0000000
--- a/test/969-iface-super/smali/G.smali
+++ /dev/null
@@ -1,53 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public class G extends F {
-# public String SayHi() {
-# return super.SayHi() + "?";
-# }
-# public String SayVerySurprisedHi() {
-# return super.SaySurprisedHi() + "!";
-# }
-# }
-
-.class public LG;
-.super LF;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, LF;-><init>()V
- return-void
-.end method
-
-.method public SayHi()Ljava/lang/String;
- .locals 2
- invoke-super {p0}, LF;->SayHi()Ljava/lang/String;
- move-result-object v0
- const-string v1, "?"
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
-
-.method public SayVerySurprisedHi()Ljava/lang/String;
- .locals 2
- invoke-super {p0}, LF;->SaySurprisedHi()Ljava/lang/String;
- move-result-object v0
- const-string v1, "!"
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/969-iface-super/smali/H.smali b/test/969-iface-super/smali/H.smali
deleted file mode 100644
index 12f246b..0000000
--- a/test/969-iface-super/smali/H.smali
+++ /dev/null
@@ -1,66 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public class H extends A {
-# public String SayHi() {
-# return super.SayHi() + "?";
-# }
-# public String SaySurprisedHi() {
-# return super.SayHi() + "!";
-# }
-# public String SayConfusedHi() {
-# return SayHi() + "!";
-# }
-# }
-
-.class public LH;
-.super LA;
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {p0}, LA;-><init>()V
- return-void
-.end method
-
-.method public SayHi()Ljava/lang/String;
- .locals 2
- invoke-super {p0}, LA;->SayHi()Ljava/lang/String;
- move-result-object v0
- const-string v1, "?"
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
-
-.method public SaySurprisedHi()Ljava/lang/String;
- .locals 2
- invoke-super {p0}, LA;->SayHi()Ljava/lang/String;
- move-result-object v0
- const-string v1, "!"
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
-
-.method public SayConfusedHi()Ljava/lang/String;
- .locals 2
- invoke-virtual {p0}, LH;->SayHi()Ljava/lang/String;
- move-result-object v0
- const-string v1, "!"
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/969-iface-super/smali/classes.xml b/test/969-iface-super/smali/classes.xml
deleted file mode 100644
index 4d205bd..0000000
--- a/test/969-iface-super/smali/classes.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<data>
- <classes>
- <class name="A" super="java/lang/Object">
- <implements>
- <item>iface</item>
- </implements>
- <methods> </methods>
- </class>
-
- <class name="B" super="java/lang/Object">
- <implements>
- <item>iface2</item>
- </implements>
- <methods> </methods>
- </class>
-
- <class name="C" super="java/lang/Object">
- <implements>
- <item>iface</item>
- </implements>
- <methods> </methods>
- </class>
-
- <class name="D" super="java/lang/Object">
- <implements>
- <item>iface2</item>
- </implements>
- <methods> </methods>
- </class>
-
- <class name="E" super="java/lang/Object">
- <implements>
- <item>iface3</item>
- </implements>
- <methods> </methods>
- </class>
-
- <class name="F" super="E">
- <implements> </implements>
- <methods>
- <item>SaySurprisedHi</item>
- </methods>
- </class>
-
- <class name="G" super="F">
- <implements> </implements>
- <methods>
- <item>SayVerySurprisedHi</item>
- </methods>
- </class>
-
- <class name="H" super="A">
- <implements> </implements>
- <methods>
- <item>SaySurprisedHi</item>
- <item>SayConfusedHi</item>
- </methods>
- </class>
- </classes>
-
- <interfaces>
- <interface name="iface" super="java/lang/Object">
- <implements> </implements>
- <methods>
- <item>SayHi</item>
- </methods>
- </interface>
-
- <interface name="iface2" super="java/lang/Object">
- <implements>
- <item>iface</item>
- </implements>
- <methods> </methods>
- </interface>
-
- <interface name="iface3" super="java/lang/Object">
- <implements>
- <item>iface</item>
- </implements>
- <methods> </methods>
- </interface>
- </interfaces>
-</data>
diff --git a/test/969-iface-super/smali/iface.smali b/test/969-iface-super/smali/iface.smali
deleted file mode 100644
index 08bb93d..0000000
--- a/test/969-iface-super/smali/iface.smali
+++ /dev/null
@@ -1,30 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface iface {
-# public default String SayHi() {
-# return "Hello ";
-# }
-# }
-
-.class public abstract interface Liface;
-.super Ljava/lang/Object;
-
-.method public SayHi()Ljava/lang/String;
- .locals 1
- const-string v0, "Hello "
- return-object v0
-.end method
diff --git a/test/969-iface-super/smali/iface2.smali b/test/969-iface-super/smali/iface2.smali
deleted file mode 100644
index ce6f864..0000000
--- a/test/969-iface-super/smali/iface2.smali
+++ /dev/null
@@ -1,36 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface iface2 extends iface {
-# public default String SayHi() {
-# return iface.super.SayHi() + iface.super.SayHi();
-# }
-# }
-
-.class public abstract interface Liface2;
-.super Ljava/lang/Object;
-.implements Liface;
-
-.method public SayHi()Ljava/lang/String;
- .locals 2
- invoke-super {p0}, Liface;->SayHi()Ljava/lang/String;
- move-result-object v0
- invoke-super {p0}, Liface;->SayHi()Ljava/lang/String;
- move-result-object v1
- invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v0
- return-object v0
-.end method
diff --git a/test/969-iface-super/smali/iface3.smali b/test/969-iface-super/smali/iface3.smali
deleted file mode 100644
index bf20036..0000000
--- a/test/969-iface-super/smali/iface3.smali
+++ /dev/null
@@ -1,22 +0,0 @@
-# /*
-# * Copyright (C) 2015 The Android Open Source Project
-# *
-# * Licensed under the Apache License, Version 2.0 (the "License");
-# * you may not use this file except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.apache.org/licenses/LICENSE-2.0
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# */
-#
-# public interface iface3 extends iface {
-# }
-
-.class public abstract interface Liface3;
-.super Ljava/lang/Object;
-.implements Liface;
diff --git a/test/969-iface-super/src/A.java b/test/969-iface-super/src/A.java
new file mode 100644
index 0000000..47db14b
--- /dev/null
+++ b/test/969-iface-super/src/A.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class A implements Iface { }
diff --git a/test/969-iface-super/src/B.java b/test/969-iface-super/src/B.java
new file mode 100644
index 0000000..70f63a2
--- /dev/null
+++ b/test/969-iface-super/src/B.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class B implements Iface2 { }
diff --git a/test/969-iface-super/src/C.java b/test/969-iface-super/src/C.java
new file mode 100644
index 0000000..0fa0b92
--- /dev/null
+++ b/test/969-iface-super/src/C.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class C implements Iface {
+ public String SayHi() {
+ return Iface.super.SayHi() + " and welcome ";
+ }
+}
diff --git a/test/969-iface-super/src/D.java b/test/969-iface-super/src/D.java
new file mode 100644
index 0000000..8a607c3
--- /dev/null
+++ b/test/969-iface-super/src/D.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class D implements Iface2 {
+ public String SayHi() {
+ return Iface2.super.SayHi() + " and welcome ";
+ }
+}
diff --git a/test/969-iface-super/src/E.java b/test/969-iface-super/src/E.java
new file mode 100644
index 0000000..d5942b2
--- /dev/null
+++ b/test/969-iface-super/src/E.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class E implements Iface3 {
+ public String SayHi() {
+ return Iface3.super.SayHi() + " there!";
+ }
+}
diff --git a/test/969-iface-super/src/F.java b/test/969-iface-super/src/F.java
new file mode 100644
index 0000000..610bcb1
--- /dev/null
+++ b/test/969-iface-super/src/F.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class F extends E {
+ public String SaySurprisedHi() {
+ return super.SayHi() + "!";
+ }
+}
diff --git a/test/969-iface-super/src/G.java b/test/969-iface-super/src/G.java
new file mode 100644
index 0000000..edaf3a9
--- /dev/null
+++ b/test/969-iface-super/src/G.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class G extends F {
+ public String SayHi() {
+ return super.SayHi() + "?";
+ }
+ public String SayVerySurprisedHi() {
+ return super.SaySurprisedHi() + "!";
+ }
+}
diff --git a/test/969-iface-super/src/H.java b/test/969-iface-super/src/H.java
new file mode 100644
index 0000000..744bda6
--- /dev/null
+++ b/test/969-iface-super/src/H.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class H extends A {
+ public String SayHi() {
+ return super.SayHi() + "?";
+ }
+ public String SaySurprisedHi() {
+ return super.SayHi() + "!";
+ }
+ public String SayConfusedHi() {
+ return SayHi() + "!";
+ }
+}
diff --git a/test/969-iface-super/src/Iface.java b/test/969-iface-super/src/Iface.java
new file mode 100644
index 0000000..ece5e59
--- /dev/null
+++ b/test/969-iface-super/src/Iface.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface {
+ public default String SayHi() {
+ return "Hello ";
+ }
+}
diff --git a/test/969-iface-super/src/Iface2.java b/test/969-iface-super/src/Iface2.java
new file mode 100644
index 0000000..d74ee6d
--- /dev/null
+++ b/test/969-iface-super/src/Iface2.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface2 extends Iface {
+ public default String SayHi() {
+ return Iface.super.SayHi() + Iface.super.SayHi();
+ }
+}
diff --git a/test/969-iface-super/src/Iface3.java b/test/969-iface-super/src/Iface3.java
new file mode 100644
index 0000000..10b010c
--- /dev/null
+++ b/test/969-iface-super/src/Iface3.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public interface Iface3 extends Iface { }
diff --git a/test/969-iface-super/src/classes.xml b/test/969-iface-super/src/classes.xml
new file mode 100644
index 0000000..4c3dae4
--- /dev/null
+++ b/test/969-iface-super/src/classes.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<data>
+ <classes>
+ <class name="A" super="java/lang/Object">
+ <implements>
+ <item>Iface</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="B" super="java/lang/Object">
+ <implements>
+ <item>Iface2</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="C" super="java/lang/Object">
+ <implements>
+ <item>Iface</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="D" super="java/lang/Object">
+ <implements>
+ <item>Iface2</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="E" super="java/lang/Object">
+ <implements>
+ <item>Iface3</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="F" super="E">
+ <implements> </implements>
+ <methods>
+ <item>SaySurprisedHi</item>
+ </methods>
+ </class>
+
+ <class name="G" super="F">
+ <implements> </implements>
+ <methods>
+ <item>SayVerySurprisedHi</item>
+ </methods>
+ </class>
+
+ <class name="H" super="A">
+ <implements> </implements>
+ <methods>
+ <item>SaySurprisedHi</item>
+ <item>SayConfusedHi</item>
+ </methods>
+ </class>
+ </classes>
+
+ <interfaces>
+ <interface name="Iface" super="java/lang/Object">
+ <implements> </implements>
+ <methods>
+ <item>SayHi</item>
+ </methods>
+ </interface>
+
+ <interface name="Iface2" super="java/lang/Object">
+ <implements>
+ <item>Iface</item>
+ </implements>
+ <methods> </methods>
+ </interface>
+
+ <interface name="Iface3" super="java/lang/Object">
+ <implements>
+ <item>Iface</item>
+ </implements>
+ <methods> </methods>
+ </interface>
+ </interfaces>
+</data>
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 167ad85..c4f0171 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -222,8 +222,14 @@
# Disable 097-duplicate-method while investigation (broken by latest Jack release, b/27358065)
+# Disable 137-cfi (b/27391690).
+# Disable 536-checker-needs-access-check and 537-checker-inline-and-unverified (b/27425061)
+# Disable 577-profile-foreign-dex (b/27454772).
TEST_ART_BROKEN_ALL_TARGET_TESTS := \
- 097-duplicate-method
+ 097-duplicate-method \
+ 536-checker-needs-access-check \
+ 537-checker-inline-and-unverified \
+ 577-profile-foreign-dex \
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
$(COMPILER_TYPES), $(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
@@ -535,7 +541,9 @@
TEST_ART_BROKEN_OPTIMIZING_DEBUGGABLE_RUN_TESTS :=
# Tests that should fail in the read barrier configuration with the interpreter.
-TEST_ART_BROKEN_INTERPRETER_READ_BARRIER_RUN_TESTS :=
+# 145: Test sometimes times out in read barrier configuration (b/27467554).
+TEST_ART_BROKEN_INTERPRETER_READ_BARRIER_RUN_TESTS := \
+ 145-alloc-tracking-stress
# Tests that should fail in the read barrier configuration with the default (Quick) compiler (AOT).
# Quick has no support for read barriers and punts to the interpreter, so this list is composed of
@@ -545,6 +553,7 @@
$(TEST_ART_BROKEN_INTERPRETER_RUN_TESTS)
# Tests that should fail in the read barrier configuration with the Optimizing compiler (AOT).
+# 145: Test sometimes times out in read barrier configuration (b/27467554).
# 484: Baker's fast path based read barrier compiler instrumentation generates code containing
# more parallel moves on x86, thus some Checker assertions may fail.
# 527: On ARM64, the read barrier instrumentation does not support the HArm64IntermediateAddress
@@ -552,6 +561,7 @@
# 537: Expects an array copy to be intrinsified on x86-64, but calling-on-slowpath intrinsics are
# not yet handled in the read barrier configuration.
TEST_ART_BROKEN_OPTIMIZING_READ_BARRIER_RUN_TESTS := \
+ 145-alloc-tracking-stress \
484-checker-register-hints \
527-checker-array-access-split \
537-checker-arraycopy
diff --git a/test/run-test b/test/run-test
index f1875d7..d0f93b9 100755
--- a/test/run-test
+++ b/test/run-test
@@ -677,11 +677,7 @@
# Tests named '<number>-checker-*' will also have their CFGs verified with
# Checker when compiled with Optimizing on host.
if [[ "$TEST_NAME" =~ ^[0-9]+-checker- ]]; then
- # Jack does not necessarily generate the same DEX output than dx. Because these tests depend
- # on a particular DEX output, keep building them with dx for now (b/19467889).
- USE_JACK="false"
-
- if [ "$runtime" = "art" -a "$image_suffix" = "-optimizing" ]; then
+ if [ "$runtime" = "art" -a "$image_suffix" = "-optimizing" -a "$USE_JACK" = "true" ]; then
# Optimizing has read barrier support for certain architectures
# only. On other architectures, compiling is disabled when read
# barriers are enabled, meaning that we do not produce a CFG file
diff --git a/test/utils/python/generate_java_main.py b/test/utils/python/generate_java_main.py
new file mode 100755
index 0000000..f66d0dd
--- /dev/null
+++ b/test/utils/python/generate_java_main.py
@@ -0,0 +1,309 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Generate Java Main file from a classes.xml file.
+"""
+
+import os
+import sys
+from pathlib import Path
+
+BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+if BUILD_TOP is None:
+ print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
+ sys.exit(1)
+
+# Allow us to import utils and mixins.
+sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
+
+from testgen.utils import get_copyright
+import testgen.mixins as mixins
+
+from collections import namedtuple
+import itertools
+import functools
+import xml.etree.ElementTree as ET
+
+class MainClass(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin):
+ """
+ A mainclass and main method for this test.
+ """
+
+ MAIN_CLASS_TEMPLATE = """{copyright}
+class Main {{
+{test_groups}
+{test_funcs}
+{main_func}
+}}
+"""
+
+ MAIN_FUNCTION_TEMPLATE = """
+ public static void main(String[] args) {{
+ {test_group_invoke}
+ }}
+"""
+
+ TEST_GROUP_INVOKE_TEMPLATE = """
+ {test_name}();
+"""
+
+ def __init__(self):
+ """
+ Initialize this MainClass
+ """
+ self.tests = set()
+ self.global_funcs = set()
+
+ def add_instance(self, it):
+ """
+ Add an instance test for the given class
+ """
+ self.tests.add(it)
+
+ def add_func(self, f):
+ """
+ Add a function to the class
+ """
+ self.global_funcs.add(f)
+
+ def get_name(self):
+ """
+ Get the name of this class
+ """
+ return "Main"
+
+ def __str__(self):
+ """
+ Print this class
+ """
+ all_tests = sorted(self.tests)
+ test_invoke = ""
+ test_groups = ""
+ for t in all_tests:
+ test_groups += str(t)
+ for t in sorted(all_tests):
+ test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
+ main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)
+
+ funcs = ""
+ for f in self.global_funcs:
+ funcs += str(f)
+ return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright('java'),
+ test_groups=test_groups,
+ main_func=main_func, test_funcs=funcs)
+
+
+class InstanceTest(mixins.Named, mixins.NameComparableMixin):
+ """
+ A method that runs tests for a particular concrete type, It calls the test
+ cases for running it in all possible ways.
+ """
+
+ INSTANCE_TEST_TEMPLATE = """
+ public static void {test_name}() {{
+ System.out.println("Testing for type {ty}");
+ String s = "{ty}";
+ {ty} v = new {ty}();
+
+ {invokes}
+
+ System.out.println("End testing for type {ty}");
+ }}
+"""
+
+ TEST_INVOKE_TEMPLATE = """
+ {fname}(s, v);
+"""
+
+ def __init__(self, main, ty):
+ """
+ Initialize this test group for the given type
+ """
+ self.ty = ty
+ self.main = main
+ self.funcs = set()
+ self.main.add_instance(self)
+
+ def get_name(self):
+ """
+ Get the name of this test group
+ """
+ return "TEST_NAME_"+self.ty
+
+ def add_func(self, f):
+ """
+ Add a test function to this test group
+ """
+ self.main.add_func(f)
+ self.funcs.add(f)
+
+ def __str__(self):
+ """
+ Returns the java code for this function
+ """
+ func_invokes = ""
+ for f in sorted(self.funcs, key=lambda a: (a.func, a.farg)):
+ func_invokes += self.TEST_INVOKE_TEMPLATE.format(fname=f.get_name(),
+ farg=f.farg)
+
+ return self.INSTANCE_TEST_TEMPLATE.format(test_name=self.get_name(), ty=self.ty,
+ invokes=func_invokes)
+
+class Func(mixins.Named, mixins.NameComparableMixin):
+ """
+ A single test case that attempts to invoke a function on receiver of a given type.
+ """
+
+ TEST_FUNCTION_TEMPLATE = """
+ public static void {fname}(String s, {farg} v) {{
+ try {{
+ System.out.printf("%s-{invoke_type:<9} {farg:>9}.{callfunc}()='%s'\\n", s, v.{callfunc}());
+ return;
+ }} catch (Error e) {{
+ System.out.printf("%s-{invoke_type} on {farg}: {callfunc}() threw exception!\\n", s);
+ e.printStackTrace(System.out);
+ }}
+ }}
+"""
+
+ def __init__(self, func, farg, invoke):
+ """
+ Initialize this test function for the given invoke type and argument
+ """
+ self.func = func
+ self.farg = farg
+ self.invoke = invoke
+
+ def get_name(self):
+ """
+ Get the name of this test
+ """
+ return "Test_Func_{}_{}_{}".format(self.func, self.farg, self.invoke)
+
+ def __str__(self):
+ """
+ Get the java code for this test function
+ """
+ return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(),
+ farg=self.farg,
+ invoke_type=self.invoke,
+ callfunc=self.func)
+
+def flatten_classes(classes, c):
+ """
+ Iterate over all the classes 'c' can be used as
+ """
+ while c:
+ yield c
+ c = classes.get(c.super_class)
+
+def flatten_class_methods(classes, c):
+ """
+ Iterate over all the methods 'c' can call
+ """
+ for c1 in flatten_classes(classes, c):
+ yield from c1.methods
+
+def flatten_interfaces(dat, c):
+ """
+ Iterate over all the interfaces 'c' transitively implements
+ """
+ def get_ifaces(cl):
+ for i2 in cl.implements:
+ yield dat.interfaces[i2]
+ yield from get_ifaces(dat.interfaces[i2])
+
+ for cl in flatten_classes(dat.classes, c):
+ yield from get_ifaces(cl)
+
+def flatten_interface_methods(dat, i):
+ """
+ Iterate over all the interface methods 'c' can call
+ """
+ yield from i.methods
+ for i2 in flatten_interfaces(dat, i):
+ yield from i2.methods
+
+def make_main_class(dat):
+ """
+ Creates a Main.java file that runs all the tests
+ """
+ m = MainClass()
+ for c in dat.classes.values():
+ i = InstanceTest(m, c.name)
+ for clazz in flatten_classes(dat.classes, c):
+ for meth in flatten_class_methods(dat.classes, clazz):
+ i.add_func(Func(meth, clazz.name, 'virtual'))
+ for iface in flatten_interfaces(dat, clazz):
+ for meth in flatten_interface_methods(dat, iface):
+ i.add_func(Func(meth, clazz.name, 'virtual'))
+ i.add_func(Func(meth, iface.name, 'interface'))
+ return m
+
+class TestData(namedtuple("TestData", ['classes', 'interfaces'])):
+ """
+ A class representing the classes.xml document.
+ """
+ pass
+
+class Clazz(namedtuple("Clazz", ["name", "methods", "super_class", "implements"])):
+ """
+ A class representing a class element in the classes.xml document.
+ """
+ pass
+
+class IFace(namedtuple("IFace", ["name", "methods", "super_class", "implements"])):
+ """
+ A class representing an interface element in the classes.xml document.
+ """
+ pass
+
+def parse_xml(xml):
+ """
+ Parse the xml description of this test.
+ """
+ classes = dict()
+ ifaces = dict()
+ root = ET.fromstring(xml)
+ for iface in root.find("interfaces"):
+ name = iface.attrib['name']
+ implements = [a.text for a in iface.find("implements")]
+ methods = [a.text for a in iface.find("methods")]
+ ifaces[name] = IFace(name = name,
+ super_class = iface.attrib['super'],
+ methods = methods,
+ implements = implements)
+ for clazz in root.find('classes'):
+ name = clazz.attrib['name']
+ implements = [a.text for a in clazz.find("implements")]
+ methods = [a.text for a in clazz.find("methods")]
+ classes[name] = Clazz(name = name,
+ super_class = clazz.attrib['super'],
+ methods = methods,
+ implements = implements)
+ return TestData(classes, ifaces)
+
+def main(argv):
+ java_dir = Path(argv[1])
+ if not java_dir.exists() or not java_dir.is_dir():
+ print("{} is not a valid java dir".format(java_dir), file=sys.stderr)
+ sys.exit(1)
+ class_data = parse_xml((java_dir / "classes.xml").open().read())
+ make_main_class(class_data).dump(java_dir)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/test/utils/python/generate_smali_main.py b/test/utils/python/generate_smali_main.py
deleted file mode 100755
index d796d31..0000000
--- a/test/utils/python/generate_smali_main.py
+++ /dev/null
@@ -1,376 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Generate Smali Main file from a classes.xml file.
-"""
-
-import os
-import sys
-from pathlib import Path
-
-BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
-if BUILD_TOP is None:
- print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
- sys.exit(1)
-
-# Allow us to import utils and mixins.
-sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
-
-from testgen.utils import get_copyright
-import testgen.mixins as mixins
-
-from collections import namedtuple
-import itertools
-import functools
-import xml.etree.ElementTree as ET
-
-class MainClass(mixins.DumpMixin, mixins.Named, mixins.SmaliFileMixin):
- """
- A mainclass and main method for this test.
- """
-
- MAIN_CLASS_TEMPLATE = """{copyright}
-.class public LMain;
-.super Ljava/lang/Object;
-
-# class Main {{
-
-.method public constructor <init>()V
- .registers 1
- invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
- return-void
-.end method
-
-{test_groups}
-
-{test_funcs}
-
-{main_func}
-
-# }}
-"""
-
- MAIN_FUNCTION_TEMPLATE = """
-# public static void main(String[] args) {{
-.method public static main([Ljava/lang/String;)V
- .locals 2
- sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
-
- {test_group_invoke}
-
- return-void
-.end method
-# }}
-"""
-
- TEST_GROUP_INVOKE_TEMPLATE = """
-# {test_name}();
- invoke-static {{}}, {test_name}()V
-"""
-
- def __init__(self):
- """
- Initialize this MainClass
- """
- self.tests = set()
- self.global_funcs = set()
-
- def add_instance(self, it):
- """
- Add an instance test for the given class
- """
- self.tests.add(it)
-
- def add_func(self, f):
- """
- Add a function to the class
- """
- self.global_funcs.add(f)
-
- def get_name(self):
- """
- Get the name of this class
- """
- return "Main"
-
- def __str__(self):
- """
- Print this class
- """
- all_tests = sorted(self.tests)
- test_invoke = ""
- test_groups = ""
- for t in all_tests:
- test_groups += str(t)
- for t in sorted(all_tests):
- test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
- main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)
-
- funcs = ""
- for f in self.global_funcs:
- funcs += str(f)
- return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright('smali'),
- test_groups=test_groups,
- main_func=main_func, test_funcs=funcs)
-
-
-class InstanceTest(mixins.Named, mixins.NameComparableMixin):
- """
- A method that runs tests for a particular concrete type, It calls the test
- cases for running it in all possible ways.
- """
-
- INSTANCE_TEST_TEMPLATE = """
-# public static void {test_name}() {{
-# System.out.println("Testing for type {ty}");
-# String s = "{ty}";
-# {ty} v = new {ty}();
-.method public static {test_name}()V
- .locals 3
- sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v0, "Testing for type {ty}"
- invoke-virtual {{v2,v0}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
-
- const-string v0, "{ty}"
- new-instance v1, L{ty};
- invoke-direct {{v1}}, L{ty};-><init>()V
-
- {invokes}
-
- const-string v0, "End testing for type {ty}"
- invoke-virtual {{v2,v0}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
- return-void
-.end method
-# System.out.println("End testing for type {ty}");
-# }}
-"""
-
- TEST_INVOKE_TEMPLATE = """
-# {fname}(s, v);
- invoke-static {{v0, v1}}, {fname}(Ljava/lang/String;L{farg};)V
-"""
-
- def __init__(self, main, ty):
- """
- Initialize this test group for the given type
- """
- self.ty = ty
- self.main = main
- self.funcs = set()
- self.main.add_instance(self)
-
- def get_name(self):
- """
- Get the name of this test group
- """
- return "TEST_NAME_"+self.ty
-
- def add_func(self, f):
- """
- Add a test function to this test group
- """
- self.main.add_func(f)
- self.funcs.add(f)
-
- def __str__(self):
- """
- Returns the smali code for this function
- """
- func_invokes = ""
- for f in sorted(self.funcs, key=lambda a: (a.func, a.farg)):
- func_invokes += self.TEST_INVOKE_TEMPLATE.format(fname=f.get_name(),
- farg=f.farg)
-
- return self.INSTANCE_TEST_TEMPLATE.format(test_name=self.get_name(), ty=self.ty,
- invokes=func_invokes)
-
-class Func(mixins.Named, mixins.NameComparableMixin):
- """
- A single test case that attempts to invoke a function on receiver of a given type.
- """
-
- TEST_FUNCTION_TEMPLATE = """
-# public static void {fname}(String s, {farg} v) {{
-# try {{
-# System.out.printf("%s-{invoke_type:<9} {farg:>9}.{callfunc}()='%s'\\n", s, v.{callfunc}());
-# return;
-# }} catch (Error e) {{
-# System.out.printf("%s-{invoke_type} on {farg}: {callfunc}() threw exception!\\n", s);
-# e.printStackTrace(System.out);
-# }}
-# }}
-.method public static {fname}(Ljava/lang/String;L{farg};)V
- .locals 7
- :call_{fname}_try_start
- const/4 v0, 2
- new-array v1,v0, [Ljava/lang/Object;
- const/4 v0, 0
- aput-object p0,v1,v0
-
- sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v3, "%s-{invoke_type:<9} {farg:>9}.{callfunc}()='%s'\\n"
-
- invoke-{invoke_type} {{p1}}, L{farg};->{callfunc}()Ljava/lang/String;
- move-result-object v4
- const/4 v0, 1
- aput-object v4, v1, v0
-
- invoke-virtual {{v2,v3,v1}}, Ljava/io/PrintStream;->printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
- return-void
- :call_{fname}_try_end
- .catch Ljava/lang/Error; {{:call_{fname}_try_start .. :call_{fname}_try_end}} :error_{fname}_start
- :error_{fname}_start
- move-exception v3
- const/4 v0, 1
- new-array v1,v0, [Ljava/lang/Object;
- const/4 v0, 0
- aput-object p0, v1, v0
- sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
- const-string v4, "%s-{invoke_type} on {farg}: {callfunc}() threw exception!\\n"
- invoke-virtual {{v2,v4,v1}}, Ljava/io/PrintStream;->printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
- invoke-virtual {{v3,v2}}, Ljava/lang/Error;->printStackTrace(Ljava/io/PrintStream;)V
- return-void
-.end method
-"""
-
- def __init__(self, func, farg, invoke):
- """
- Initialize this test function for the given invoke type and argument
- """
- self.func = func
- self.farg = farg
- self.invoke = invoke
-
- def get_name(self):
- """
- Get the name of this test
- """
- return "Test_Func_{}_{}_{}".format(self.func, self.farg, self.invoke)
-
- def __str__(self):
- """
- Get the smali code for this test function
- """
- return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(),
- farg=self.farg,
- invoke_type=self.invoke,
- callfunc=self.func)
-
-def flatten_classes(classes, c):
- """
- Iterate over all the classes 'c' can be used as
- """
- while c:
- yield c
- c = classes.get(c.super_class)
-
-def flatten_class_methods(classes, c):
- """
- Iterate over all the methods 'c' can call
- """
- for c1 in flatten_classes(classes, c):
- yield from c1.methods
-
-def flatten_interfaces(dat, c):
- """
- Iterate over all the interfaces 'c' transitively implements
- """
- def get_ifaces(cl):
- for i2 in cl.implements:
- yield dat.interfaces[i2]
- yield from get_ifaces(dat.interfaces[i2])
-
- for cl in flatten_classes(dat.classes, c):
- yield from get_ifaces(cl)
-
-def flatten_interface_methods(dat, i):
- """
- Iterate over all the interface methods 'c' can call
- """
- yield from i.methods
- for i2 in flatten_interfaces(dat, i):
- yield from i2.methods
-
-def make_main_class(dat):
- """
- Creates a Main.smali file that runs all the tests
- """
- m = MainClass()
- for c in dat.classes.values():
- i = InstanceTest(m, c.name)
- for clazz in flatten_classes(dat.classes, c):
- for meth in flatten_class_methods(dat.classes, clazz):
- i.add_func(Func(meth, clazz.name, 'virtual'))
- for iface in flatten_interfaces(dat, clazz):
- for meth in flatten_interface_methods(dat, iface):
- i.add_func(Func(meth, clazz.name, 'virtual'))
- i.add_func(Func(meth, iface.name, 'interface'))
- return m
-
-class TestData(namedtuple("TestData", ['classes', 'interfaces'])):
- """
- A class representing the classes.xml document.
- """
- pass
-
-class Clazz(namedtuple("Clazz", ["name", "methods", "super_class", "implements"])):
- """
- A class representing a class element in the classes.xml document.
- """
- pass
-
-class IFace(namedtuple("IFace", ["name", "methods", "super_class", "implements"])):
- """
- A class representing an interface element in the classes.xml document.
- """
- pass
-
-def parse_xml(xml):
- """
- Parse the xml description of this test.
- """
- classes = dict()
- ifaces = dict()
- root = ET.fromstring(xml)
- for iface in root.find("interfaces"):
- name = iface.attrib['name']
- implements = [a.text for a in iface.find("implements")]
- methods = [a.text for a in iface.find("methods")]
- ifaces[name] = IFace(name = name,
- super_class = iface.attrib['super'],
- methods = methods,
- implements = implements)
- for clazz in root.find('classes'):
- name = clazz.attrib['name']
- implements = [a.text for a in clazz.find("implements")]
- methods = [a.text for a in clazz.find("methods")]
- classes[name] = Clazz(name = name,
- super_class = clazz.attrib['super'],
- methods = methods,
- implements = implements)
- return TestData(classes, ifaces)
-
-def main(argv):
- smali_dir = Path(argv[1])
- if not smali_dir.exists() or not smali_dir.is_dir():
- print("{} is not a valid smali dir".format(smali_dir), file=sys.stderr)
- sys.exit(1)
- class_data = parse_xml((smali_dir / "classes.xml").open().read())
- make_main_class(class_data).dump(smali_dir)
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/tools/Android.mk b/tools/Android.mk
index 9a96f7a..bc2fd8c 100644
--- a/tools/Android.mk
+++ b/tools/Android.mk
@@ -19,21 +19,14 @@
# Copy the art shell script to the host's bin directory
include $(CLEAR_VARS)
LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE := art
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/art $(ACP)
- @echo "Copy: $(PRIVATE_MODULE) ($@)"
- $(copy-file-to-new-target)
- $(hide) chmod 755 $@
+LOCAL_SRC_FILES := art
+include $(BUILD_PREBUILT)
# Copy the art shell script to the target's bin directory
include $(CLEAR_VARS)
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE := art
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/art $(ACP)
- @echo "Copy: $(PRIVATE_MODULE) ($@)"
- $(copy-file-to-new-target)
- $(hide) chmod 755 $@
+LOCAL_SRC_FILES := art
+include $(BUILD_PREBUILT)
diff --git a/tools/ahat/Android.mk b/tools/ahat/Android.mk
index 6869b04..cfbafde 100644
--- a/tools/ahat/Android.mk
+++ b/tools/ahat/Android.mk
@@ -35,16 +35,10 @@
# --- ahat script ----------------
include $(CLEAR_VARS)
LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE := ahat
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/ahat $(ACP)
- @echo "Copy: $(PRIVATE_MODULE) ($@)"
- $(copy-file-to-new-target)
- $(hide) chmod 755 $@
-
-ahat: $(LOCAL_BUILT_MODULE)
+LOCAL_SRC_FILES := ahat
+include $(BUILD_PREBUILT)
# --- ahat-tests.jar --------------
include $(CLEAR_VARS)
diff --git a/tools/checker/common/logger.py b/tools/checker/common/logger.py
index 28bb458..f13eaf6 100644
--- a/tools/checker/common/logger.py
+++ b/tools/checker/common/logger.py
@@ -13,6 +13,7 @@
# limitations under the License.
from __future__ import print_function
+import collections
import sys
class Logger(object):
@@ -21,7 +22,7 @@
NoOutput, Error, Info = range(3)
class Color(object):
- Default, Blue, Gray, Purple, Red = range(5)
+ Default, Blue, Gray, Purple, Red, Green = range(6)
@staticmethod
def terminalCode(color, out=sys.stdout):
@@ -35,6 +36,8 @@
return '\033[95m'
elif color == Logger.Color.Red:
return '\033[91m'
+ elif color == Logger.Color.Green:
+ return '\033[32m'
else:
return '\033[0m'
@@ -52,19 +55,34 @@
out.flush()
@staticmethod
- def fail(msg, file=None, line=-1):
- location = ""
- if file:
- location += file + ":"
- if line > 0:
- location += str(line) + ":"
- if location:
- location += " "
-
- Logger.log(location, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr)
+ def fail(msg, file=None, line=-1, lineText=None, variables=None):
Logger.log("error: ", Logger.Level.Error, color=Logger.Color.Red, newLine=False, out=sys.stderr)
Logger.log(msg, Logger.Level.Error, out=sys.stderr)
- sys.exit(msg)
+
+ if lineText:
+ loc = ""
+ if file:
+ loc += file + ":"
+ if line > 0:
+ loc += str(line) + ":"
+ if loc:
+ loc += " "
+ Logger.log(loc, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr)
+ Logger.log(lineText, Logger.Level.Error, out=sys.stderr)
+
+ if variables:
+ longestName = 0
+ for var in variables:
+ longestName = max(longestName, len(var))
+
+ for var in collections.OrderedDict(sorted(variables.items())):
+ padding = ' ' * (longestName - len(var))
+ Logger.log(var, Logger.Level.Error, color=Logger.Color.Green, newLine=False, out=sys.stderr)
+ Logger.log(padding, Logger.Level.Error, newLine=False, out=sys.stderr)
+ Logger.log(" = ", Logger.Level.Error, newLine=False, out=sys.stderr)
+ Logger.log(variables[var], Logger.Level.Error, out=sys.stderr)
+
+ sys.exit(1)
@staticmethod
def startTest(name):
@@ -76,6 +94,6 @@
Logger.log("PASS", color=Logger.Color.Blue)
@staticmethod
- def testFailed(msg, file=None, line=-1):
+ def testFailed(msg, assertion, variables):
Logger.log("FAIL", color=Logger.Color.Red)
- Logger.fail(msg, file, line)
+ Logger.fail(msg, assertion.fileName, assertion.lineNo, assertion.originalText, variables)
diff --git a/tools/checker/match/file.py b/tools/checker/match/file.py
index 3ded074..6ff19d5 100644
--- a/tools/checker/match/file.py
+++ b/tools/checker/match/file.py
@@ -23,9 +23,10 @@
MatchInfo = namedtuple("MatchInfo", ["scope", "variables"])
class MatchFailedException(Exception):
- def __init__(self, assertion, lineNo):
+ def __init__(self, assertion, lineNo, variables):
self.assertion = assertion
self.lineNo = lineNo
+ self.variables = variables
def splitIntoGroups(assertions):
""" Breaks up a list of assertions, grouping instructions which should be
@@ -58,7 +59,7 @@
newVariables = MatchLines(assertion, c1Pass.body[i], variables)
if newVariables is not None:
return MatchInfo(MatchScope(i, i), newVariables)
- raise MatchFailedException(assertion, scope.start)
+ raise MatchFailedException(assertion, scope.start, variables)
def matchDagGroup(assertions, c1Pass, scope, variables):
""" Attempts to find matching `c1Pass` lines for a group of DAG assertions.
@@ -92,12 +93,12 @@
for assertion in assertions:
assert assertion.variant == TestAssertion.Variant.Not
if MatchLines(assertion, line, variables) is not None:
- raise MatchFailedException(assertion, i)
+ raise MatchFailedException(assertion, i, variables)
def testEvalGroup(assertions, scope, variables):
for assertion in assertions:
if not EvaluateLine(assertion, variables):
- raise MatchFailedException(assertion, scope.start)
+ raise MatchFailedException(assertion, scope.start, variables)
def MatchTestCase(testCase, c1Pass):
""" Runs a test case against a C1visualizer graph dump.
@@ -181,8 +182,8 @@
except MatchFailedException as e:
lineNo = c1Pass.startLineNo + e.lineNo
if e.assertion.variant == TestAssertion.Variant.Not:
- Logger.testFailed("NOT assertion matched line {}".format(lineNo),
- e.assertion.fileName, e.assertion.lineNo)
+ msg = "NOT assertion matched line {}"
else:
- Logger.testFailed("Assertion could not be matched starting from line {}".format(lineNo),
- e.assertion.fileName, e.assertion.lineNo)
+ msg = "Assertion could not be matched starting from line {}"
+ msg = msg.format(lineNo)
+ Logger.testFailed(msg, e.assertion, e.variables)
diff --git a/tools/checker/match/line.py b/tools/checker/match/line.py
index 08f001f..ed48a53 100644
--- a/tools/checker/match/line.py
+++ b/tools/checker/match/line.py
@@ -35,15 +35,13 @@
if name in variables:
return variables[name]
else:
- Logger.testFailed("Missing definition of variable \"{}\"".format(name),
- pos.fileName, pos.lineNo)
+ Logger.testFailed("Missing definition of variable \"{}\"".format(name), pos, variables)
def setVariable(name, value, variables, pos):
if name not in variables:
return variables.copyWith(name, value)
else:
- Logger.testFailed("Multiple definitions of variable \"{}\"".format(name),
- pos.fileName, pos.lineNo)
+ Logger.testFailed("Multiple definitions of variable \"{}\"".format(name), pos, variables)
def matchWords(checkerWord, stringWord, variables, pos):
""" Attempts to match a list of TestExpressions against a string.
diff --git a/tools/dexfuzz/Android.mk b/tools/dexfuzz/Android.mk
index 1580bc3..473f6de 100644
--- a/tools/dexfuzz/Android.mk
+++ b/tools/dexfuzz/Android.mk
@@ -27,14 +27,10 @@
# --- dexfuzz script ----------------
include $(CLEAR_VARS)
LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE := dexfuzz
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/dexfuzz $(ACP)
- @echo "Copy: $(PRIVATE_MODULE) ($@)"
- $(copy-file-to-new-target)
- $(hide) chmod 755 $@
+LOCAL_SRC_FILES := dexfuzz
+include $(BUILD_PREBUILT)
# --- dexfuzz script with core image dependencies ----------------
fuzzer: $(LOCAL_BUILT_MODULE) $(HOST_CORE_IMG_OUTS)
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 46100ae..fab4599 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -270,5 +270,10 @@
description: "Only work with --mode=activity",
result: EXEC_FAILED,
names: [ "libcore.java.io.FileTest#testJavaIoTmpdirMutable" ]
+},
+{
+ description: "Temporary suppressing while test is fixed",
+ result: EXEC_FAILED,
+ names: [ "org.apache.harmony.tests.java.util.ArrayDequeTest#test_forEachRemaining_iterator" ]
}
]
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index e4af9fa..8422e20 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -51,7 +51,7 @@
image_compiler_option=""
debug="no"
verbose="no"
-image="-Ximage:/data/art-test/core-jit.art"
+image="-Ximage:/data/art-test/core-optimizing-pic.art"
vm_args=""
# By default, we run the whole JDWP test suite.
test="org.apache.harmony.jpda.tests.share.AllTests"
@@ -70,9 +70,6 @@
device_dir=""
# Vogar knows which VM to use on host.
vm_command=""
- # We only compile the image on the host. Note that not providing this option
- # for target testing puts us below the adb command limit for vogar.
- image_compiler_option="--vm-arg -Ximage-compiler-option --vm-arg --debuggable"
shift
elif [[ $1 == -Ximage:* ]]; then
image="$1"
diff --git a/tools/setup-buildbot-device.sh b/tools/setup-buildbot-device.sh
index 45b60dc..9e085b5 100755
--- a/tools/setup-buildbot-device.sh
+++ b/tools/setup-buildbot-device.sh
@@ -37,6 +37,14 @@
echo -e "${green}Battery info${nc}"
adb shell dumpsys battery
+echo -e "${green}Setting adb buffer size to 32MB${nc}"
+adb logcat -G 32M
+adb logcat -g
+
+echo -e "${green}Removing adb spam filter${nc}"
+adb logcat -P ""
+adb logcat -p
+
echo -e "${green}Kill stalled dalvikvm processes${nc}"
processes=$(adb shell "ps" | grep dalvikvm | awk '{print $2}')
for i in $processes; do adb shell kill -9 $i; done