tests/unicorn: Add type aliases to the Unicorn class
Centralizes all register and vector array definitions to a single set of aliases, so if these are ever changed, then the rest of the testing code will follow suit without the need to manually change them.
This commit is contained in:
parent
a1d6a86e8c
commit
a25bacc436
4 changed files with 41 additions and 36 deletions
|
@ -148,7 +148,8 @@ static u32 GenFloatInst(u64 pc, bool is_last_inst) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RunTestInstance(const std::array<u64, 31>& regs, const std::array<Vector, 32>& vecs, const size_t instructions_offset, const std::vector<u32>& instructions, const u32 pstate, const u32 fpcr) {
|
static void RunTestInstance(const Unicorn::RegisterArray& regs, const Unicorn::VectorArray& vecs, const size_t instructions_offset,
|
||||||
|
const std::vector<u32>& instructions, const u32 pstate, const u32 fpcr) {
|
||||||
static TestEnv jit_env;
|
static TestEnv jit_env;
|
||||||
static TestEnv uni_env;
|
static TestEnv uni_env;
|
||||||
|
|
||||||
|
@ -243,8 +244,8 @@ static void RunTestInstance(const std::array<u64, 31>& regs, const std::array<Ve
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("A64: Single random instruction", "[a64]") {
|
TEST_CASE("A64: Single random instruction", "[a64]") {
|
||||||
std::array<u64, 31> regs;
|
Unicorn::RegisterArray regs;
|
||||||
std::array<Vector, 32> vecs;
|
Unicorn::VectorArray vecs;
|
||||||
std::vector<u32> instructions(1);
|
std::vector<u32> instructions(1);
|
||||||
|
|
||||||
for (size_t iteration = 0; iteration < 100000; ++iteration) {
|
for (size_t iteration = 0; iteration < 100000; ++iteration) {
|
||||||
|
@ -356,8 +357,8 @@ TEST_CASE("A64: Floating point instructions", "[a64]") {
|
||||||
return Vector{lower, upper};
|
return Vector{lower, upper};
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<u64, 31> regs;
|
Unicorn::RegisterArray regs;
|
||||||
std::array<Vector, 32> vecs;
|
Unicorn::VectorArray vecs;
|
||||||
std::vector<u32> instructions(1);
|
std::vector<u32> instructions(1);
|
||||||
|
|
||||||
for (size_t iteration = 0; iteration < 100000; ++iteration) {
|
for (size_t iteration = 0; iteration < 100000; ++iteration) {
|
||||||
|
@ -374,8 +375,8 @@ TEST_CASE("A64: Floating point instructions", "[a64]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("A64: Small random block", "[a64]") {
|
TEST_CASE("A64: Small random block", "[a64]") {
|
||||||
std::array<u64, 31> regs;
|
Unicorn::RegisterArray regs;
|
||||||
std::array<Vector, 32> vecs;
|
Unicorn::VectorArray vecs;
|
||||||
std::vector<u32> instructions(5);
|
std::vector<u32> instructions(5);
|
||||||
|
|
||||||
for (size_t iteration = 0; iteration < 100000; ++iteration) {
|
for (size_t iteration = 0; iteration < 100000; ++iteration) {
|
||||||
|
|
|
@ -60,18 +60,17 @@ void Unicorn::SetPC(u64 value) {
|
||||||
CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &value));
|
CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &value));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t num_gprs = 31;
|
constexpr std::array<int, Unicorn::num_gprs> gpr_ids{
|
||||||
static const std::array<int, num_gprs> gpr_ids {
|
|
||||||
UC_ARM64_REG_X0, UC_ARM64_REG_X1, UC_ARM64_REG_X2, UC_ARM64_REG_X3, UC_ARM64_REG_X4, UC_ARM64_REG_X5, UC_ARM64_REG_X6, UC_ARM64_REG_X7,
|
UC_ARM64_REG_X0, UC_ARM64_REG_X1, UC_ARM64_REG_X2, UC_ARM64_REG_X3, UC_ARM64_REG_X4, UC_ARM64_REG_X5, UC_ARM64_REG_X6, UC_ARM64_REG_X7,
|
||||||
UC_ARM64_REG_X8, UC_ARM64_REG_X9, UC_ARM64_REG_X10, UC_ARM64_REG_X11, UC_ARM64_REG_X12, UC_ARM64_REG_X13, UC_ARM64_REG_X14, UC_ARM64_REG_X15,
|
UC_ARM64_REG_X8, UC_ARM64_REG_X9, UC_ARM64_REG_X10, UC_ARM64_REG_X11, UC_ARM64_REG_X12, UC_ARM64_REG_X13, UC_ARM64_REG_X14, UC_ARM64_REG_X15,
|
||||||
UC_ARM64_REG_X16, UC_ARM64_REG_X17, UC_ARM64_REG_X18, UC_ARM64_REG_X19, UC_ARM64_REG_X20, UC_ARM64_REG_X21, UC_ARM64_REG_X22, UC_ARM64_REG_X23,
|
UC_ARM64_REG_X16, UC_ARM64_REG_X17, UC_ARM64_REG_X18, UC_ARM64_REG_X19, UC_ARM64_REG_X20, UC_ARM64_REG_X21, UC_ARM64_REG_X22, UC_ARM64_REG_X23,
|
||||||
UC_ARM64_REG_X24, UC_ARM64_REG_X25, UC_ARM64_REG_X26, UC_ARM64_REG_X27, UC_ARM64_REG_X28, UC_ARM64_REG_X29, UC_ARM64_REG_X30
|
UC_ARM64_REG_X24, UC_ARM64_REG_X25, UC_ARM64_REG_X26, UC_ARM64_REG_X27, UC_ARM64_REG_X28, UC_ARM64_REG_X29, UC_ARM64_REG_X30
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<u64, 31> Unicorn::GetRegisters() const {
|
Unicorn::RegisterArray Unicorn::GetRegisters() const {
|
||||||
std::array<u64, num_gprs> regs;
|
RegisterArray regs;
|
||||||
std::array<u64*, num_gprs> ptrs;
|
RegisterPtrArray ptrs;
|
||||||
for (size_t i = 0; i < num_gprs; ++i)
|
for (size_t i = 0; i < ptrs.size(); ++i)
|
||||||
ptrs[i] = ®s[i];
|
ptrs[i] = ®s[i];
|
||||||
|
|
||||||
CHECKED(uc_reg_read_batch(uc, const_cast<int*>(gpr_ids.data()),
|
CHECKED(uc_reg_read_batch(uc, const_cast<int*>(gpr_ids.data()),
|
||||||
|
@ -79,28 +78,26 @@ std::array<u64, 31> Unicorn::GetRegisters() const {
|
||||||
return regs;
|
return regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unicorn::SetRegisters(const std::array<u64, 31>& value) {
|
void Unicorn::SetRegisters(const RegisterArray& value) {
|
||||||
std::array<const u64*, num_gprs> ptrs;
|
RegisterConstPtrArray ptrs;
|
||||||
for (size_t i = 0; i < num_gprs; ++i)
|
for (size_t i = 0; i < ptrs.size(); ++i)
|
||||||
ptrs[i] = &value[i];
|
ptrs[i] = &value[i];
|
||||||
|
|
||||||
CHECKED(uc_reg_write_batch(uc, const_cast<int*>(gpr_ids.data()),
|
CHECKED(uc_reg_write_batch(uc, const_cast<int*>(gpr_ids.data()),
|
||||||
reinterpret_cast<void**>(const_cast<u64**>(ptrs.data())), num_gprs));
|
reinterpret_cast<void**>(const_cast<u64**>(ptrs.data())), num_gprs));
|
||||||
}
|
}
|
||||||
|
|
||||||
using Vector = Unicorn::Vector;
|
constexpr std::array<int, Unicorn::num_vecs> vec_ids{
|
||||||
constexpr size_t num_vecs = 32;
|
|
||||||
static const std::array<int, num_vecs> vec_ids {
|
|
||||||
UC_ARM64_REG_Q0, UC_ARM64_REG_Q1, UC_ARM64_REG_Q2, UC_ARM64_REG_Q3, UC_ARM64_REG_Q4, UC_ARM64_REG_Q5, UC_ARM64_REG_Q6, UC_ARM64_REG_Q7,
|
UC_ARM64_REG_Q0, UC_ARM64_REG_Q1, UC_ARM64_REG_Q2, UC_ARM64_REG_Q3, UC_ARM64_REG_Q4, UC_ARM64_REG_Q5, UC_ARM64_REG_Q6, UC_ARM64_REG_Q7,
|
||||||
UC_ARM64_REG_Q8, UC_ARM64_REG_Q9, UC_ARM64_REG_Q10, UC_ARM64_REG_Q11, UC_ARM64_REG_Q12, UC_ARM64_REG_Q13, UC_ARM64_REG_Q14, UC_ARM64_REG_Q15,
|
UC_ARM64_REG_Q8, UC_ARM64_REG_Q9, UC_ARM64_REG_Q10, UC_ARM64_REG_Q11, UC_ARM64_REG_Q12, UC_ARM64_REG_Q13, UC_ARM64_REG_Q14, UC_ARM64_REG_Q15,
|
||||||
UC_ARM64_REG_Q16, UC_ARM64_REG_Q17, UC_ARM64_REG_Q18, UC_ARM64_REG_Q19, UC_ARM64_REG_Q20, UC_ARM64_REG_Q21, UC_ARM64_REG_Q22, UC_ARM64_REG_Q23,
|
UC_ARM64_REG_Q16, UC_ARM64_REG_Q17, UC_ARM64_REG_Q18, UC_ARM64_REG_Q19, UC_ARM64_REG_Q20, UC_ARM64_REG_Q21, UC_ARM64_REG_Q22, UC_ARM64_REG_Q23,
|
||||||
UC_ARM64_REG_Q24, UC_ARM64_REG_Q25, UC_ARM64_REG_Q26, UC_ARM64_REG_Q27, UC_ARM64_REG_Q28, UC_ARM64_REG_Q29, UC_ARM64_REG_Q30, UC_ARM64_REG_Q31
|
UC_ARM64_REG_Q24, UC_ARM64_REG_Q25, UC_ARM64_REG_Q26, UC_ARM64_REG_Q27, UC_ARM64_REG_Q28, UC_ARM64_REG_Q29, UC_ARM64_REG_Q30, UC_ARM64_REG_Q31
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<Vector, 32> Unicorn::GetVectors() const {
|
Unicorn::VectorArray Unicorn::GetVectors() const {
|
||||||
std::array<Vector, num_vecs> vecs;
|
VectorArray vecs;
|
||||||
std::array<Vector*, num_vecs> ptrs;
|
VectorPtrArray ptrs;
|
||||||
for (size_t i = 0; i < num_vecs; ++i)
|
for (size_t i = 0; i < ptrs.size(); ++i)
|
||||||
ptrs[i] = &vecs[i];
|
ptrs[i] = &vecs[i];
|
||||||
|
|
||||||
CHECKED(uc_reg_read_batch(uc, const_cast<int*>(vec_ids.data()),
|
CHECKED(uc_reg_read_batch(uc, const_cast<int*>(vec_ids.data()),
|
||||||
|
@ -109,9 +106,9 @@ std::array<Vector, 32> Unicorn::GetVectors() const {
|
||||||
return vecs;
|
return vecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unicorn::SetVectors(const std::array<Vector, 32>& value) {
|
void Unicorn::SetVectors(const VectorArray& value) {
|
||||||
std::array<const Vector*, num_vecs> ptrs;
|
VectorConstPtrArray ptrs;
|
||||||
for (size_t i = 0; i < num_vecs; ++i)
|
for (size_t i = 0; i < ptrs.size(); ++i)
|
||||||
ptrs[i] = &value[i];
|
ptrs[i] = &value[i];
|
||||||
|
|
||||||
CHECKED(uc_reg_write_batch(uc, const_cast<int*>(vec_ids.data()),
|
CHECKED(uc_reg_write_batch(uc, const_cast<int*>(vec_ids.data()),
|
||||||
|
|
|
@ -16,6 +16,16 @@
|
||||||
|
|
||||||
class Unicorn final {
|
class Unicorn final {
|
||||||
public:
|
public:
|
||||||
|
static constexpr size_t num_gprs = 31;
|
||||||
|
using RegisterArray = std::array<u64, num_gprs>;
|
||||||
|
using RegisterPtrArray = std::array<RegisterArray::pointer, num_gprs>;
|
||||||
|
using RegisterConstPtrArray = std::array<RegisterArray::const_pointer, num_gprs>;
|
||||||
|
|
||||||
|
static constexpr size_t num_vecs = 32;
|
||||||
|
using VectorArray = std::array<Vector, num_vecs>;
|
||||||
|
using VectorPtrArray = std::array<VectorArray::pointer, num_vecs>;
|
||||||
|
using VectorConstPtrArray = std::array<VectorArray::const_pointer, num_vecs>;
|
||||||
|
|
||||||
explicit Unicorn(TestEnv& testenv);
|
explicit Unicorn(TestEnv& testenv);
|
||||||
~Unicorn();
|
~Unicorn();
|
||||||
|
|
||||||
|
@ -27,14 +37,11 @@ public:
|
||||||
u64 GetPC() const;
|
u64 GetPC() const;
|
||||||
void SetPC(u64 value);
|
void SetPC(u64 value);
|
||||||
|
|
||||||
std::array<u64, 31> GetRegisters() const;
|
RegisterArray GetRegisters() const;
|
||||||
void SetRegisters(const std::array<u64, 31>& value);
|
void SetRegisters(const RegisterArray& value);
|
||||||
|
|
||||||
using Vector = std::array<u64, 2>;
|
VectorArray GetVectors() const;
|
||||||
static_assert(sizeof(Vector) == sizeof(u64) * 2);
|
void SetVectors(const VectorArray& value);
|
||||||
|
|
||||||
std::array<Vector, 32> GetVectors() const;
|
|
||||||
void SetVectors(const std::array<Vector, 32>& value);
|
|
||||||
|
|
||||||
u32 GetFpcr() const;
|
u32 GetFpcr() const;
|
||||||
void SetFpcr(u32 value);
|
void SetFpcr(u32 value);
|
||||||
|
|
|
@ -19,7 +19,7 @@ TEST_CASE("Unicorn: Sanity test", "[a64]") {
|
||||||
env.code_mem[0] = 0x8b020020; // ADD X0, X1, X2
|
env.code_mem[0] = 0x8b020020; // ADD X0, X1, X2
|
||||||
env.code_mem[1] = 0x14000000; // B .
|
env.code_mem[1] = 0x14000000; // B .
|
||||||
|
|
||||||
std::array<u64, 31> regs {
|
constexpr Unicorn::RegisterArray regs{
|
||||||
0, 1, 2, 0, 0, 0, 0, 0,
|
0, 1, 2, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
@ -46,7 +46,7 @@ TEST_CASE("Unicorn: Ensure 0xFFFF'FFFF'FFFF'FFFF is readable", "[a64]") {
|
||||||
env.code_mem[0] = 0x385fed99; // LDRB W25, [X12, #0xfffffffffffffffe]!
|
env.code_mem[0] = 0x385fed99; // LDRB W25, [X12, #0xfffffffffffffffe]!
|
||||||
env.code_mem[1] = 0x14000000; // B .
|
env.code_mem[1] = 0x14000000; // B .
|
||||||
|
|
||||||
std::array<u64, 31> regs{};
|
Unicorn::RegisterArray regs{};
|
||||||
regs[12] = 1;
|
regs[12] = 1;
|
||||||
|
|
||||||
Unicorn unicorn{env};
|
Unicorn unicorn{env};
|
||||||
|
@ -66,7 +66,7 @@ TEST_CASE("Unicorn: Ensure is able to read across page boundaries", "[a64]") {
|
||||||
env.code_mem[0] = 0xb85f93d9; // LDUR W25, [X30, #0xfffffffffffffff9]
|
env.code_mem[0] = 0xb85f93d9; // LDUR W25, [X30, #0xfffffffffffffff9]
|
||||||
env.code_mem[1] = 0x14000000; // B .
|
env.code_mem[1] = 0x14000000; // B .
|
||||||
|
|
||||||
std::array<u64, 31> regs{};
|
Unicorn::RegisterArray regs{};
|
||||||
regs[30] = 4;
|
regs[30] = 4;
|
||||||
|
|
||||||
Unicorn unicorn{env};
|
Unicorn unicorn{env};
|
||||||
|
|
Loading…
Reference in a new issue