Index: runtime/vm/simulator_dbc.cc |
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc |
index 499f6046d037a81f7f3495e7697d6b19a5370e58..9fe715b89672b067a9ee6455b4dcf8af87c1941f 100644 |
--- a/runtime/vm/simulator_dbc.cc |
+++ b/runtime/vm/simulator_dbc.cc |
@@ -442,7 +442,7 @@ DART_FORCE_INLINE static bool SignedMulWithOverflow(intptr_t lhs, |
: "r"(rhs), "r"(out) |
: "cc", "r12"); |
#elif defined(HOST_ARCH_ARM64) |
- int64_t prod_lo; |
+ int64_t prod_lo = 0; |
asm volatile( |
"mul %1, %2, %3\n" |
"smulh %2, %2, %3\n" |
@@ -451,7 +451,7 @@ DART_FORCE_INLINE static bool SignedMulWithOverflow(intptr_t lhs, |
"mov %0, #0;\n" |
"str %1, [%4, #0]\n" |
"1:" |
- : "+r"(res), "=r"(prod_lo), "+r"(lhs) |
+ : "=r"(res), "+r"(prod_lo), "+r"(lhs) |
: "r"(rhs), "r"(out) |
: "cc"); |
#else |
@@ -477,6 +477,7 @@ DART_FORCE_INLINE static bool AreBothSmis(intptr_t a, intptr_t b) { |
#define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres) |
#define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false) |
#define SMI_BITAND(lhs, rhs, pres) ((*(pres) = ((lhs) & (rhs))), false) |
+#define SMI_BITXOR(lhs, rhs, pres) ((*(pres) = ((lhs) ^ (rhs))), false) |
void Simulator::CallRuntime(Thread* thread, |
@@ -786,6 +787,28 @@ static DART_NOINLINE bool InvokeNativeWrapper( |
} \ |
} |
+// Skip the next instruction if there is no overflow. |
+#define SMI_OP_CHECK(ResultT, Func) \ |
+ { \ |
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); \ |
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); \ |
+ ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]); \ |
+ if (LIKELY(!Func(lhs, rhs, slot))) { \ |
+ /* Success. Skip the instruction that follows. */ \ |
+ pc++; \ |
+ } \ |
+ } |
+ |
+// Do not check for overflow. |
+#define SMI_OP_NOCHECK(ResultT, Func) \ |
+ { \ |
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); \ |
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); \ |
+ ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]); \ |
+ Func(lhs, rhs, slot); \ |
+ } \ |
+ |
+ |
// Exception handling helper. Gets handler FP and PC from the Simulator where |
// they were stored by Simulator::Longjmp and proceeds to execute the handler. |
// Corner case: handler PC can be a fake marker that marks entry frame, which |
@@ -1541,6 +1564,97 @@ RawObject* Simulator::Call(const Code& code, |
SMI_FASTPATH_TOS(RawObject*, SMI_GT); |
DISPATCH(); |
} |
+ { |
+ BYTECODE(Add, A_B_C); |
+ SMI_OP_CHECK(intptr_t, SignedAddWithOverflow); |
+ DISPATCH(); |
+ } |
+ { |
+ BYTECODE(Sub, A_B_C); |
+ SMI_OP_CHECK(intptr_t, SignedSubWithOverflow); |
+ DISPATCH(); |
+ } |
+ { |
+ BYTECODE(Mul, A_B_C); |
+ SMI_OP_CHECK(intptr_t, SMI_MUL); |
+ DISPATCH(); |
+ } |
+ { |
+ BYTECODE(BitOr, A_B_C); |
+ SMI_OP_NOCHECK(intptr_t, SMI_BITOR); |
+ DISPATCH(); |
+ } |
+ { |
+ BYTECODE(BitAnd, A_B_C); |
+ SMI_OP_NOCHECK(intptr_t, SMI_BITAND); |
+ DISPATCH(); |
+ } |
+ { |
+ BYTECODE(BitXor, A_B_C); |
+ SMI_OP_NOCHECK(intptr_t, SMI_BITXOR); |
+ DISPATCH(); |
+ } |
+ |
+ { |
+ BYTECODE(Div, A_B_C); |
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); |
+ if (rhs != 0) { |
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); |
+ const intptr_t res = (lhs >> kSmiTagSize) / (rhs >> kSmiTagSize); |
+#if defined(ARCH_IS_64_BIT) |
+ const intptr_t untaggable = 0x4000000000000000LL; |
+#else |
+ const intptr_t untaggable = 0x40000000L; |
+#endif // defined(ARCH_IS_64_BIT) |
+ if (res != untaggable) { |
+ *reinterpret_cast<intptr_t*>(&FP[rA]) = res << kSmiTagSize; |
+ pc++; |
+ } |
+ } |
+ DISPATCH(); |
+ } |
+ |
+ { |
+ BYTECODE(Mod, A_B_C); |
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); |
+ if (rhs != 0) { |
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); |
+ const intptr_t res = |
+ ((lhs >> kSmiTagSize) % (rhs >> kSmiTagSize)) << kSmiTagSize; |
+ *reinterpret_cast<intptr_t*>(&FP[rA]) = |
+ (res < 0) ? ((rhs < 0) ? (res - rhs) : (res + rhs)) : res; |
+ pc++; |
+ } |
+ DISPATCH(); |
+ } |
+ |
+ { |
+ BYTECODE(Shl, A_B_C); |
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize; |
+ if (rhs >= 0) { |
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); |
+ const intptr_t res = lhs << rhs; |
+ if (lhs == (res >> rhs)) { |
+ *reinterpret_cast<intptr_t*>(&FP[rA]) = res; |
+ pc++; |
+ } |
+ } |
+ DISPATCH(); |
+ } |
+ |
+ { |
+ BYTECODE(Shr, A_B_C); |
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize; |
+ if (rhs >= 0) { |
+ const intptr_t shift_amount = |
+ (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs; |
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize; |
+ *reinterpret_cast<intptr_t*>(&FP[rA]) = |
+ (lhs >> shift_amount) << kSmiTagSize; |
+ pc++; |
+ } |
+ DISPATCH(); |
+ } |
// Return and return like instructions (Instrinsic). |
{ |
@@ -2042,6 +2156,11 @@ RawObject* Simulator::Call(const Code& code, |
} |
{ |
+ BYTECODE(Nop, 0); |
+ DISPATCH(); |
+ } |
+ |
+ { |
BYTECODE(Trap, 0); |
UNIMPLEMENTED(); |
DISPATCH(); |