1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-17 06:29:28 +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
operator std::string() const {
return "";
switch(type) {
default: return "";
case Type::Register: return std::string("r") + std::to_string(value);
}
}
};
struct Instruction {
Condition condition;
Condition condition = Condition::AL;
enum class Operation {
AND, EOR, SUB, RSB,
ADD, ADC, SBC, RSC,
TST, TEQ, CMP, CMN,
ORR, MOV, BIC, MVN,
LDR, STR,
B, BL,
SWI,
@ -44,6 +49,7 @@ struct Instruction {
} operation = Operation::Undefined;
Operand destination, operand1, operand2;
bool sets_flags = false;
std::string to_string(uint32_t address) const {
std::ostringstream result;
@ -77,12 +83,42 @@ struct Instruction {
case Operation::MOV: result << "mov"; break;
case Operation::BIC: result << "bic"; 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) {
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();
@ -101,9 +137,29 @@ struct Disassembler {
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(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 f> void perform(Branch fields) {
constexpr BranchFlags flags(f);