From 9f91ba1f7357c61dd2c7c3b437ea203d467fd400 Mon Sep 17 00:00:00 2001 From: Liam Date: Fri, 17 Nov 2023 23:44:53 +0200 Subject: arm: Implement native code execution backend --- src/core/arm/nce/instructions.h | 147 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/core/arm/nce/instructions.h (limited to 'src/core/arm/nce/instructions.h') diff --git a/src/core/arm/nce/instructions.h b/src/core/arm/nce/instructions.h new file mode 100644 index 000000000..5b56ff857 --- /dev/null +++ b/src/core/arm/nce/instructions.h @@ -0,0 +1,147 @@ +// SPDX-FileCopyrightText: Copyright © 2020 Skyline Team and Contributors +// SPDX-License-Identifier: MPL-2.0 + +#include "common/bit_field.h" +#include "common/common_types.h" + +namespace Core::NCE { + +enum SystemRegister : u32 { + TpidrEl0 = 0x5E82, + TpidrroEl0 = 0x5E83, + CntfrqEl0 = 0x5F00, + CntpctEl0 = 0x5F01, +}; + +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/SVC--Supervisor-Call- +union SVC { + constexpr explicit SVC(u32 raw_) : raw{raw_} {} + + constexpr bool Verify() { + return (this->GetSig0() == 0x1 && this->GetSig1() == 0x6A0); + } + + constexpr u32 GetSig0() { + return decltype(sig0)::ExtractValue(raw); + } + + constexpr u32 GetValue() { + return decltype(value)::ExtractValue(raw); + } + + constexpr u32 GetSig1() { + return decltype(sig1)::ExtractValue(raw); + } + + u32 raw; + +private: + BitField<0, 5, u32> sig0; // 0x1 + BitField<5, 16, u32> value; // 16-bit immediate + BitField<21, 11, u32> sig1; // 0x6A0 +}; +static_assert(sizeof(SVC) == sizeof(u32)); +static_assert(SVC(0xD40000C1).Verify()); +static_assert(SVC(0xD40000C1).GetValue() == 0x6); + +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MRS--Move-System-Register- +union MRS { + constexpr explicit MRS(u32 raw_) : raw{raw_} {} + + constexpr bool Verify() { + return (this->GetSig() == 0xD53); + } + + constexpr u32 GetRt() { + return decltype(rt)::ExtractValue(raw); + } + + constexpr u32 GetSystemReg() { + return decltype(system_reg)::ExtractValue(raw); + } + + constexpr u32 GetSig() { + return decltype(sig)::ExtractValue(raw); + } + + u32 raw; + +private: + BitField<0, 5, u32> rt; // destination register + BitField<5, 15, u32> system_reg; // source system register + BitField<20, 12, u32> sig; // 0xD53 +}; +static_assert(sizeof(MRS) == sizeof(u32)); +static_assert(MRS(0xD53BE020).Verify()); +static_assert(MRS(0xD53BE020).GetSystemReg() == CntpctEl0); +static_assert(MRS(0xD53BE020).GetRt() == 0x0); + +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MSR--register---Move-general-purpose-register-to-System-Register- +union MSR { + constexpr explicit MSR(u32 raw_) : raw{raw_} {} + + constexpr bool Verify() { + return this->GetSig() == 0xD51; + } + + constexpr u32 GetRt() { + return decltype(rt)::ExtractValue(raw); + } + + constexpr u32 GetSystemReg() { + return decltype(system_reg)::ExtractValue(raw); + } + + constexpr u32 GetSig() { + return decltype(sig)::ExtractValue(raw); + } + + u32 raw; + +private: + BitField<0, 5, u32> rt; // source register + BitField<5, 15, u32> system_reg; // destination system register + BitField<20, 12, u32> sig; // 0xD51 +}; +static_assert(sizeof(MSR) == sizeof(u32)); +static_assert(MSR(0xD51BD040).Verify()); +static_assert(MSR(0xD51BD040).GetSystemReg() == TpidrEl0); +static_assert(MSR(0xD51BD040).GetRt() == 0x0); + +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDXR--Load-Exclusive-Register- +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDXP--Load-Exclusive-Pair-of-Registers- +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/STXR--Store-Exclusive-Register- +// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/STXP--Store-Exclusive-Pair-of-registers- +union Exclusive { + constexpr explicit Exclusive(u32 raw_) : raw{raw_} {} + + constexpr bool Verify() { + return this->GetSig() == 0x10; + } + + constexpr u32 GetSig() { + return decltype(sig)::ExtractValue(raw); + } + + constexpr u32 AsOrdered() { + return raw | decltype(o0)::FormatValue(1); + } + + u32 raw; + +private: + BitField<0, 5, u32> rt; // memory operand + BitField<5, 5, u32> rn; // register operand 1 + BitField<10, 5, u32> rt2; // register operand 2 + BitField<15, 1, u32> o0; // ordered + BitField<16, 5, u32> rs; // status register + BitField<21, 2, u32> l; // operation type + BitField<23, 7, u32> sig; // 0x10 + BitField<30, 2, u32> size; // size +}; +static_assert(Exclusive(0xC85FFC00).Verify()); +static_assert(Exclusive(0xC85FFC00).AsOrdered() == 0xC85FFC00); +static_assert(Exclusive(0xC85F7C00).AsOrdered() == 0xC85FFC00); +static_assert(Exclusive(0xC8200440).AsOrdered() == 0xC8208440); + +} // namespace Core::NCE -- cgit v1.2.3