Last active
July 31, 2019 23:52
-
-
Save SiD3W4y/7f13922073a7c4470e3ab5704455d83d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
union ARMOperand { | |
uint8_t reg; | |
int32_t immediate; | |
}; | |
struct ARMInstructionInfo { | |
uint32_t opcode; | |
union ARMOperand op1; | |
union ARMOperand op2; | |
union ARMOperand op3; | |
}; | |
enum { | |
ARM_SP = 13, | |
ARM_LR = 14, | |
ARM_PC = 15 | |
}; | |
void BL1Decode(uint16_t opcode, struct ARMInstructionInfo* info) { | |
int16_t immediate = (opcode & 0x07FF) << 5; | |
info->op1.reg = ARM_LR; | |
info->op2.reg = ARM_PC; | |
info->op3.immediate = (((int32_t) immediate) << 7); | |
} | |
void BL2Decode(uint16_t opcode, struct ARMInstructionInfo* info) { | |
info->op1.reg = ARM_PC; | |
info->op2.reg = ARM_LR; | |
info->op3.immediate = (opcode & 0x07FF) << 1; | |
} | |
void faultyCombine(struct ARMInstructionInfo* info1, struct ARMInstructionInfo* info2, struct ARMInstructionInfo* out) { | |
if (info1->op1.reg != ARM_LR || info1->op2.reg != ARM_PC) { | |
//return false; | |
} | |
if (info2->op1.reg != ARM_PC || info2->op2.reg != ARM_LR) { | |
//return false; | |
} | |
out->op1.immediate = info1->op3.immediate | info2->op3.immediate; | |
/* Skipped other variables */ | |
//return true; | |
} | |
void fixedCombine(struct ARMInstructionInfo* info1, struct ARMInstructionInfo* info2, struct ARMInstructionInfo* out) { | |
if (info1->op1.reg != ARM_LR || info1->op2.reg != ARM_PC) { | |
//return false; | |
} | |
if (info2->op1.reg != ARM_PC || info2->op2.reg != ARM_LR) { | |
//return false; | |
} | |
uint32_t S = (uint32_t)(info1->op3.immediate) >> 31; | |
uint32_t I1 = ((info2->opcode >> 13) & 1) ^ S ^ 1; | |
uint32_t I2 = ((info2->opcode >> 11) & 1) ^ S ^ 1; | |
out->op1.immediate = info1->op3.immediate | info2->op3.immediate; | |
out->op1.immediate = (out->op1.immediate & 0xff3fffff) | (I2 << 22) | (I1 << 23); | |
/* Skipped other variables */ | |
//return true; | |
} | |
struct TestCase { | |
uint32_t opcode; | |
int32_t expected; | |
}; | |
struct TestCase testCases[] = { | |
{ .opcode = 0xf8fef000, .expected = 0x200}, | |
{ .opcode = 0xfefef7ff, .expected = -0x200}, | |
{ .opcode = 0xf810f000, .expected = 0x24}, | |
{ .opcode = 0xff05f000, .expected = 0xe0e}, | |
{ .opcode = 0xf691f183, .expected = 0x583d26}, | |
{ .opcode = 0xf16bf67c, .expected = -0x583d26}, | |
}; | |
static int testFaulty(struct TestCase testCase) { | |
struct ARMInstructionInfo info1; | |
struct ARMInstructionInfo info2; | |
struct ARMInstructionInfo out; | |
info1.opcode = testCase.opcode & 0xffff; | |
info2.opcode = testCase.opcode >> 16; | |
BL1Decode(info1.opcode, &info1); | |
BL2Decode(info2.opcode, &info2); | |
faultyCombine(&info1, &info2, &out); | |
if((out.op1.immediate + 4)!= testCase.expected) { | |
printf("faultyCombine: Expected 0x%08x but got 0x%08x\n", testCase.expected, out.op1.immediate); | |
return 0; | |
} | |
return 1; | |
} | |
static int testFixed(struct TestCase testCase) { | |
struct ARMInstructionInfo info1; | |
struct ARMInstructionInfo info2; | |
struct ARMInstructionInfo out; | |
info1.opcode = testCase.opcode & 0xffff; | |
info2.opcode = testCase.opcode >> 16; | |
BL1Decode(info1.opcode, &info1); | |
BL2Decode(info2.opcode, &info2); | |
fixedCombine(&info1, &info2, &out); | |
if((out.op1.immediate + 4) != testCase.expected) { | |
printf("fixedCombine: Expected 0x%08x but got 0x%08x\n", testCase.expected, out.op1.immediate); | |
return 0; | |
} | |
return 1; | |
} | |
int main() { | |
size_t faultyCount = 0; | |
size_t fixedCount = 0; | |
size_t testCasesCount = sizeof(testCases) / sizeof(struct TestCase); | |
for(size_t i = 0; i < testCasesCount; i++) { | |
struct TestCase c = testCases[i]; | |
testFaulty(c); | |
testFixed(c); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment