[vm] More pieces of Windows ARM support.

TEST=ci
Bug: https://github.com/dart-lang/sdk/issues/47824
Change-Id: Ie7388b12359b9ae11509a3f1b9e86c72507df38f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/240483
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2022-04-07 23:15:48 +00:00 committed by Commit Bot
parent ca9ba196c8
commit 53c04ff910
14 changed files with 67 additions and 49 deletions

View file

@ -185,7 +185,10 @@ DART_EXPORT void* TestUnprotectCode(void (*fn)(void)) {
// Clobbers some registers with special meaning in Dart before re-entry, for
// stress-testing. Not used on 32-bit Windows due to complications with Windows
// "safeseh".
#if defined(DART_TARGET_OS_WINDOWS) && defined(HOST_ARCH_IA32)
// TODO(47824): Figure out how ARM/ARM64 syntax is different on Windows.
#if defined(DART_TARGET_OS_WINDOWS) && \
(defined(HOST_ARCH_IA32) || defined(HOST_ARCH_ARM) || \
defined(HOST_ARCH_ARM64))
void ClobberAndCall(void (*fn)()) {
fn();
}

View file

@ -67,16 +67,22 @@ inline void abort_noreturn() { abort(); }
// the output of the division with the expected result. (Inlining must be
// disabled.)
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
#if defined(_M_X64) || defined(__x86_64__) || defined(__ARMEL__) || \
defined(__avr32__) || defined(__hppa__) || defined(__ia64__) || \
defined(__mips__) || defined(__powerpc__) || defined(__ppc__) || \
defined(__ppc64__) || defined(_POWER) || defined(_ARCH_PPC) || \
defined(_ARCH_PPC64) || defined(__sparc__) || defined(__sparc) || \
defined(__s390__) || defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || defined(__AARCH64EL__) || \
defined(__aarch64__) || defined(__riscv)
#if defined(_M_X64) || defined(__x86_64__) || \
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
defined(__hppa__) || defined(__ia64__) || \
defined(__mips__) || \
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || \
defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
defined(__riscv) || \
defined(__or1k__) || defined(__arc__) || \
defined(__EMSCRIPTEN__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
#elif defined(__mc68000__)
#elif defined(__mc68000__) || \
defined(__pnacl__) || defined(__native_client__)
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
#if defined(_WIN32)

View file

@ -271,7 +271,7 @@ void Assembler::bics(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), BIC, 1, rn, rd, o);
}
void Assembler::mvn(Register rd, Operand o, Condition cond) {
void Assembler::mvn_(Register rd, Operand o, Condition cond) {
EmitType01(cond, o.type(), MVN, 0, R0, rd, o);
}
@ -2779,7 +2779,7 @@ void Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
if (Operand::CanHold(value, &o)) {
mov(rd, o, cond);
} else if (Operand::CanHold(~value, &o)) {
mvn(rd, o, cond);
mvn_(rd, o, cond);
} else {
LoadDecodableImmediate(rd, value, cond);
}
@ -3072,10 +3072,10 @@ void Assembler::AddImmediate(Register rd,
} else {
ASSERT(rn != IP);
if (Operand::CanHold(~value, &o)) {
mvn(IP, o, cond);
mvn_(IP, o, cond);
add(rd, rn, Operand(IP), cond);
} else if (Operand::CanHold(~(-value), &o)) {
mvn(IP, o, cond);
mvn_(IP, o, cond);
sub(rd, rn, Operand(IP), cond);
} else if (value > 0) {
LoadDecodableImmediate(IP, value, cond);
@ -3101,11 +3101,11 @@ void Assembler::AddImmediateSetFlags(Register rd,
} else {
ASSERT(rn != IP);
if (Operand::CanHold(~value, &o)) {
mvn(IP, o, cond);
mvn_(IP, o, cond);
adds(rd, rn, Operand(IP), cond);
} else if (Operand::CanHold(~(-value), &o)) {
ASSERT(value != kMinInt32); // Would cause erroneous overflow detection.
mvn(IP, o, cond);
mvn_(IP, o, cond);
subs(rd, rn, Operand(IP), cond);
} else {
LoadDecodableImmediate(IP, value, cond);
@ -3135,11 +3135,11 @@ void Assembler::SubImmediateSetFlags(Register rd,
} else {
ASSERT(rn != IP);
if (Operand::CanHold(~value, &o)) {
mvn(IP, o, cond);
mvn_(IP, o, cond);
subs(rd, rn, Operand(IP), cond);
} else if (Operand::CanHold(~(-value), &o)) {
ASSERT(value != kMinInt32); // Would cause erroneous overflow detection.
mvn(IP, o, cond);
mvn_(IP, o, cond);
adds(rd, rn, Operand(IP), cond);
} else {
LoadDecodableImmediate(IP, value, cond);

View file

@ -500,7 +500,7 @@ class Assembler : public AssemblerBase {
void bic(Register rd, Register rn, Operand o, Condition cond = AL);
void bics(Register rd, Register rn, Operand o, Condition cond = AL);
void mvn(Register rd, Operand o, Condition cond = AL);
void mvn_(Register rd, Operand o, Condition cond = AL);
void mvns(Register rd, Operand o, Condition cond = AL);
// Miscellaneous data-processing instructions.

View file

@ -1586,7 +1586,9 @@ class Assembler : public AssemblerBase {
}
}
void vmov(VRegister vd, VRegister vn) { vorr(vd, vn, vn); }
void mvn(Register rd, Register rm) { orn(rd, ZR, Operand(rm)); }
void mvn_(Register rd, Register rm) {
orn(rd, ZR, Operand(rm));
}
void mvnw(Register rd, Register rm) { ornw(rd, ZR, Operand(rm)); }
void neg(Register rd, Register rm) { sub(rd, ZR, Operand(rm)); }
void negs(Register rd, Register rm, OperandSize sz = kEightBytes) {

View file

@ -3258,8 +3258,7 @@ ASSEMBLER_TEST_GENERATE(Smaddl3, assembler) {
ASSEMBLER_TEST_RUN(Smaddl3, test) {
typedef int64_t (*Int64Return)() DART_UNUSED;
EXPECT_EQ(0xffffl * 0xffffl,
EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
EXPECT_EQ(0xfffe0001, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
EXPECT_DISASSEMBLY(
"movz r1, #0xffff\n"
"movz r2, #0xffff\n"

View file

@ -75,7 +75,7 @@ ASSEMBLER_TEST_RUN(Simple, test) {
}
ASSEMBLER_TEST_GENERATE(MoveNegated, assembler) {
__ mvn(R0, Operand(42));
__ mvn_(R0, Operand(42));
__ Ret();
}
@ -988,7 +988,7 @@ ASSEMBLER_TEST_GENERATE(Clz, assembler) {
__ clz(R2, R2);
__ cmp(R2, Operand(26));
__ b(&error, NE);
__ mvn(R0, Operand(0));
__ mvn_(R0, Operand(0));
__ clz(R1, R0);
__ cmp(R1, Operand(0));
__ b(&error, NE);

View file

@ -5786,7 +5786,7 @@ void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
break;
}
case Token::kBIT_NOT:
__ mvn(result, compiler::Operand(value));
__ mvn_(result, compiler::Operand(value));
// Remove inverted smi-tag.
__ bic(result, result, compiler::Operand(kSmiTagMask));
break;
@ -7071,8 +7071,8 @@ void UnaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
switch (op_kind()) {
case Token::kBIT_NOT:
__ mvn(out_lo, compiler::Operand(left_lo));
__ mvn(out_hi, compiler::Operand(left_hi));
__ mvn_(out_lo, compiler::Operand(left_lo));
__ mvn_(out_hi, compiler::Operand(left_hi));
break;
case Token::kNEGATE:
__ rsbs(out_lo, left_lo, compiler::Operand(0));
@ -7143,7 +7143,7 @@ void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(op_kind() == Token::kBIT_NOT);
__ mvn(out, compiler::Operand(left));
__ mvn_(out, compiler::Operand(left));
}
LocationSummary* IntConverterInstr::MakeLocationSummary(Zone* zone,

View file

@ -4832,7 +4832,7 @@ void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
break;
}
case Token::kBIT_NOT:
__ mvn(result, value);
__ mvn_(result, value);
// Remove inverted smi-tag.
__ andi(result, result, compiler::Immediate(~kSmiTagMask));
break;
@ -6145,7 +6145,7 @@ void UnaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register out = locs()->out(0).reg();
switch (op_kind()) {
case Token::kBIT_NOT:
__ mvn(out, left);
__ mvn_(out, left);
break;
case Token::kNEGATE:
__ sub(out, ZR, compiler::Operand(left));

View file

@ -14,15 +14,12 @@
#include "vm/object.h"
#include "vm/simulator.h"
#if defined(DART_HOST_OS_IOS)
#if !defined(TARGET_HOST_MISMATCH)
#if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
#include <libkern/OSCacheControl.h>
#elif defined(DART_HOST_OS_WINDOWS)
#include <processthreadsapi.h>
#endif
#if !defined(TARGET_HOST_MISMATCH)
#include <sys/syscall.h> /* NOLINT */
#include <unistd.h> /* NOLINT */
#endif
// ARM version differences.

View file

@ -12,19 +12,14 @@
#include "vm/simulator.h"
#if !defined(USING_SIMULATOR)
#if !defined(DART_HOST_OS_FUCHSIA)
#include <sys/syscall.h>
#else
#if defined(DART_HOST_OS_FUCHSIA)
#include <zircon/syscalls.h>
#endif
#include <unistd.h>
#endif
#if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
#elif defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
#include <libkern/OSCacheControl.h>
#elif defined(DART_HOST_OS_WINDOWS)
#include <processthreadsapi.h>
#endif
#endif
namespace dart {

View file

@ -180,12 +180,9 @@ static const uword kZapUninitializedWord = 0xabababababababab;
__asm { mov fp, ebp} \
; // NOLINT
// clang-format on
#elif defined(HOST_ARCH_X64)
// We don't have the asm equivalent to get at the frame pointer on
// windows x64, return the stack pointer instead.
#define COPY_FP_REGISTER(fp) fp = OSThread::GetCurrentStackPointer();
#else
#error Unknown host architecture.
// Inline assembly is only available on x86; return the stack pointer instead.
#define COPY_FP_REGISTER(fp) fp = OSThread::GetCurrentStackPointer();
#endif
#else // !defined(DART_HOST_OS_WINDOWS))

View file

@ -416,6 +416,14 @@ void Profiler::DumpStackTrace(void* context) {
uword pc = static_cast<uword>(ctx->Rip);
uword fp = static_cast<uword>(ctx->Rbp);
uword sp = static_cast<uword>(ctx->Rsp);
#elif defined(HOST_ARCH_ARM)
uword pc = static_cast<uword>(ctx->Pc);
uword fp = static_cast<uword>(ctx->R11);
uword sp = static_cast<uword>(ctx->Sp);
#elif defined(HOST_ARCH_ARM64)
uword pc = static_cast<uword>(ctx->Pc);
uword fp = static_cast<uword>(ctx->Fp);
uword sp = static_cast<uword>(ctx->Sp);
#else
#error Unsupported architecture.
#endif

View file

@ -26,7 +26,8 @@ class ThreadInterrupterWin : public AllStatic {
#if defined(HOST_ARCH_IA32)
// On IA32, CONTEXT_CONTROL includes Eip, Ebp, and Esp.
context.ContextFlags = CONTEXT_CONTROL;
#elif defined(HOST_ARCH_X64)
#elif defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM) || \
defined(HOST_ARCH_ARM64)
// On X64, CONTEXT_CONTROL includes Rip and Rsp. Rbp is classified
// as an "integer" register.
context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
@ -44,6 +45,16 @@ class ThreadInterrupterWin : public AllStatic {
state->fp = static_cast<uintptr_t>(context.Rbp);
state->csp = static_cast<uintptr_t>(context.Rsp);
state->dsp = static_cast<uintptr_t>(context.Rsp);
#elif defined(HOST_ARCH_ARM)
state->pc = static_cast<uintptr_t>(context.Pc);
state->fp = static_cast<uintptr_t>(context.R11);
state->csp = static_cast<uintptr_t>(context.Sp);
state->dsp = static_cast<uintptr_t>(context.Sp);
#elif defined(HOST_ARCH_ARM64)
state->pc = static_cast<uintptr_t>(context.Pc);
state->fp = static_cast<uintptr_t>(context.Fp);
state->csp = static_cast<uintptr_t>(context.Sp);
state->dsp = static_cast<uintptr_t>(context.X15);
#else
#error Unsupported architecture.
#endif