1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Run into the shifts wall with LDR/STR.

This commit is contained in:
Thomas Harte 2024-03-19 12:19:49 -04:00
parent 623eda7162
commit 106937b679

View File

@ -24,18 +24,23 @@ struct Operand {
// TODO: encode shifting // TODO: encode shifting
operator std::string() const { operator std::string() const {
return ""; switch(type) {
default: return "";
case Type::Register: return std::string("r") + std::to_string(value);
}
} }
}; };
struct Instruction { struct Instruction {
Condition condition; Condition condition = Condition::AL;
enum class Operation { enum class Operation {
AND, EOR, SUB, RSB, AND, EOR, SUB, RSB,
ADD, ADC, SBC, RSC, ADD, ADC, SBC, RSC,
TST, TEQ, CMP, CMN, TST, TEQ, CMP, CMN,
ORR, MOV, BIC, MVN, ORR, MOV, BIC, MVN,
LDR, STR,
B, BL, B, BL,
SWI, SWI,
@ -44,6 +49,7 @@ struct Instruction {
} operation = Operation::Undefined; } operation = Operation::Undefined;
Operand destination, operand1, operand2; Operand destination, operand1, operand2;
bool sets_flags = false;
std::string to_string(uint32_t address) const { std::string to_string(uint32_t address) const {
std::ostringstream result; std::ostringstream result;
@ -77,12 +83,42 @@ struct Instruction {
case Operation::MOV: result << "mov"; break; case Operation::MOV: result << "mov"; break;
case Operation::BIC: result << "bic"; break; case Operation::BIC: result << "bic"; break;
case Operation::MVN: result << "mvn"; break; case Operation::MVN: result << "mvn"; break;
case Operation::LDR: result << "ldr"; break;
case Operation::STR: result << "str"; break;
} }
// If this is a branch, append the target and complete. // Append the sets-flags modifier if applicable.
if(sets_flags) result << 's';
// Possibly a condition code.
switch(condition) {
case Condition::EQ: result << "eq"; break;
case Condition::NE: result << "ne"; break;
case Condition::CS: result << "cs"; break;
case Condition::CC: result << "cc"; break;
case Condition::MI: result << "mi"; break;
case Condition::PL: result << "pl"; break;
case Condition::VS: result << "vs"; break;
case Condition::VC: result << "vc"; break;
case Condition::HI: result << "hi"; break;
case Condition::LS: result << "ls"; break;
case Condition::GE: result << "ge"; break;
case Condition::LT: result << "lt"; break;
case Condition::GT: result << "gt"; break;
case Condition::LE: result << "le"; break;
default: break;
}
// If this is a branch, append the target.
if(operation == Operation::B || operation == Operation::BL) { if(operation == Operation::B || operation == Operation::BL) {
result << " 0x" << std::hex << ((address + 8 + operand1.value) & 0x3fffffc); result << " 0x" << std::hex << ((address + 8 + operand1.value) & 0x3fffffc);
return result.str(); }
if(operation == Operation::LDR || operation == Operation::STR) {
result << ' ' << static_cast<std::string>(destination);
result << ", [" << static_cast<std::string>(operand1) << "]";
// TODO: learn how ARM shifts/etc are normally represented.
} }
return result.str(); return result.str();
@ -101,9 +137,29 @@ struct Disassembler {
return true; return true;
} }
template <Flags> void perform(DataProcessing) {} template <Flags f> void perform(DataProcessing fields) {
constexpr DataProcessingFlags flags(f);
//
instruction_.operand1.type = Operand::Type::Register;
instruction_.operand1.value = fields.operand1();
instruction_.sets_flags = flags.set_condition_codes();
}
template <Flags> void perform(Multiply) {} template <Flags> void perform(Multiply) {}
template <Flags> void perform(SingleDataTransfer) {} template <Flags f> void perform(SingleDataTransfer fields) {
constexpr SingleDataTransferFlags flags(f);
instruction_.operation =
(flags.operation() == SingleDataTransferFlags::Operation::STR) ?
Instruction::Operation::STR : Instruction::Operation::LDR;
instruction_.destination.type = Operand::Type::Register;
instruction_.destination.value = fields.destination();
instruction_.operand1.type = Operand::Type::Register;
instruction_.operand1.value = fields.base();
}
template <Flags> void perform(BlockDataTransfer) {} template <Flags> void perform(BlockDataTransfer) {}
template <Flags f> void perform(Branch fields) { template <Flags f> void perform(Branch fields) {
constexpr BranchFlags flags(f); constexpr BranchFlags flags(f);