Skip to content

Instantly share code, notes, and snippets.

@SiD3W4y
Last active July 31, 2019 23:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SiD3W4y/7f13922073a7c4470e3ab5704455d83d to your computer and use it in GitHub Desktop.
Save SiD3W4y/7f13922073a7c4470e3ab5704455d83d to your computer and use it in GitHub Desktop.
#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