Merged in Subv/dynarmic/arm_mem_tests (pull request #4)

Added some fuzz tests for most cases of ARM Load/Store instructions
This commit is contained in:
Merry 2016-07-20 10:19:55 +01:00
commit 95316b8443
2 changed files with 188 additions and 18 deletions

View file

@ -181,8 +181,8 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
//INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"),
//INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"),
//INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"),
//INST(&V::arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------"),
//INST(&V::arm_LDRBT, "LDRBT (A2)", "----0110-111---------------0----"),
//INST(&V::arm_LDRBT, "LDRBT (A1)", "cccc0100u111nnnnttttvvvvvvvvvvvv"),
//INST(&V::arm_LDRBT, "LDRBT (A2)", "cccc0110u111nnnnttttvvvvvrr0mmmm"),
//INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E
//INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E
//INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"),
@ -197,22 +197,22 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
//INST(&V::arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnndddd00001111mmmm"),
//INST(&V::arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----"),
//INST(&V::arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----"),
//INST(&V::arm_LDRT, "LDRT (A1)", "----0100-011--------------------"),
//INST(&V::arm_LDRT, "LDRT (A2)", "----0110-011---------------0----"),
//INST(&V::arm_LDRT, "LDRT (A1)", "cccc0100u011nnnnttttvvvvvvvvvvvv"),
//INST(&V::arm_LDRT, "LDRT (A2)", "cccc0110u011nnnnttttvvvvvrr0mmmm"),
//INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnddddvvvvvvvvvvvv"),
//INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnddddvvvvvrr0mmmm"),
//INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnddddvvvvvvvvvvvv"),
//INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"),
//INST(&V::arm_STRBT, "STRBT (A1)", "----0100-110--------------------"),
//INST(&V::arm_STRBT, "STRBT (A2)", "----0110-110---------------0----"),
//INST(&V::arm_STRBT, "STRBT (A1)", "cccc0100u110nnnnttttvvvvvvvvvvvv"),
//INST(&V::arm_STRBT, "STRBT (A2)", "cccc0110u110nnnnttttvvvvvrr0mmmm"),
//INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E
//INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnndddd00001111mmmm"), // v5E
//INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnddddvvvv1011vvvv"),
//INST(&V::arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnndddd00001011mmmm"),
//INST(&V::arm_STRHT, "STRHT (A1)", "----0000-110------------1011----"),
//INST(&V::arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----"),
//INST(&V::arm_STRT, "STRT (A1)", "----0100-010--------------------"),
//INST(&V::arm_STRT, "STRT (A2)", "----0110-010---------------0----"),
//INST(&V::arm_STRT, "STRT (A1)", "cccc0100u010nnnnttttvvvvvvvvvvvv"),
//INST(&V::arm_STRT, "STRT (A2)", "cccc0110u010nnnnttttvvvvvrr0mmmm"),
// Load/Store Multiple instructions
//INST(&V::arm_LDM, "LDM", "cccc100pu0w1nnnnxxxxxxxxxxxxxxxx"), // all

View file

@ -366,29 +366,199 @@ TEST_CASE("Fuzz ARM reversal instructions", "[JitX64]") {
return Dynarmic::Common::Bits<0, 3>(instr) != 0b1111 && Dynarmic::Common::Bits<12, 15>(instr) != 0b1111;
};
const std::array<InstructionGenerator, 3> reg_instructions = {
const std::array<InstructionGenerator, 3> rev_instructions = {
{
InstructionGenerator("cccc011010111111dddd11110011mmmm", is_valid),
InstructionGenerator("cccc011010111111dddd11111011mmmm", is_valid),
InstructionGenerator("cccc011011111111dddd11111011mmmm", is_valid),
InstructionGenerator("0000011010111111dddd11110011mmmm", is_valid),
InstructionGenerator("0000011010111111dddd11111011mmmm", is_valid),
InstructionGenerator("0000011011111111dddd11111011mmmm", is_valid),
}
};
SECTION("REV tests") {
FuzzJitArm(1, 1, 10000, [&reg_instructions]() -> u32 {
return reg_instructions[0].Generate();
FuzzJitArm(1, 1, 10000, [&rev_instructions]() -> u32 {
u32 cond = 0xE;
// Have a one-in-twenty-five chance of actually having a cond.
if (RandInt(1, 25) == 1) {
cond = RandInt<u32>(0x0, 0xD);
}
return rev_instructions[0].Generate() | (cond << 28);
});
}
SECTION("REV16 tests") {
FuzzJitArm(1, 1, 10000, [&reg_instructions]() -> u32 {
return reg_instructions[1].Generate();
FuzzJitArm(1, 1, 10000, [&rev_instructions]() -> u32 {
u32 cond = 0xE;
// Have a one-in-twenty-five chance of actually having a cond.
if (RandInt(1, 25) == 1) {
cond = RandInt<u32>(0x0, 0xD);
}
return rev_instructions[1].Generate() | (cond << 28);
});
}
SECTION("REVSH tests") {
FuzzJitArm(1, 1, 10000, [&reg_instructions]() -> u32 {
return reg_instructions[2].Generate();
FuzzJitArm(1, 1, 10000, [&rev_instructions]() -> u32 {
u32 cond = 0xE;
// Have a one-in-twenty-five chance of actually having a cond.
if (RandInt(1, 25) == 1) {
cond = RandInt<u32>(0x0, 0xD);
}
return rev_instructions[2].Generate() | (cond << 28);
});
}
}
TEST_CASE("Fuzz ARM Load/Store instructions", "[JitX64]") {
auto forbid_r15 = [](u32 inst) -> bool {
return Dynarmic::Common::Bits<12, 15>(inst) != 0b1111;
};
auto forbid_r14_and_r15 = [](u32 inst) -> bool {
return Dynarmic::Common::Bits<13, 15>(inst) != 0b111;
};
const std::array<InstructionGenerator, 4> doubleword_instructions = {
{
// Load
InstructionGenerator("0000000pu1w0nnnnddd0vvvv1101vvvv", forbid_r14_and_r15),
InstructionGenerator("0000000pu0w0nnnnddd000001101mmmm", forbid_r14_and_r15),
// Store
InstructionGenerator("0000000pu1w0nnnnddd0vvvv1111vvvv", forbid_r14_and_r15),
InstructionGenerator("0000000pu0w0nnnnddd000001111mmmm", forbid_r14_and_r15),
}
};
const std::array<InstructionGenerator, 8> word_instructions = {
{
// Load
InstructionGenerator("0000010pu0w1nnnnddddvvvvvvvvvvvv", forbid_r15),
InstructionGenerator("0000011pu0w1nnnnddddvvvvvrr0mmmm", forbid_r15),
InstructionGenerator("00000100u011nnnnttttmmmmmmmmmmmm", forbid_r15),
InstructionGenerator("00000110u011nnnnttttvvvvvrr0mmmm", forbid_r15),
// Store
InstructionGenerator("0000010pu0w0nnnnddddvvvvvvvvvvvv", forbid_r15),
InstructionGenerator("0000011pu0w0nnnnddddvvvvvrr0mmmm", forbid_r15),
InstructionGenerator("00000100u010nnnnttttvvvvvvvvvvvv", forbid_r15),
InstructionGenerator("00000110u010nnnnttttvvvvvrr0mmmm", forbid_r15),
}
};
const std::array<InstructionGenerator, 6> halfword_instructions = {
{
// Load
InstructionGenerator("0000000pu1w1nnnnddddvvvv1011vvvv", forbid_r15),
InstructionGenerator("0000000pu0w1nnnndddd00001011mmmm", forbid_r15),
// InstructionGenerator("----0000-111------------1011----"), // LDRHT (A1) Not available in ARMv6K
// InstructionGenerator("----0000-011--------00001011----"), // LDRHT (A2) Not available in ARMv6K
InstructionGenerator("0000000pu1w1nnnnddddvvvv1111vvvv", forbid_r15),
InstructionGenerator("0000000pu0w1nnnndddd00001111mmmm", forbid_r15),
// InstructionGenerator("----0000-111------------1111----"), // LDRSHT (A1) Not available in ARMv6K
// InstructionGenerator("----0000-011--------00001111----"), // LDRSHT (A2) Not available in ARMv6K
// Store
InstructionGenerator("0000000pu1w0nnnnddddvvvv1011vvvv", forbid_r15),
InstructionGenerator("0000000pu0w0nnnndddd00001011mmmm", forbid_r15),
// InstructionGenerator("----0000-110------------1011----"), // STRHT (A1) Not available in ARMv6K
// InstructionGenerator("----0000-010--------00001011----"), // STRHT (A2) Not available in ARMv6K
}
};
const std::array<InstructionGenerator, 10> byte_instructions = {
{
// Load
InstructionGenerator("0000010pu1w1nnnnddddvvvvvvvvvvvv", forbid_r15),
InstructionGenerator("0000011pu1w1nnnnddddvvvvvrr0mmmm", forbid_r15),
InstructionGenerator("00000100u111nnnnttttvvvvvvvvvvvv", forbid_r15),
InstructionGenerator("00000110u111nnnnttttvvvvvrr0mmmm", forbid_r15),
InstructionGenerator("0000000pu1w1nnnnddddvvvv1101vvvv", forbid_r15),
InstructionGenerator("0000000pu0w1nnnndddd00001101mmmm", forbid_r15),
// InstructionGenerator("----0000-111------------1101----"), // LDRSBT (A1) Not available in ARMv6K
// InstructionGenerator("----0000-011--------00001101----"), // LDRSBT (A2) Not available in ARMv6K
// Store
InstructionGenerator("0000010pu1w0nnnnddddvvvvvvvvvvvv", forbid_r15),
InstructionGenerator("0000011pu1w0nnnnddddvvvvvrr0mmmm", forbid_r15),
InstructionGenerator("00000100u110nnnnttttvvvvvvvvvvvv", forbid_r15),
InstructionGenerator("00000110u110nnnnttttvvvvvrr0mmmm", forbid_r15),
}
};
SECTION("Doubleword tests") {
FuzzJitArm(1, 1, 10000, [&doubleword_instructions]() -> u32 {
u32 cond = 0xE;
// Have a one-in-twenty-five chance of actually having a cond.
if (RandInt(1, 25) == 1) {
cond = RandInt<u32>(0x0, 0xD);
}
return doubleword_instructions[RandInt<size_t>(0, doubleword_instructions.size() - 1)].Generate() | (cond << 28);
});
}
SECTION("Word tests") {
FuzzJitArm(1, 1, 10000, [&word_instructions]() -> u32 {
u32 cond = 0xE;
// Have a one-in-twenty-five chance of actually having a cond.
if (RandInt(1, 25) == 1) {
cond = RandInt<u32>(0x0, 0xD);
}
return word_instructions[RandInt<size_t>(0, word_instructions.size() - 1)].Generate() | (cond << 28);
});
}
SECTION("Halfword tests") {
FuzzJitArm(1, 1, 10000, [&halfword_instructions]() -> u32 {
u32 cond = 0xE;
// Have a one-in-twenty-five chance of actually having a cond.
if (RandInt(1, 25) == 1) {
cond = RandInt<u32>(0x0, 0xD);
}
return halfword_instructions[RandInt<size_t>(0, halfword_instructions.size() - 1)].Generate() | (cond << 28);
});
}
SECTION("Byte tests") {
FuzzJitArm(1, 1, 10000, [&byte_instructions]() -> u32 {
u32 cond = 0xE;
// Have a one-in-twenty-five chance of actually having a cond.
if (RandInt(1, 25) == 1) {
cond = RandInt<u32>(0x0, 0xD);
}
return byte_instructions[RandInt<size_t>(0, byte_instructions.size() - 1)].Generate() | (cond << 28);
});
}
SECTION("Mixed tests") {
FuzzJitArm(10, 10, 10000, [&]() -> u32 {
size_t selection = RandInt<size_t>(0, 3);
u32 cond = 0xE;
// Have a one-in-twenty-five chance of actually having a cond.
if (RandInt(1, 25) == 1) {
cond = RandInt<u32>(0x0, 0xD);
}
switch (selection) {
case 0:
return doubleword_instructions[RandInt<size_t>(0, doubleword_instructions.size() - 1)].Generate() | (cond << 28);
case 1:
return word_instructions[RandInt<size_t>(0, word_instructions.size() - 1)].Generate() | (cond << 28);
case 2:
return halfword_instructions[RandInt<size_t>(0, halfword_instructions.size() - 1)].Generate() | (cond << 28);
case 3:
return byte_instructions[RandInt<size_t>(0, byte_instructions.size() - 1)].Generate() | (cond << 28);
}
return 0;
});
}
SECTION("Write to PC") {
// TODO
FAIL();
}
}