A64: Initial framework
This commit is contained in:
parent
cde2d48eb9
commit
e161cf16f5
14 changed files with 2650 additions and 1 deletions
|
@ -51,6 +51,15 @@ add_library(dynarmic
|
||||||
frontend/A32/translate/translate_thumb.cpp
|
frontend/A32/translate/translate_thumb.cpp
|
||||||
frontend/A32/types.cpp
|
frontend/A32/types.cpp
|
||||||
frontend/A32/types.h
|
frontend/A32/types.h
|
||||||
|
frontend/A64/decoder/a64.h
|
||||||
|
frontend/A64/imm.h
|
||||||
|
frontend/A64/location_descriptor.cpp
|
||||||
|
frontend/A64/location_descriptor.h
|
||||||
|
frontend/A64/translate/impl/impl.h
|
||||||
|
frontend/A64/translate/translate.cpp
|
||||||
|
frontend/A64/translate/translate.h
|
||||||
|
frontend/A64/types.cpp
|
||||||
|
frontend/A64/types.h
|
||||||
frontend/decoder/decoder_detail.h
|
frontend/decoder/decoder_detail.h
|
||||||
frontend/decoder/matcher.h
|
frontend/decoder/matcher.h
|
||||||
frontend/ir/basic_block.cpp
|
frontend/ir/basic_block.cpp
|
||||||
|
|
112
src/frontend/A64/FPCR.h
Normal file
112
src/frontend/A64/FPCR.h
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
#include "common/bit_util.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
namespace A64 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of the Floating-Point Control Register.
|
||||||
|
*/
|
||||||
|
class FPCR final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class RoundingMode {
|
||||||
|
ToNearest,
|
||||||
|
TowardsPlusInfinity,
|
||||||
|
TowardsMinusInfinity,
|
||||||
|
TowardsZero
|
||||||
|
};
|
||||||
|
|
||||||
|
FPCR() = default;
|
||||||
|
FPCR(const FPCR&) = default;
|
||||||
|
FPCR(FPCR&&) = default;
|
||||||
|
explicit FPCR(u32 data) : value{data & mask} {}
|
||||||
|
|
||||||
|
FPCR& operator=(const FPCR&) = default;
|
||||||
|
FPCR& operator=(FPCR&&) = default;
|
||||||
|
FPCR& operator=(u32 data) {
|
||||||
|
value = data & mask;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Alternate half-precision control flag.
|
||||||
|
bool AHP() const {
|
||||||
|
return Common::Bit<26>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default NaN mode control bit.
|
||||||
|
bool DN() const {
|
||||||
|
return Common::Bit<25>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Flush-to-zero mode control bit.
|
||||||
|
bool FZ() const {
|
||||||
|
return Common::Bit<24>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rounding mode control field.
|
||||||
|
RoundingMode RMode() const {
|
||||||
|
return static_cast<RoundingMode>(Common::Bits<22, 23>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Input denormal exception trap enable flag.
|
||||||
|
bool IDE() const {
|
||||||
|
return Common::Bit<15>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inexact exception trap enable flag.
|
||||||
|
bool IXE() const {
|
||||||
|
return Common::Bit<12>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Underflow exception trap enable flag.
|
||||||
|
bool UFE() const {
|
||||||
|
return Common::Bit<11>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Overflow exception trap enable flag.
|
||||||
|
bool OFE() const {
|
||||||
|
return Common::Bit<10>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Division by zero exception trap enable flag.
|
||||||
|
bool DZE() const {
|
||||||
|
return Common::Bit<9>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Invalid operation exception trap enable flag.
|
||||||
|
bool IOE() const {
|
||||||
|
return Common::Bit<8>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the underlying raw value within the FPCR.
|
||||||
|
u32 Value() const {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Bits 0-7, 13-14, 19, and 27-31 are reserved.
|
||||||
|
static constexpr u32 mask = 0x07F79F00;
|
||||||
|
u32 value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(FPCR lhs, FPCR rhs) {
|
||||||
|
return lhs.Value() == rhs.Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(FPCR lhs, FPCR rhs) {
|
||||||
|
return !operator==(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace A64
|
||||||
|
} // namespace Dynarmic
|
1069
src/frontend/A64/decoder/a64.h
Normal file
1069
src/frontend/A64/decoder/a64.h
Normal file
File diff suppressed because it is too large
Load diff
99
src/frontend/A64/imm.h
Normal file
99
src/frontend/A64/imm.h
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/bit_util.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
namespace A64 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imm represents an immediate value in an AArch64 instruction.
|
||||||
|
* Imm is used during translation as a typesafe way of passing around immediates of fixed sizes.
|
||||||
|
*/
|
||||||
|
template <size_t bit_size_>
|
||||||
|
class Imm {
|
||||||
|
public:
|
||||||
|
static constexpr size_t bit_size = bit_size_;
|
||||||
|
|
||||||
|
explicit Imm(u32 value) : value(value) {
|
||||||
|
ASSERT_MSG((Common::Bits<0, bit_size-1>(value) == value), "More bits in value than expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = u32>
|
||||||
|
T ZeroExtend() const {
|
||||||
|
static_assert(Common::BitSize<T>() <= bit_size);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = s32>
|
||||||
|
T SignExtend() const {
|
||||||
|
static_assert(Common::BitSize<T>() <= bit_size);
|
||||||
|
return static_cast<T>(Common::SignExtend<bit_size>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t bit>
|
||||||
|
bool Bit() const {
|
||||||
|
static_assert(bit < bit_size);
|
||||||
|
return Common::Bit<bit>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Imm<bit_size>& other) const {
|
||||||
|
return value == other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Imm<bit_size>& other) const {
|
||||||
|
return value != other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static_assert(bit_size != 0, "Cannot have a zero-sized immediate");
|
||||||
|
static_assert(bit_size <= 32, "Cannot have an immediate larger than the instruction size");
|
||||||
|
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <size_t bit_size>
|
||||||
|
bool operator==(u32 a, const Imm<bit_size>& b) {
|
||||||
|
return Imm<bit_size>{a} == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t bit_size>
|
||||||
|
bool operator==(const Imm<bit_size>& a, u32 b) {
|
||||||
|
return Imm<bit_size>{b} == a;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t bit_size>
|
||||||
|
bool operator!=(u32 a, const Imm<bit_size>& b) {
|
||||||
|
return Imm<bit_size>{a} != b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t bit_size>
|
||||||
|
bool operator!=(const Imm<bit_size>& a, u32 b) {
|
||||||
|
return Imm<bit_size>{b} != a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatentate immediates together.
|
||||||
|
* Left to right correpeonds to most significant imm to least significant imm.
|
||||||
|
* This is equivalent to a:b:...:z in ASL.
|
||||||
|
*/
|
||||||
|
template <size_t first_bit_size, size_t ...rest_bit_sizes>
|
||||||
|
auto concatenate(Imm<first_bit_size> first, Imm<rest_bit_sizes> ...rest) -> Imm<(first_bit_size + ... + rest_bit_sizes)> {
|
||||||
|
if constexpr (sizeof...(rest) == 0) {
|
||||||
|
return first;
|
||||||
|
} else {
|
||||||
|
const auto concat_rest = concatenate(rest...);
|
||||||
|
const u32 value = (first.ZeroExtend() << concat_rest.bit_size) | concat_rest.ZeroExtend();
|
||||||
|
return Imm<(first_bit_size + ... + rest_bit_sizes)>{value};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace A64
|
||||||
|
} // namespace Dynarmic
|
21
src/frontend/A64/location_descriptor.cpp
Normal file
21
src/frontend/A64/location_descriptor.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "frontend/A64/location_descriptor.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
namespace A64 {
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& o, const LocationDescriptor& loc) {
|
||||||
|
o << fmt::format("{{{}, {}}}", loc.PC(), loc.FPCR().Value());
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace A64
|
||||||
|
} // namespace Dynarmic
|
95
src/frontend/A64/location_descriptor.h
Normal file
95
src/frontend/A64/location_descriptor.h
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "common/bit_util.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "frontend/A64/FPCR.h"
|
||||||
|
#include "frontend/ir/location_descriptor.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
namespace A64 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocationDescriptor describes the location of a basic block.
|
||||||
|
* The location is not solely based on the PC because other flags influence the way
|
||||||
|
* instructions should be translated.
|
||||||
|
*/
|
||||||
|
class LocationDescriptor {
|
||||||
|
public:
|
||||||
|
static constexpr u64 PC_MASK = 0x00FF'FFFF'FFFF'FFFFull;
|
||||||
|
static constexpr u32 FPCR_MASK = 0x07C0'0000;
|
||||||
|
|
||||||
|
LocationDescriptor(u64 pc, FPCR fpcr) : pc(pc & PC_MASK), fpcr(fpcr.Value() & FPCR_MASK) {}
|
||||||
|
|
||||||
|
explicit LocationDescriptor(const IR::LocationDescriptor& o)
|
||||||
|
: pc(o.Value() & PC_MASK), fpcr((o.Value() >> 37) & FPCR_MASK) {}
|
||||||
|
|
||||||
|
u64 PC() const { return Common::SignExtend<56>(pc); }
|
||||||
|
FPCR FPCR() const { return fpcr; }
|
||||||
|
|
||||||
|
bool operator == (const LocationDescriptor& o) const {
|
||||||
|
return std::tie(pc, fpcr) == std::tie(o.pc, o.fpcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator != (const LocationDescriptor& o) const {
|
||||||
|
return !operator==(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationDescriptor SetPC(u32 new_pc) const {
|
||||||
|
return LocationDescriptor(new_pc, fpcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationDescriptor AdvancePC(int amount) const {
|
||||||
|
return LocationDescriptor(static_cast<u64>(pc + amount), fpcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 UniqueHash() const {
|
||||||
|
// This value MUST BE UNIQUE.
|
||||||
|
// This calculation has to match up with EmitTerminalPopRSBHint
|
||||||
|
u64 fpcr_u64 = static_cast<u64>(fpcr.Value()) << 37;
|
||||||
|
return pc | fpcr_u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator IR::LocationDescriptor() const {
|
||||||
|
return IR::LocationDescriptor{UniqueHash()};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
u64 pc; ///< Current program counter value.
|
||||||
|
A64::FPCR fpcr; ///< Floating point control register.
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a string representation of a LocationDescriptor.
|
||||||
|
*
|
||||||
|
* @param o Output stream
|
||||||
|
* @param descriptor The descriptor to get a string representation of
|
||||||
|
*/
|
||||||
|
std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor);
|
||||||
|
|
||||||
|
} // namespace A64
|
||||||
|
} // namespace Dynarmic
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct less<Dynarmic::A64::LocationDescriptor> {
|
||||||
|
bool operator()(const Dynarmic::A64::LocationDescriptor& x, const Dynarmic::A64::LocationDescriptor& y) const {
|
||||||
|
return x.UniqueHash() < y.UniqueHash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct hash<Dynarmic::A64::LocationDescriptor> {
|
||||||
|
size_t operator()(const Dynarmic::A64::LocationDescriptor& x) const {
|
||||||
|
return std::hash<u64>()(x.UniqueHash());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace std
|
1043
src/frontend/A64/translate/impl/impl.h
Normal file
1043
src/frontend/A64/translate/impl/impl.h
Normal file
File diff suppressed because it is too large
Load diff
21
src/frontend/A64/translate/translate.cpp
Normal file
21
src/frontend/A64/translate/translate.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "frontend/A64/location_descriptor.h"
|
||||||
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
#include "frontend/A64/translate/translate.h"
|
||||||
|
#include "frontend/ir/basic_block.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
namespace A64 {
|
||||||
|
|
||||||
|
IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType /*memory_read_code*/) {
|
||||||
|
// TODO
|
||||||
|
return IR::Block{descriptor};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace A64
|
||||||
|
} // namespace Dynarmic
|
31
src/frontend/A64/translate/translate.h
Normal file
31
src/frontend/A64/translate/translate.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
|
||||||
|
namespace IR {
|
||||||
|
class Block;
|
||||||
|
} // namespace IR
|
||||||
|
|
||||||
|
namespace A64 {
|
||||||
|
|
||||||
|
class LocationDescriptor;
|
||||||
|
|
||||||
|
using MemoryReadCodeFuncType = u32 (*)(u64 vaddr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function translates instructions in memory into our intermediate representation.
|
||||||
|
* @param descriptor The starting location of the basic block. Includes information like PC, Thumb state, &c.
|
||||||
|
* @param memory_read_code The function we should use to read emulated memory.
|
||||||
|
* @return A translated basic block in the intermediate representation.
|
||||||
|
*/
|
||||||
|
IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code);
|
||||||
|
|
||||||
|
} // namespace A64
|
||||||
|
} // namespace Dynarmic
|
46
src/frontend/A64/types.cpp
Normal file
46
src/frontend/A64/types.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "common/bit_util.h"
|
||||||
|
#include "frontend/A64/types.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
namespace A64 {
|
||||||
|
|
||||||
|
const char* CondToString(Cond cond) {
|
||||||
|
constexpr std::array<const char*, 16> cond_strs = {
|
||||||
|
"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
|
||||||
|
};
|
||||||
|
return cond_strs.at(static_cast<size_t>(cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RegToString(Reg reg) {
|
||||||
|
if (reg == Reg::R31)
|
||||||
|
return "sp|zr";
|
||||||
|
return fmt::format("r{}", static_cast<size_t>(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string VecToString(Vec vec) {
|
||||||
|
return fmt::format("v{}", static_cast<size_t>(vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& o, Reg reg) {
|
||||||
|
o << RegToString(reg);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& o, Vec vec) {
|
||||||
|
o << VecToString(vec);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace A64
|
||||||
|
} // namespace Dynarmic
|
75
src/frontend/A64/types.h
Normal file
75
src/frontend/A64/types.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* This software may be used and distributed according to the terms of the GNU
|
||||||
|
* General Public License version 2 or any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "frontend/ir/cond.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
namespace A64 {
|
||||||
|
|
||||||
|
using Cond = IR::Cond;
|
||||||
|
|
||||||
|
enum class Reg {
|
||||||
|
R0, R1, R2, R3, R4, R5, R6, R7,
|
||||||
|
R8, R9, R10, R11, R12, R13, R14, R15,
|
||||||
|
R16, R17, R18, R19, R20, R21, R22, R23,
|
||||||
|
R24, R25, R26, R27, R28, R29, R30, R31,
|
||||||
|
LR = R30,
|
||||||
|
SP = R31, ZR = R31,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Vec {
|
||||||
|
V0, V1, V2, V3, V4, V5, V6, V7,
|
||||||
|
V8, V9, V10, V11, V12, V13, V14, V15,
|
||||||
|
V16, V17, V18, V19, V20, V21, V22, V23,
|
||||||
|
V24, V25, V26, V27, V28, V29, V30, V31,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ShiftType {
|
||||||
|
LSL,
|
||||||
|
LSR,
|
||||||
|
ASR,
|
||||||
|
ROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* CondToString(Cond cond);
|
||||||
|
std::string RegToString(Reg reg);
|
||||||
|
std::string VecToString(Vec vec);
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& o, Reg reg);
|
||||||
|
std::ostream& operator<<(std::ostream& o, Vec vec);
|
||||||
|
|
||||||
|
inline size_t RegNumber(Reg reg) {
|
||||||
|
return static_cast<size_t>(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t VecNumber(Vec vec) {
|
||||||
|
return static_cast<size_t>(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Reg operator+(Reg reg, size_t number) {
|
||||||
|
size_t new_reg = static_cast<size_t>(reg) + number;
|
||||||
|
ASSERT(new_reg <= 31);
|
||||||
|
|
||||||
|
return static_cast<Reg>(new_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec operator+(Vec vec, size_t number) {
|
||||||
|
size_t new_vec = static_cast<size_t>(vec) + number;
|
||||||
|
ASSERT(new_vec <= 31);
|
||||||
|
|
||||||
|
return static_cast<Vec>(new_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace A64
|
||||||
|
} // namespace Dynarmic
|
|
@ -43,7 +43,8 @@ enum class Type {
|
||||||
U64 = 1 << 9,
|
U64 = 1 << 9,
|
||||||
F32 = 1 << 10,
|
F32 = 1 << 10,
|
||||||
F64 = 1 << 11,
|
F64 = 1 << 11,
|
||||||
CoprocInfo = 1 << 12,
|
F128 = 1 << 12,
|
||||||
|
CoprocInfo = 1 << 13,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr Type operator|(Type a, Type b) {
|
constexpr Type operator|(Type a, Type b) {
|
||||||
|
|
|
@ -23,6 +23,14 @@ Value::Value(A32::ExtReg value) : type(Type::A32ExtReg) {
|
||||||
inner.imm_a32extregref = value;
|
inner.imm_a32extregref = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value::Value(A64::Reg value) : type(Type::A64Reg) {
|
||||||
|
inner.imm_a64regref = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::Value(A64::Vec value) : type(Type::A64Vec) {
|
||||||
|
inner.imm_a64vecref = value;
|
||||||
|
}
|
||||||
|
|
||||||
Value::Value(bool value) : type(Type::U1) {
|
Value::Value(bool value) : type(Type::U1) {
|
||||||
inner.imm_u1 = value;
|
inner.imm_u1 = value;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +86,16 @@ A32::ExtReg Value::GetA32ExtRegRef() const {
|
||||||
return inner.imm_a32extregref;
|
return inner.imm_a32extregref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
A64::Reg Value::GetA64RegRef() const {
|
||||||
|
ASSERT(type == Type::A64Reg);
|
||||||
|
return inner.imm_a64regref;
|
||||||
|
}
|
||||||
|
|
||||||
|
A64::Vec Value::GetA64VecRef() const {
|
||||||
|
ASSERT(type == Type::A64Vec);
|
||||||
|
return inner.imm_a64vecref;
|
||||||
|
}
|
||||||
|
|
||||||
Inst* Value::GetInst() const {
|
Inst* Value::GetInst() const {
|
||||||
ASSERT(type == Type::Opaque);
|
ASSERT(type == Type::Opaque);
|
||||||
return inner.inst;
|
return inner.inst;
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "frontend/A32/types.h"
|
#include "frontend/A32/types.h"
|
||||||
|
#include "frontend/A64/types.h"
|
||||||
|
#include "frontend/ir/opcodes.h"
|
||||||
|
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace IR {
|
namespace IR {
|
||||||
|
@ -25,6 +27,8 @@ public:
|
||||||
explicit Value(Inst* value);
|
explicit Value(Inst* value);
|
||||||
explicit Value(A32::Reg value);
|
explicit Value(A32::Reg value);
|
||||||
explicit Value(A32::ExtReg value);
|
explicit Value(A32::ExtReg value);
|
||||||
|
explicit Value(A64::Reg value);
|
||||||
|
explicit Value(A64::Vec value);
|
||||||
explicit Value(bool value);
|
explicit Value(bool value);
|
||||||
explicit Value(u8 value);
|
explicit Value(u8 value);
|
||||||
explicit Value(u16 value);
|
explicit Value(u16 value);
|
||||||
|
@ -39,6 +43,8 @@ public:
|
||||||
Inst* GetInst() const;
|
Inst* GetInst() const;
|
||||||
A32::Reg GetA32RegRef() const;
|
A32::Reg GetA32RegRef() const;
|
||||||
A32::ExtReg GetA32ExtRegRef() const;
|
A32::ExtReg GetA32ExtRegRef() const;
|
||||||
|
A64::Reg GetA64RegRef() const;
|
||||||
|
A64::Vec GetA64VecRef() const;
|
||||||
bool GetU1() const;
|
bool GetU1() const;
|
||||||
u8 GetU8() const;
|
u8 GetU8() const;
|
||||||
u16 GetU16() const;
|
u16 GetU16() const;
|
||||||
|
@ -53,6 +59,8 @@ private:
|
||||||
Inst* inst; // type == Type::Opaque
|
Inst* inst; // type == Type::Opaque
|
||||||
A32::Reg imm_a32regref;
|
A32::Reg imm_a32regref;
|
||||||
A32::ExtReg imm_a32extregref;
|
A32::ExtReg imm_a32extregref;
|
||||||
|
A64::Reg imm_a64regref;
|
||||||
|
A64::Vec imm_a64vecref;
|
||||||
bool imm_u1;
|
bool imm_u1;
|
||||||
u8 imm_u8;
|
u8 imm_u8;
|
||||||
u16 imm_u16;
|
u16 imm_u16;
|
||||||
|
@ -86,6 +94,7 @@ using U32 = TypedValue<Type::U32>;
|
||||||
using U64 = TypedValue<Type::U64>;
|
using U64 = TypedValue<Type::U64>;
|
||||||
using F32 = TypedValue<Type::F32>;
|
using F32 = TypedValue<Type::F32>;
|
||||||
using F64 = TypedValue<Type::F64>;
|
using F64 = TypedValue<Type::F64>;
|
||||||
|
using F128 = TypedValue<Type::F128>;
|
||||||
using F32F64 = TypedValue<Type::F32 | Type::F64>;
|
using F32F64 = TypedValue<Type::F32 | Type::F64>;
|
||||||
|
|
||||||
} // namespace IR
|
} // namespace IR
|
||||||
|
|
Loading…
Reference in a new issue