mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-05 21:32:55 +00:00
Add 'quick' decoding and testing.
This commit is contained in:
parent
45c02c31f8
commit
549e440f7c
@ -172,14 +172,20 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated
|
|||||||
|
|
||||||
// ADD, SUB, MOVE, MOVEA
|
// ADD, SUB, MOVE, MOVEA
|
||||||
case OpT(Operation::ADDb): case OpT(Operation::ADDw): case OpT(Operation::ADDl):
|
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 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::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>()) {
|
switch(original.mode<0>()) {
|
||||||
default: break;
|
default: break;
|
||||||
case AddressingMode::AddressRegisterDirect:
|
case AddressingMode::AddressRegisterDirect:
|
||||||
// TODO: I'm going to need get-size-by-operation elsewhere; use that here when implemented.
|
if constexpr (!is_byte) {
|
||||||
if constexpr (op != OpT(Operation::ADDb) && op != OpT(Operation::SUBb) && op != OpT(Operation::MOVEb)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
@ -191,7 +197,7 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated
|
|||||||
default: return original;
|
default: return original;
|
||||||
|
|
||||||
case AddressingMode::AddressRegisterDirect:
|
case AddressingMode::AddressRegisterDirect:
|
||||||
if constexpr (op == OpT(Operation::MOVEAw) || op == OpT(Operation::MOVEAl)) {
|
if constexpr (!is_byte) {
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
@ -201,6 +207,7 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated
|
|||||||
case AddressingMode::None:
|
case AddressingMode::None:
|
||||||
return Preinstruction();
|
return Preinstruction();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ADDA, SUBA.
|
// ADDA, SUBA.
|
||||||
case OpT(Operation::ADDAw): case OpT(Operation::ADDAl):
|
case OpT(Operation::ADDAw): case OpT(Operation::ADDAl):
|
||||||
@ -1061,7 +1068,11 @@ Preinstruction Predecoder<model>::decode7(uint16_t instruction) {
|
|||||||
using Op = Operation;
|
using Op = Operation;
|
||||||
|
|
||||||
// 4-134 (p238)
|
// 4-134 (p238)
|
||||||
Decode(Op::MOVEq);
|
if(!(instruction & 0x100)) {
|
||||||
|
Decode(Op::MOVEq);
|
||||||
|
} else {
|
||||||
|
return Preinstruction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <Model model>
|
template <Model model>
|
||||||
|
@ -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.
|
/// Indicates the addressing mode applicable to an operand.
|
||||||
///
|
///
|
||||||
/// Implementation notes:
|
/// Implementation notes:
|
||||||
|
@ -17,7 +17,7 @@ using namespace InstructionSet::M68k;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template <int index> NSString *operand(Preinstruction instruction) {
|
template <int index> NSString *operand(Preinstruction instruction, uint16_t opcode) {
|
||||||
switch(instruction.mode<index>()) {
|
switch(instruction.mode<index>()) {
|
||||||
default: return [NSString stringWithFormat:@"[Mode %d?]", int(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:
|
case AddressingMode::ImmediateData:
|
||||||
return @"#";
|
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::ROXRl: instruction = @"ROXR.l"; break;
|
||||||
case Operation::ROXRm: instruction = @"ROXR.w"; break;
|
case Operation::ROXRm: instruction = @"ROXR.w"; break;
|
||||||
|
|
||||||
|
// case Operation::MOVEMl: instruction = @"MOVEM.l"; break;
|
||||||
|
// case Operation::MOVEMw: instruction = @"MOVEM.w"; break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
MOVEMl, MOVEMw,
|
|
||||||
MOVEPl, MOVEPw,
|
MOVEPl, MOVEPw,
|
||||||
|
|
||||||
ANDb, ANDw, ANDl,
|
ANDb, ANDw, ANDl,
|
||||||
@ -252,17 +257,17 @@ template <int index> NSString *operand(Preinstruction instruction) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *const operand1 = operand<0>(found);
|
NSString *const operand1 = operand<0>(found, uint16_t(instr));
|
||||||
NSString *const operand2 = operand<1>(found);
|
NSString *const operand2 = operand<1>(found, uint16_t(instr));
|
||||||
|
|
||||||
if(operand1.length) instruction = [instruction stringByAppendingFormat:@" %@", operand1];
|
if(operand1.length) instruction = [instruction stringByAppendingFormat:@" %@", operand1];
|
||||||
if(operand2.length) instruction = [instruction stringByAppendingFormat:@", %@", operand2];
|
if(operand2.length) instruction = [instruction stringByAppendingFormat:@", %@", operand2];
|
||||||
|
|
||||||
// Quick decoding not yet supported. TODO.
|
// Quick decoding not yet supported. TODO.
|
||||||
if(found.mode<0>() == AddressingMode::Quick || found.mode<1>() == AddressingMode::Quick) {
|
// if(found.mode<0>() == AddressingMode::Quick || found.mode<1>() == AddressingMode::Quick) {
|
||||||
++skipped;
|
// ++skipped;
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
|
|
||||||
XCTAssertFalse(found.mode<0>() == AddressingMode::None && found.mode<1>() != AddressingMode::None, @"Decoding of %@ provided a second operand but not a first", instrName);
|
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);
|
XCTAssertEqualObjects(instruction, expected, "%@ should decode as %@; got %@", instrName, expected, instruction);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user