1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-29 16:55:59 +00:00

Add 'quick' decoding and testing.

This commit is contained in:
Thomas Harte 2022-04-21 16:05:00 -04:00
parent 45c02c31f8
commit 549e440f7c
3 changed files with 51 additions and 13 deletions

View File

@ -172,14 +172,20 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated
// ADD, SUB, MOVE, MOVEA
case OpT(Operation::ADDb): case OpT(Operation::ADDw): case OpT(Operation::ADDl):
case ADDQb: case ADDQw: case ADDQl:
case OpT(Operation::SUBb): case OpT(Operation::SUBw): case OpT(Operation::SUBl):
case SUBQb: case SUBQw: case SUBQl:
case OpT(Operation::MOVEb): case OpT(Operation::MOVEw): case OpT(Operation::MOVEl):
case OpT(Operation::MOVEAw): case OpT(Operation::MOVEAl):
case OpT(Operation::MOVEAw): case OpT(Operation::MOVEAl): {
// TODO: I'm going to need get-size-by-operation elsewhere; use that here when implemented.
constexpr bool is_byte =
op == OpT(Operation::ADDb) || op == OpT(Operation::SUBb) || op == OpT(Operation::MOVEb) ||
op == ADDQb || op == SUBQb;
switch(original.mode<0>()) {
default: break;
case AddressingMode::AddressRegisterDirect:
// TODO: I'm going to need get-size-by-operation elsewhere; use that here when implemented.
if constexpr (op != OpT(Operation::ADDb) && op != OpT(Operation::SUBb) && op != OpT(Operation::MOVEb)) {
if constexpr (!is_byte) {
break;
}
[[fallthrough]];
@ -191,7 +197,7 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated
default: return original;
case AddressingMode::AddressRegisterDirect:
if constexpr (op == OpT(Operation::MOVEAw) || op == OpT(Operation::MOVEAl)) {
if constexpr (!is_byte) {
return original;
}
[[fallthrough]];
@ -201,6 +207,7 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated
case AddressingMode::None:
return Preinstruction();
}
}
// ADDA, SUBA.
case OpT(Operation::ADDAw): case OpT(Operation::ADDAl):
@ -1061,7 +1068,11 @@ Preinstruction Predecoder<model>::decode7(uint16_t instruction) {
using Op = Operation;
// 4-134 (p238)
Decode(Op::MOVEq);
if(!(instruction & 0x100)) {
Decode(Op::MOVEq);
} else {
return Preinstruction();
}
}
template <Model model>

View File

@ -136,6 +136,28 @@ constexpr int size(Operation operation) {
}
}
template <Operation op>
constexpr int8_t quick(uint16_t instruction) {
switch(op) {
case Operation::Bccb:
case Operation::MOVEq: return int8_t(instruction);
default: {
int8_t value = (instruction >> 9) & 7;
value |= (value - 1)&8;
return value;
}
}
}
constexpr int8_t quick(Operation op, uint16_t instruction) {
if(op == Operation::MOVEq || op == Operation::Bccb) {
return quick<Operation::MOVEq>(instruction);
} else {
// ADDw is arbitrary; anything other than MOVEq will do.
return quick<Operation::ADDw>(instruction);
}
}
/// Indicates the addressing mode applicable to an operand.
///
/// Implementation notes:

View File

@ -17,7 +17,7 @@ using namespace InstructionSet::M68k;
namespace {
template <int index> NSString *operand(Preinstruction instruction) {
template <int index> NSString *operand(Preinstruction instruction, uint16_t opcode) {
switch(instruction.mode<index>()) {
default: return [NSString stringWithFormat:@"[Mode %d?]", int(instruction.mode<index>())];
@ -52,6 +52,9 @@ template <int index> NSString *operand(Preinstruction instruction) {
case AddressingMode::ImmediateData:
return @"#";
case AddressingMode::Quick:
return [NSString stringWithFormat:@"%d", quick(instruction.operation, opcode)];
}
}
@ -216,10 +219,12 @@ template <int index> NSString *operand(Preinstruction instruction) {
case Operation::ROXRl: instruction = @"ROXR.l"; break;
case Operation::ROXRm: instruction = @"ROXR.w"; break;
// case Operation::MOVEMl: instruction = @"MOVEM.l"; break;
// case Operation::MOVEMw: instruction = @"MOVEM.w"; break;
/*
TODO:
MOVEMl, MOVEMw,
MOVEPl, MOVEPw,
ANDb, ANDw, ANDl,
@ -252,17 +257,17 @@ template <int index> NSString *operand(Preinstruction instruction) {
continue;
}
NSString *const operand1 = operand<0>(found);
NSString *const operand2 = operand<1>(found);
NSString *const operand1 = operand<0>(found, uint16_t(instr));
NSString *const operand2 = operand<1>(found, uint16_t(instr));
if(operand1.length) instruction = [instruction stringByAppendingFormat:@" %@", operand1];
if(operand2.length) instruction = [instruction stringByAppendingFormat:@", %@", operand2];
// Quick decoding not yet supported. TODO.
if(found.mode<0>() == AddressingMode::Quick || found.mode<1>() == AddressingMode::Quick) {
++skipped;
continue;
}
// if(found.mode<0>() == AddressingMode::Quick || found.mode<1>() == AddressingMode::Quick) {
// ++skipped;
// continue;
// }
XCTAssertFalse(found.mode<0>() == AddressingMode::None && found.mode<1>() != AddressingMode::None, @"Decoding of %@ provided a second operand but not a first", instrName);
XCTAssertEqualObjects(instruction, expected, "%@ should decode as %@; got %@", instrName, expected, instruction);