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:
parent
623eda7162
commit
106937b679
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user