JitX64: Implement branch instructions
This commit is contained in:
@@ -7,10 +7,16 @@ set(HEADERS
|
||||
|
||||
if(ARCHITECTURE_x86_64)
|
||||
set(SRCS ${SRCS}
|
||||
core/arm/jit_x64/rand_int.h
|
||||
core/arm/jit_x64/fuzz_arm_branch.cpp
|
||||
core/arm/jit_x64/fuzz_arm_common.cpp
|
||||
core/arm/jit_x64/fuzz_arm_data_processing.cpp
|
||||
core/arm/jit_x64/fuzz_thumb.cpp
|
||||
)
|
||||
|
||||
set(HEADERS ${HEADERS}
|
||||
core/arm/jit_x64/fuzz_arm_common.h
|
||||
core/arm/jit_x64/rand_int.h
|
||||
)
|
||||
endif()
|
||||
|
||||
create_directory_groups(${SRCS} ${HEADERS})
|
||||
|
||||
35
src/tests/core/arm/jit_x64/fuzz_arm_branch.cpp
Normal file
35
src/tests/core/arm/jit_x64/fuzz_arm_branch.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include "tests/core/arm/jit_x64/rand_int.h"
|
||||
#include "tests/core/arm/jit_x64/fuzz_arm_common.h"
|
||||
|
||||
TEST_CASE("Fuzz ARM branch instructions", "[JitX64]") {
|
||||
const std::array<std::pair<u32, u32>, 6> instructions = {{
|
||||
FromBitString32("1111101hvvvvvvvvvvvvvvvvvvvvvvvv"),
|
||||
FromBitString32("cccc000100101111111111110011mmmm"),
|
||||
FromBitString32("cccc1010vvvvvvvvvvvvvvvvvvvvvvvv"),
|
||||
FromBitString32("cccc1011vvvvvvvvvvvvvvvvvvvvvvvv"),
|
||||
FromBitString32("cccc000100101111111111110001mmmm"),
|
||||
FromBitString32("cccc000100101111111111110010mmmm"),
|
||||
}};
|
||||
|
||||
auto instruction_select = [&]() -> u32 {
|
||||
size_t inst_index = RandInt<size_t>(0, instructions.size() - 1);
|
||||
|
||||
u32 random = RandInt<u32>(0, 0xFFFFFFFF);
|
||||
|
||||
return instructions[inst_index].first | (random & (~instructions[inst_index].second));
|
||||
};
|
||||
|
||||
SECTION("R15") {
|
||||
FuzzJit(1, 1, 10000, instruction_select);
|
||||
}
|
||||
}
|
||||
143
src/tests/core/arm/jit_x64/fuzz_arm_common.cpp
Normal file
143
src/tests/core/arm/jit_x64/fuzz_arm_common.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/scope_exit.h"
|
||||
|
||||
#include "core/arm/disassembler/arm_disasm.h"
|
||||
#include "core/arm/dyncom/arm_dyncom.h"
|
||||
#include "core/arm/jit_x64/interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/memory_setup.h"
|
||||
|
||||
#include "tests/core/arm/jit_x64/fuzz_arm_common.h"
|
||||
#include "tests/core/arm/jit_x64/rand_int.h"
|
||||
|
||||
std::pair<u32, u32> FromBitString32(const char* str) {
|
||||
REQUIRE(strlen(str) == 32);
|
||||
|
||||
u32 bits = 0;
|
||||
u32 mask = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
const u32 bit = 1 << (31 - i);
|
||||
switch (str[i]) {
|
||||
case '0':
|
||||
mask |= bit;
|
||||
break;
|
||||
case '1':
|
||||
bits |= bit;
|
||||
mask |= bit;
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return{ bits, mask };
|
||||
}
|
||||
|
||||
void FuzzJit(const int instruction_count, const int instructions_to_execute_count, const int run_count, const std::function<u32()> instruction_generator) {
|
||||
// Init core
|
||||
Core::Init();
|
||||
SCOPE_EXIT({ Core::Shutdown(); });
|
||||
|
||||
// Prepare memory
|
||||
constexpr size_t MEMORY_SIZE = 4096 * 2;
|
||||
std::array<u8, MEMORY_SIZE> test_mem{};
|
||||
Memory::MapMemoryRegion(0, MEMORY_SIZE, test_mem.data());
|
||||
SCOPE_EXIT({ Memory::UnmapRegion(0, MEMORY_SIZE); });
|
||||
|
||||
// Prepare test subjects
|
||||
JitX64::ARM_Jit jit(PrivilegeMode::USER32MODE);
|
||||
ARM_DynCom interp(PrivilegeMode::USER32MODE);
|
||||
SCOPE_EXIT({
|
||||
jit.FastClearCache();
|
||||
interp.ClearCache();
|
||||
});
|
||||
|
||||
for (int run_number = 0; run_number < run_count; run_number++) {
|
||||
jit.FastClearCache();
|
||||
interp.ClearCache();
|
||||
|
||||
u32 initial_regs[15];
|
||||
for (int i = 0; i < 15; i++) {
|
||||
u32 val = RandInt<u32>(0, 0xFFFFFFFF);
|
||||
interp.SetReg(i, val);
|
||||
jit.SetReg(i, val);
|
||||
initial_regs[i] = val;
|
||||
}
|
||||
|
||||
interp.SetCPSR(0x000001d0);
|
||||
jit.SetCPSR(0x000001d0);
|
||||
|
||||
interp.SetPC(0);
|
||||
jit.SetPC(0);
|
||||
|
||||
for (int i = 0; i < instruction_count; i++) {
|
||||
u32 inst = instruction_generator();
|
||||
|
||||
Memory::Write32(i * 4, inst);
|
||||
}
|
||||
|
||||
Memory::Write32(instruction_count * 4, 0xEAFFFFFE); // b +#0 // busy wait loop
|
||||
|
||||
interp.ExecuteInstructions(instructions_to_execute_count);
|
||||
jit.ExecuteInstructions(instructions_to_execute_count);
|
||||
|
||||
bool pass = true;
|
||||
|
||||
if (interp.GetCPSR() != jit.GetCPSR()) pass = false;
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
if (interp.GetReg(i) != jit.GetReg(i)) pass = false;
|
||||
}
|
||||
|
||||
if (!pass) {
|
||||
printf("Failed at execution number %i\n", run_number);
|
||||
|
||||
printf("\nInstruction Listing: \n");
|
||||
for (int i = 0; i < instruction_count; i++) {
|
||||
printf("%s\n", ARM_Disasm::Disassemble(i * 4, Memory::Read32(i * 4)).c_str());
|
||||
}
|
||||
|
||||
printf("\nFinal Register Listing: \n");
|
||||
printf(" R interp jit\n");
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
printf("%4i: %08x %08x %s\n", i, interp.GetReg(i), jit.GetReg(i), interp.GetReg(i) != jit.GetReg(i) ? "*" : "");
|
||||
}
|
||||
printf("CPSR: %08x %08x %s\n", interp.GetCPSR(), jit.GetCPSR(), interp.GetCPSR() != jit.GetCPSR() ? "*" : "");
|
||||
|
||||
printf("\nInterpreter walkthrough:\n");
|
||||
interp.ClearCache();
|
||||
interp.SetPC(0);
|
||||
interp.SetCPSR(0x000001d0);
|
||||
for (int i = 0; i < 15; i++) {
|
||||
interp.SetReg(i, initial_regs[i]);
|
||||
printf("%4i: %08x\n", i, interp.GetReg(i));
|
||||
}
|
||||
for (int inst = 0; inst < instruction_count; inst++) {
|
||||
printf("%s\n", ARM_Disasm::Disassemble(inst * 4, Memory::Read32(inst * 4)).c_str());
|
||||
interp.Step();
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
printf("%4i: %08x\n", i, interp.GetReg(i));
|
||||
}
|
||||
printf("CPSR: %08x\n", interp.GetCPSR());
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
DebugBreak();
|
||||
#endif
|
||||
FAIL();
|
||||
}
|
||||
|
||||
printf("%i\r", run_number);
|
||||
if (run_number % 50 == 0) {
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/tests/core/arm/jit_x64/fuzz_arm_common.h
Normal file
22
src/tests/core/arm/jit_x64/fuzz_arm_common.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
std::pair<u32, u32> FromBitString32(const char* str);
|
||||
|
||||
/**
|
||||
* For run_count times:
|
||||
* 1. Generates instruction_count instructions using instruction_generator
|
||||
* 2. Requests JitX64 and interpreter to execute them for instructions_to_execute_count instructions
|
||||
* 3. Verifies that the register state are equivalent
|
||||
*
|
||||
* Note: A b #+0 instruction is appended to the list of instructions.
|
||||
*/
|
||||
void FuzzJit(const int instruction_count, const int instructions_to_execute_count, const int run_count, const std::function<u32()> instruction_generator);
|
||||
@@ -2,194 +2,65 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <array>
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/scope_exit.h"
|
||||
|
||||
#include "core/arm/disassembler/arm_disasm.h"
|
||||
#include "core/arm/dyncom/arm_dyncom.h"
|
||||
#include "core/arm/jit_x64/interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/memory_setup.h"
|
||||
|
||||
#include "tests/core/arm/jit_x64/rand_int.h"
|
||||
|
||||
std::pair<u32, u32> FromBitString(const char* str) {
|
||||
REQUIRE(strlen(str) == 32);
|
||||
|
||||
u32 bits = 0;
|
||||
u32 mask = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
const u32 bit = 1 << (31 - i);
|
||||
switch (str[i]) {
|
||||
case '0':
|
||||
mask |= bit;
|
||||
break;
|
||||
case '1':
|
||||
bits |= bit;
|
||||
mask |= bit;
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return { bits, mask };
|
||||
}
|
||||
|
||||
void FuzzJit(const int instruction_count, const int run_count, const std::function<u32()> instruction_generator) {
|
||||
// Init core
|
||||
Core::Init();
|
||||
SCOPE_EXIT({ Core::Shutdown(); });
|
||||
|
||||
// Prepare memory
|
||||
constexpr size_t MEMORY_SIZE = 4096 * 2;
|
||||
std::array<u8, MEMORY_SIZE> test_mem{};
|
||||
Memory::MapMemoryRegion(0, MEMORY_SIZE, test_mem.data());
|
||||
SCOPE_EXIT({ Memory::UnmapRegion(0, MEMORY_SIZE); });
|
||||
|
||||
// Prepare test subjects
|
||||
JitX64::ARM_Jit jit(PrivilegeMode::USER32MODE);
|
||||
ARM_DynCom interp(PrivilegeMode::USER32MODE);
|
||||
SCOPE_EXIT({
|
||||
jit.FastClearCache();
|
||||
interp.ClearCache();
|
||||
});
|
||||
|
||||
for (int run_number = 0; run_number < run_count; run_number++) {
|
||||
jit.FastClearCache();
|
||||
interp.ClearCache();
|
||||
|
||||
u32 initial_regs[15];
|
||||
for (int i = 0; i < 15; i++) {
|
||||
u32 val = RandInt<u32>(0, 0xFFFFFFFF);
|
||||
interp.SetReg(i, val);
|
||||
jit.SetReg(i, val);
|
||||
initial_regs[i] = val;
|
||||
}
|
||||
|
||||
interp.SetCPSR(0x000001d0);
|
||||
jit.SetCPSR(0x000001d0);
|
||||
|
||||
interp.SetPC(0);
|
||||
jit.SetPC(0);
|
||||
|
||||
for (int i = 0; i < instruction_count; i++) {
|
||||
u32 inst = instruction_generator();
|
||||
|
||||
Memory::Write32(i * 4, inst);
|
||||
}
|
||||
|
||||
Memory::Write32(instruction_count * 4, 0xEAFFFFFE); // b +#0 // busy wait loop
|
||||
|
||||
interp.ExecuteInstructions(instruction_count);
|
||||
jit.ExecuteInstructions(instruction_count);
|
||||
|
||||
bool pass = true;
|
||||
|
||||
if (interp.GetCPSR() != jit.GetCPSR()) pass = false;
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
if (interp.GetReg(i) != jit.GetReg(i)) pass = false;
|
||||
}
|
||||
|
||||
if (!pass) {
|
||||
printf("Failed at execution number %i\n", run_number);
|
||||
|
||||
printf("\nInstruction Listing: \n");
|
||||
for (int i = 0; i < instruction_count; i++) {
|
||||
printf("%s\n", ARM_Disasm::Disassemble(i * 4, Memory::Read32(i * 4)).c_str());
|
||||
}
|
||||
|
||||
printf("\nFinal Register Listing: \n");
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
printf("%4i: %08x %08x %s\n", i, interp.GetReg(i), jit.GetReg(i), interp.GetReg(i) != jit.GetReg(i) ? "*" : "");
|
||||
}
|
||||
printf("CPSR: %08x %08x %s\n", interp.GetCPSR(), jit.GetCPSR(), interp.GetCPSR() != jit.GetCPSR() ? "*" : "");
|
||||
|
||||
printf("\nInterpreter walkthrough:\n");
|
||||
interp.ClearCache();
|
||||
interp.SetPC(0);
|
||||
interp.SetCPSR(0x000001d0);
|
||||
for (int i = 0; i < 15; i++) {
|
||||
interp.SetReg(i, initial_regs[i]);
|
||||
printf("%4i: %08x\n", i, interp.GetReg(i));
|
||||
}
|
||||
for (int inst = 0; inst < instruction_count; inst++) {
|
||||
printf("%s\n", ARM_Disasm::Disassemble(inst * 4, Memory::Read32(inst * 4)).c_str());
|
||||
interp.Step();
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
printf("%4i: %08x\n", i, interp.GetReg(i));
|
||||
}
|
||||
printf("CPSR: %08x\n", interp.GetCPSR());
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
DebugBreak();
|
||||
#endif
|
||||
FAIL();
|
||||
}
|
||||
|
||||
printf("%i\r", run_number);
|
||||
if (run_number % 50 == 0) {
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "tests/core/arm/jit_x64/fuzz_arm_common.h"
|
||||
|
||||
TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
|
||||
const std::array<std::pair<u32, u32>, 48> instructions = {{
|
||||
FromBitString("cccc0010101Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0000101Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0000101Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0010100Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0000100Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0000100Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0010000Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0000000Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0000000Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0011110Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0001110Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0001110Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc00110111nnnn0000rrrrvvvvvvvv"),
|
||||
FromBitString("cccc00010111nnnn0000vvvvvrr0mmmm"),
|
||||
FromBitString("cccc00010111nnnn0000ssss0rr1mmmm"),
|
||||
FromBitString("cccc00110101nnnn0000rrrrvvvvvvvv"),
|
||||
FromBitString("cccc00010101nnnn0000vvvvvrr0mmmm"),
|
||||
FromBitString("cccc00010101nnnn0000ssss0rr1mmmm"),
|
||||
FromBitString("cccc0010001Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0000001Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0000001Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0011101S0000ddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0001101S0000ddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0001101S0000ddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0011111S0000ddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0001111S0000ddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0001111S0000ddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0011100Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0001100Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0001100Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0010011Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0000011Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0000011Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0010111Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0000111Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0000111Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0010110Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0000110Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0000110Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc0010010Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString("cccc0000010Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString("cccc0000010Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString("cccc00110011nnnn0000rrrrvvvvvvvv"),
|
||||
FromBitString("cccc00010011nnnn0000vvvvvrr0mmmm"),
|
||||
FromBitString("cccc00010011nnnn0000ssss0rr1mmmm"),
|
||||
FromBitString("cccc00110001nnnn0000rrrrvvvvvvvv"),
|
||||
FromBitString("cccc00010001nnnn0000vvvvvrr0mmmm"),
|
||||
FromBitString("cccc00010001nnnn0000ssss0rr1mmmm"),
|
||||
FromBitString32("cccc0010101Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0000101Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0000101Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0010100Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0000100Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0000100Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0010000Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0000000Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0000000Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0011110Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0001110Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0001110Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc00110111nnnn0000rrrrvvvvvvvv"),
|
||||
FromBitString32("cccc00010111nnnn0000vvvvvrr0mmmm"),
|
||||
FromBitString32("cccc00010111nnnn0000ssss0rr1mmmm"),
|
||||
FromBitString32("cccc00110101nnnn0000rrrrvvvvvvvv"),
|
||||
FromBitString32("cccc00010101nnnn0000vvvvvrr0mmmm"),
|
||||
FromBitString32("cccc00010101nnnn0000ssss0rr1mmmm"),
|
||||
FromBitString32("cccc0010001Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0000001Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0000001Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0011101S0000ddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0001101S0000ddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0001101S0000ddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0011111S0000ddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0001111S0000ddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0001111S0000ddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0011100Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0001100Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0001100Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0010011Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0000011Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0000011Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0010111Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0000111Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0000111Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0010110Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0000110Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0000110Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc0010010Snnnnddddrrrrvvvvvvvv"),
|
||||
FromBitString32("cccc0000010Snnnnddddvvvvvrr0mmmm"),
|
||||
FromBitString32("cccc0000010Snnnnddddssss0rr1mmmm"),
|
||||
FromBitString32("cccc00110011nnnn0000rrrrvvvvvvvv"),
|
||||
FromBitString32("cccc00010011nnnn0000vvvvvrr0mmmm"),
|
||||
FromBitString32("cccc00010011nnnn0000ssss0rr1mmmm"),
|
||||
FromBitString32("cccc00110001nnnn0000rrrrvvvvvvvv"),
|
||||
FromBitString32("cccc00010001nnnn0000vvvvvrr0mmmm"),
|
||||
FromBitString32("cccc00010001nnnn0000ssss0rr1mmmm"),
|
||||
}};
|
||||
|
||||
auto instruction_select_without_R15 = [&]() -> u32 {
|
||||
@@ -212,11 +83,11 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
|
||||
};
|
||||
|
||||
SECTION("short blocks") {
|
||||
FuzzJit(5, 5000, instruction_select_without_R15);
|
||||
FuzzJit(5, 6, 5000, instruction_select_without_R15);
|
||||
}
|
||||
|
||||
SECTION("long blocks") {
|
||||
FuzzJit(1024, 15, instruction_select_without_R15);
|
||||
FuzzJit(1024, 1025, 15, instruction_select_without_R15);
|
||||
}
|
||||
|
||||
auto instruction_select_only_R15 = [&]() -> u32 {
|
||||
@@ -239,6 +110,6 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
|
||||
};
|
||||
|
||||
SECTION("R15") {
|
||||
FuzzJit(1, 10000, instruction_select_only_R15);
|
||||
FuzzJit(1, 1, 10000, instruction_select_only_R15);
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ std::pair<u16, u16> FromBitString16(const char* str) {
|
||||
return{ bits, mask };
|
||||
}
|
||||
|
||||
void FuzzJitThumb(const int instruction_count, const int run_count, const std::function<u16(int)> instruction_generator) {
|
||||
void FuzzJitThumb(const int instruction_count, const int run_count, const std::function<u16(int)> instruction_generator, bool run_plus_1 = true) {
|
||||
// Init core
|
||||
Core::Init();
|
||||
SCOPE_EXIT({ Core::Shutdown(); });
|
||||
@@ -87,8 +87,8 @@ void FuzzJitThumb(const int instruction_count, const int run_count, const std::f
|
||||
|
||||
Memory::Write16(4 + instruction_count * 2, 0xE7FE); // b +#0 // busy wait loop
|
||||
|
||||
interp.ExecuteInstructions(instruction_count + 1);
|
||||
jit.ExecuteInstructions(instruction_count + 1);
|
||||
interp.ExecuteInstructions(run_plus_1 ? instruction_count + 2 : instruction_count + 1);
|
||||
jit.ExecuteInstructions(run_plus_1 ? instruction_count + 2 : instruction_count + 1);
|
||||
|
||||
bool pass = true;
|
||||
|
||||
@@ -208,7 +208,7 @@ TEST_CASE("Fuzz Thumb instructions set 2 (affects PC)", "[JitX64][Thumb]") {
|
||||
return instructions[inst_index].first | (random &~ instructions[inst_index].second);
|
||||
};
|
||||
|
||||
FuzzJitThumb(1, 10000, instruction_select);
|
||||
FuzzJitThumb(1, 10000, instruction_select, false);
|
||||
}
|
||||
|
||||
TEST_CASE("Fuzz Thumb instructions set 3 (32-bit BL/BLX)", "[JitX64][Thumb]") {
|
||||
@@ -227,5 +227,5 @@ TEST_CASE("Fuzz Thumb instructions set 3 (32-bit BL/BLX)", "[JitX64][Thumb]") {
|
||||
return inst_info.first | (random &~ inst_info.second);
|
||||
};
|
||||
|
||||
FuzzJitThumb(1, 1000, instruction_select);
|
||||
FuzzJitThumb(1, 1000, instruction_select, false);
|
||||
}
|
||||
@@ -5,9 +5,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <random>
|
||||
#include <type_traits>
|
||||
|
||||
template <typename T>
|
||||
T RandInt(T min, T max) {
|
||||
static_assert(std::is_integral<T>::value, "T must be an integral type.");
|
||||
static_assert(!std::is_same<T, signed char>::value && !std::is_same<T, unsigned char>::value,
|
||||
"Using char with uniform_int_distribution is undefined behavior.");
|
||||
|
||||
static std::random_device rd;
|
||||
static std::mt19937 mt(rd());
|
||||
std::uniform_int_distribution<T> rand(min, max);
|
||||
|
||||
Reference in New Issue
Block a user