1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-21 05:29:13 +00:00

Implement MOVEM to memory.

This commit is contained in:
Thomas Harte 2022-05-05 18:51:29 -04:00
parent 47f4bbeec6
commit d7d0a5c15e
3 changed files with 50 additions and 7 deletions

View File

@ -440,11 +440,51 @@ void Executor<model, BusHandler>::movep(Preinstruction instruction, uint32_t sou
template <Model model, typename BusHandler>
template <typename IntT>
void Executor<model, BusHandler>::movem(Preinstruction instruction, uint32_t source, uint32_t dest) {
if(instruction.mode<0>() == AddressingMode::DataRegisterDirect) {
// Move registers to memory.
// NB:
//
// "For the MC68020, MC68030, MC68040, and CPU32, if the addressing register is also
// moved to memory, the value written is the initial register value decremented by the
// size of the operation. The MC68000 and MC68010 write the initial register value
// (not decremented)."
if(instruction.mode<0>() == AddressingMode::ImmediateData) {
// Move registers to memory. This is the only permitted use of the predecrement mode,
// which reverses output order.
if(instruction.mode<1>() == AddressingMode::AddressRegisterIndirectWithPredecrement) {
} else {
// The structure of the code in the mainline part of the executor is such
// that the address register will already have been predecremented before
// reaching here, and it'll have been by two bytes per the operand size
// rather than according to the instruction size. That's not wanted, so undo it.
//
// (TODO: with the caveat that the 68020+ have different behaviour.).
registers_[8 + instruction.reg<1>()].l += 2;
uint32_t reg = registers_[8 + instruction.reg<1>()].l;
int index = 15;
while(source) {
if(source & 1) {
reg -= sizeof(IntT);
bus_handler_.template write<IntT>(reg, IntT(registers_[index].l));
}
--index;
source >>= 1;
}
registers_[8 + instruction.reg<1>()].l = reg;
return;
}
int index = 0;
while(source) {
if(source & 1) {
bus_handler_.template write<IntT>(dest, IntT(registers_[index].l));
dest += sizeof(IntT);
}
++index;
source >>= 1;
}
} else {
// Move memory to registers.
}

View File

@ -127,6 +127,10 @@ enum class DataSize {
};
/// Classifies operations by the size of their memory accesses, if any.
///
/// For any operations that don't fit the neat model of reading one or two operands,
/// then writing zero or one, the size determines the data size of the operands only,
/// not any other accesses.
constexpr DataSize size(Operation operation) {
switch(operation) {
// These are given a value arbitrarily, to
@ -188,7 +192,7 @@ constexpr DataSize size(Operation operation) {
case Operation::RORw: case Operation::RORm:
case Operation::ROXLw: case Operation::ROXLm:
case Operation::ROXRw: case Operation::ROXRm:
case Operation::MOVEMw:
case Operation::MOVEMw: case Operation::MOVEMl:
case Operation::MOVEPw:
case Operation::ANDw: case Operation::EORw:
case Operation::NOTw: case Operation::ORw:
@ -217,7 +221,6 @@ constexpr DataSize size(Operation operation) {
case Operation::LSLl: case Operation::LSRl:
case Operation::ROLl: case Operation::RORl:
case Operation::ROXLl: case Operation::ROXRl:
case Operation::MOVEMl:
case Operation::MOVEPl:
case Operation::ANDl: case Operation::EORl:
case Operation::NOTl: case Operation::ORl:

View File

@ -72,8 +72,8 @@
- (void)setUp {
// To limit tests run to a subset of files and/or of tests, uncomment and fill in below.
_fileSet = [NSSet setWithArray:@[@"move.json"]];
// _testSet = [NSSet setWithArray:@[@"MOVE[A] 0148"]];
_fileSet = [NSSet setWithArray:@[@"movem.json"]];
// _testSet = [NSSet setWithArray:@[@"MOVEM 0060 (0)"]];
// _fileSet = [NSSet setWithArray:@[@"jmp_jsr.json"]];
// _testSet = [NSSet setWithArray:@[@"CHK 41a8"]];
}